# 機能設計書 54-parse()

## 概要

本ドキュメントは、@vue/compiler-sfcパッケージにおけるparse()関数の処理について記述する。*.vueファイル（SFC: Single File Component）のソースコードをtemplate/script/styleの各ブロックに分離解析し、SFCDescriptorを生成するSFCコンパイルのエントリーポイントである。

### 本機能の処理概要

parse()は、Vueシングルファイルコンポーネント（.vue）のソーステキストを受け取り、テンプレート、スクリプト、スタイルの各ブロックに構造化分離するパーサーである。結果として生成されるSFCDescriptorは、後続のcompileScript()、compileTemplate()、compileStyle()による個別コンパイルの入力となる。

**業務上の目的・背景**：Vueの開発において、SFC形式はテンプレート・ロジック・スタイルを1つのファイルにまとめる標準的な記法である。parse()はこのSFCを各論理ブロックに分離し、後続のコンパイルパイプラインが各ブロックを個別に処理できるようにする基盤機能である。ViteやVue CLIのビルドツールチェーンから呼び出される。

**機能の利用シーン**：.vueファイルのビルド時に最初に呼び出される。開発時のHMR（Hot Module Replacement）においてもファイル変更検知後に再解析が実行される。

**主要な処理内容**：
1. SFCソースのキャッシュチェック（LRUキャッシュ）
2. @vue/compiler-domによるSFCモードでの構文解析
3. template/script/style/カスタムブロックの分離・分類
4. 各ブロックの属性（lang, src, scoped, module, setup等）の解析
5. ソースマップの生成
6. CSS変数（v-bind in CSS）の抽出
7. :slotted()使用検出
8. HMRリロード判定関数の生成

**関連システム・外部連携**：@vue/compiler-domのparse関数をSFCモードで使用。source-map-jsによるソースマップ生成。LRUキャッシュによるパフォーマンス最適化。

**権限による制御**：該当なし（コンパイル時処理）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | App（メイン画面） | API連携 | @vue/replコンポーネントを介したSFCファイルの解析処理 |

## 機能種別

構文解析処理（SFCパーサー）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | string | Yes | SFCのソースコード文字列 | - |
| options.filename | string | No | ファイル名（デフォルト: 'anonymous.vue'） | - |
| options.sourceMap | boolean | No | ソースマップ生成有無（デフォルト: true） | - |
| options.sourceRoot | string | No | ソースマップのルートパス（デフォルト: ''） | - |
| options.pad | boolean \| 'line' \| 'space' | No | ブロック前のパディング方式（デフォルト: false） | - |
| options.ignoreEmpty | boolean | No | 空ブロックの無視（デフォルト: true） | - |
| options.compiler | TemplateCompiler | No | カスタムコンパイラ（デフォルト: CompilerDOM） | - |
| options.templateParseOptions | ParserOptions | No | テンプレート解析オプション | - |

### 入力データソース

.vueファイルのソースコード文字列。ビルドツール（Vite、webpack等）がファイルシステムから読み込んだ内容。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| descriptor | SFCDescriptor | 解析済みSFC記述子（template, script, scriptSetup, styles, customBlocks等） |
| errors | (CompilerError \| SyntaxError)[] | 解析中に検出されたエラーの配列 |

### 出力先

SFCParseResultとして返却される。compileScript()、compileTemplate()、compileStyle()の入力となる。

## 処理フロー

### 処理シーケンス

```
1. キャッシュチェック
   └─ genCacheKeyでソースとオプションからキーを生成
   └─ parseCacheからキャッシュ済み結果を検索
   └─ ヒットすればそのまま返却

2. オプションのデフォルト値設定
   └─ sourceMap=true, filename='anonymous.vue', pad=false, ignoreEmpty=true等

3. SFCDescriptorの初期化
   └─ template=null, script=null, scriptSetup=null, styles=[], customBlocks=[]

4. compiler.parse()によるAST生成
   └─ parseMode: 'sfc'でSFCモード解析
   └─ prefixIdentifiers: true

5. ASTの子ノード走査
   └─ 空ノードのスキップ（ignoreEmpty有効時）
   └─ <template>: descriptor.templateに設定（重複チェック付き）
   └─ <script>: setup属性の有無でscript/scriptSetupに振り分け（重複チェック付き）
   └─ <style>: descriptor.stylesに追加（scoped, module属性の解析）
   └─ その他: descriptor.customBlocksに追加

6. バリデーション
   └─ template/script/scriptSetupが全て無い場合はエラー
   └─ <script setup>にsrc属性がある場合はエラー
   └─ <script setup>と<script>併用時に<script>にsrc属性がある場合はエラー

7. Pug/Jadeテンプレートのデデント処理

8. ソースマップ生成
   └─ 各ブロック（template, script, styles, customBlocks）のソースマップを生成

9. CSS変数の抽出
   └─ parseCssVarsでv-bind()使用を検出

10. :slotted()使用検出
    └─ scopedスタイルでの:slotted()使用をチェック

11. 結果のキャッシュ保存と返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: parse] --> B{キャッシュヒット?}
    B -->|Yes| C[キャッシュ結果を返却]
    B -->|No| D[SFCDescriptor初期化]
    D --> E[compiler.parse SFCモード]
    E --> F[AST子ノード走査]
    F --> G{ノードのタグ?}
    G -->|template| H[descriptor.template設定]
    G -->|script| I{setup属性?}
    G -->|style| J[descriptor.styles追加]
    G -->|その他| K[customBlocks追加]
    I -->|Yes| L[descriptor.scriptSetup設定]
    I -->|No| M[descriptor.script設定]
    H --> N[バリデーション]
    L --> N
    M --> N
    J --> N
    K --> N
    N --> O[ソースマップ生成]
    O --> P[CSS変数抽出]
    P --> Q[:slotted検出]
    Q --> R[キャッシュ保存]
    R --> S[結果返却]
    C --> T[終了]
    S --> T
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-54-01 | template単一 | `<template>`ブロックは1つのみ許可 | 2つ目の`<template>`検出時にエラー |
| BR-54-02 | script単一 | `<script>`ブロックは1つのみ許可 | 2つ目の`<script>`検出時にエラー |
| BR-54-03 | scriptSetup単一 | `<script setup>`ブロックは1つのみ許可 | 2つ目の`<script setup>`検出時にエラー |
| BR-54-04 | 最低1ブロック | template/scriptの少なくとも1つが必要 | 両方ともnullの場合にエラー |
| BR-54-05 | setup src禁止 | `<script setup>`にsrc属性は使用不可 | setup属性付きscriptにsrc属性がある場合 |
| BR-54-06 | functional非対応 | `<template functional>`はVue 3で非対応 | template要素にfunctional属性がある場合 |
| BR-54-07 | style vars非推奨 | `<style vars>`は廃止（新提案に置換） | style要素にvars属性がある場合 |

### 計算ロジック

該当なし

## データベース操作仕様

該当なし（コンパイル時処理のため、データベース操作は発生しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | SyntaxError | `<template>`が重複 | 1つの`<template>`に統一する |
| - | SyntaxError | `<script>`が重複 | 1つの`<script>`に統一する |
| - | SyntaxError | template/scriptが両方存在しない | 少なくとも1つを追加する |
| - | SyntaxError | `<script setup>`にsrc属性 | src属性を削除する |
| - | SyntaxError | `<template functional>` | functional属性を削除する |
| - | CompilerError | テンプレート構文エラー | テンプレートの構文を修正する |

### リトライ仕様

該当なし（構文エラーは即座に報告される）

## トランザクション仕様

該当なし（コンパイル時処理）

## パフォーマンス要件

- LRUキャッシュ（parseCacheMap/LRUCache）により、同一ソースの再解析を回避
- genCacheKeyでソースとオプションの組み合わせからキャッシュキーを生成

## セキュリティ考慮事項

該当なし（コンパイル時処理であり、ユーザー入力の直接処理は行わない）

## 備考

- HMRリロード判定（shouldForceReload）は、TypeScript環境でのimport使用状況変更を検出するために使用される
- Pug/Jadeテンプレートは自動デデント処理が適用される
- padオプションは、各ブロックの行番号を元のSFCファイルと一致させるために使用される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、SFC関連の型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | parse.ts | `packages/compiler-sfc/src/parse.ts` | SFCBlock、SFCTemplateBlock、SFCScriptBlock、SFCStyleBlock型定義 |
| 1-2 | parse.ts | `packages/compiler-sfc/src/parse.ts` | SFCDescriptor型定義 |
| 1-3 | parse.ts | `packages/compiler-sfc/src/parse.ts` | SFCParseOptions、SFCParseResult型定義 |

**読解のコツ**: SFCDescriptorは.vueファイル全体の構造を表し、template（1つ）、script（1つ）、scriptSetup（1つ）、styles（複数）、customBlocks（複数）のブロックを保持する。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | parse.ts | `packages/compiler-sfc/src/parse.ts` | parse()関数 |

**主要処理フロー**:
1. **107-118行目**: キャッシュチェック。genCacheKeyでキー生成後、parseCacheで既存結果を検索
2. **120-128行目**: オプションのデストラクチャリングとデフォルト値設定
3. **130-141行目**: SFCDescriptorの初期化
4. **144-151行目**: compiler.parse()をSFCモードで呼び出し

#### Step 3: ブロック分類処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | parse.ts | `packages/compiler-sfc/src/parse.ts` | ASTノード走査ループ |

**主要処理フロー**:
- **152-225行目**: ast.children.forEachループでノードをタグ名で分類
- **167-195行目**: template処理 - templateBlock生成、AST設定、functional警告
- **196-208行目**: script処理 - setup属性の有無でscript/scriptSetupに振り分け
- **209-224行目**: style処理 - scoped/module属性の解析

#### Step 4: バリデーションとポスト処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | parse.ts | `packages/compiler-sfc/src/parse.ts` | バリデーション・ソースマップ・CSS変数抽出 |

**主要処理フロー**:
- **226-252行目**: バリデーション（最低1ブロック、setup srcチェック等）
- **255-263行目**: Pug/Jadeデデント処理
- **265-282行目**: ソースマップ生成（generateSourceMap関数）
- **285行目**: CSS変数抽出（parseCssVars）
- **289-291行目**: :slotted()使用検出

#### Step 5: 補助関数

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | parse.ts | `packages/compiler-sfc/src/parse.ts` | createBlock、generateSourceMap等の補助関数 |

**主要処理フロー**:
- **314-351行目**: createBlock - ノードからSFCBlockを生成（属性解析を含む）
- **357-390行目**: generateSourceMap - SourceMapGeneratorによるソースマップ生成
- **435-457行目**: hmrShouldReload - HMR時のリロード判定

### プログラム呼び出し階層図

```
parse (エントリーポイント)
    │
    ├─ genCacheKey (キャッシュキー生成)
    ├─ parseCache.get (キャッシュ検索)
    │
    ├─ compiler.parse (SFCモード解析)
    │      └─ @vue/compiler-dom の parse()
    │
    ├─ createBlock (各ブロック生成)
    │      └─ padContent (パディング処理)
    │
    ├─ createRoot (テンプレートAST生成)
    │
    ├─ generateSourceMap (ソースマップ生成)
    │      └─ SourceMapGenerator
    │
    ├─ parseCssVars (CSS変数抽出)
    │
    ├─ dedent (Pugデデント)
    │
    └─ parseCache.set (キャッシュ保存)
```

### データフロー図

```
[入力]                   [処理]                        [出力]

.vue ソースコード  ───▶ parse()                  ───▶ SFCParseResult
                         │                            ├─ descriptor
                         ├─ compiler.parse()           │   ├─ template
                         │   → AST生成                 │   ├─ script
                         │                            │   ├─ scriptSetup
                         ├─ ブロック分類              │   ├─ styles[]
                         │   → template/script/style   │   ├─ customBlocks[]
                         │                            │   ├─ cssVars[]
                         ├─ ソースマップ生成          │   └─ slotted
                         │                            │
                         └─ CSS変数抽出              └─ errors[]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| parse.ts | `packages/compiler-sfc/src/parse.ts` | ソース | SFCパーサーのメイン実装 |
| compileScript.ts | `packages/compiler-sfc/src/compileScript.ts` | ソース | parse()の出力を入力とするスクリプトコンパイラ |
| compileTemplate.ts | `packages/compiler-sfc/src/compileTemplate.ts` | ソース | parse()の出力を入力とするテンプレートコンパイラ |
| compileStyle.ts | `packages/compiler-sfc/src/compileStyle.ts` | ソース | parse()の出力を入力とするスタイルコンパイラ |
| cssVars.ts | `packages/compiler-sfc/src/style/cssVars.ts` | ソース | CSS変数（v-bind in CSS）の抽出処理 |
| cache.ts | `packages/compiler-sfc/src/cache.ts` | ソース | LRUキャッシュの生成 |
| importUsageCheck.ts | `packages/compiler-sfc/src/script/importUsageCheck.ts` | ソース | HMR用のimport使用チェック |
