# 機能設計書 1-コードフォーマット（format）

## 概要

本ドキュメントは、Prettierのコアフォーマット機能である`format`関数の設計について記述する。

### 本機能の処理概要

ソースコードを解析し、Prettierの規則に従って再フォーマットする機能である。最大行長（printWidth）を考慮してコードを折り返し、一貫性のあるコードスタイルを適用する。

**業務上の目的・背景**：チーム開発において、コードスタイルの統一は可読性向上とコードレビューの効率化に不可欠である。手動でのフォーマット作業を自動化することで、開発者はビジネスロジックの実装に集中でき、スタイルに関する議論を排除できる。

**機能の利用シーン**：
- エディタ保存時の自動フォーマット
- CI/CDパイプラインでのコード整形
- コミット前のpre-commitフックでの自動整形
- CLIからの一括フォーマット処理

**主要な処理内容**：
1. プラグインのロード（ビルトイン + 外部プラグイン）
2. オプションの正規化とパーサー/プリンターの解決
3. ソースコードのパース（AST生成）
4. ASTからDoc（中間表現）への変換
5. Docから最終出力文字列への変換

**関連システム・外部連携**：
- 各言語パーサー（Babel、TypeScript、PostCSS等）
- プラグインシステムを通じた外部パーサー連携
- エディタ統合API（VSCode、Vim等）

**権限による制御**：特になし。すべてのユーザーがAPIを利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Playground | 主機能 | 入力コードをリアルタイムでフォーマットする主処理 |
| 5 | About - Prettier概要 | 主機能 | Prettierの基本的なフォーマット機能の説明 |
| 16 | Usage - API | 主機能 | プログラマティックAPIでのformat関数の使い方を説明 |
| 17 | Usage - Browser | 主機能 | ブラウザ環境でのformat関数の使い方を説明 |

## 機能種別

計算処理 / テキスト変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| text | string | Yes | フォーマット対象のソースコード | 空文字列または空白のみの場合は早期リターン |
| options | object | No | フォーマットオプション | - |
| options.parser | string | No | 使用するパーサー名 | 未指定時はfilepathから推論、推論不可の場合はエラー |
| options.filepath | string | No | ファイルパス（パーサー推論用） | - |
| options.plugins | array | No | 追加プラグインの配列 | - |
| options.printWidth | number | No | 最大行長（デフォルト: 80） | 正の整数 |
| options.tabWidth | number | No | タブ幅（デフォルト: 2） | 正の整数 |
| options.useTabs | boolean | No | タブ使用（デフォルト: false） | - |
| options.endOfLine | string | No | 改行コード（デフォルト: lf） | lf/crlf/cr/auto |

### 入力データソース

- API呼び出しからの直接入力（文字列）
- CLIからのファイル読み込み

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| formatted | string | フォーマット済みのソースコード |

### 出力先

- API戻り値として文字列を返却
- CLIの場合は標準出力またはファイル書き込み

## 処理フロー

### 処理シーケンス

```
1. format関数呼び出し
   └─ formatWithCursorを内部呼び出し（cursorOffset: -1を設定）

2. プラグインロード
   └─ ビルトインプラグインと外部プラグインを並列でロード

3. オプション正規化
   └─ パーサー推論、デフォルト値適用、オプション検証

4. 入力テキストの正規化
   └─ BOM除去、改行コード正規化、インデックス調整

5. パース処理
   └─ パーサーによるAST生成（プリプロセス含む）

6. Doc生成
   └─ ASTからPrettierの中間表現（Doc）を生成

7. 文字列出力
   └─ DocをフォーマットされたソースコードへE変換

8. 後処理
   └─ BOM復元、改行コード変換
```

### フローチャート

```mermaid
flowchart TD
    A[format呼び出し] --> B[formatWithCursor呼び出し]
    B --> C[プラグインロード]
    C --> D[オプション正規化]
    D --> E{パーサー指定あり?}
    E -->|No| F{filepath指定あり?}
    F -->|No| G[UndefinedParserError]
    F -->|Yes| H[パーサー推論]
    H --> I{推論成功?}
    I -->|No| G
    I -->|Yes| J[入力正規化]
    E -->|Yes| J
    J --> K{空入力?}
    K -->|Yes| L[空文字列を返却]
    K -->|No| M[パース処理]
    M --> N[Doc生成]
    N --> O[文字列出力]
    O --> P[後処理]
    P --> Q[フォーマット結果を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 空入力処理 | 空文字列または空白のみの入力は即座に空文字列を返却 | text.trim().length === 0 |
| BR-02 | パーサー必須 | パーサーが指定されず推論もできない場合はエラー | parser未指定かつfilepath未指定または推論失敗 |
| BR-03 | BOM保持 | UTF-8 BOMは入力にあれば出力でも保持 | 入力先頭がBOM文字 |
| BR-04 | プラグマ制御 | requirePragmaオプションが有効な場合、プラグマがないファイルはフォーマットしない | options.requirePragma === true |
| BR-05 | 無視プラグマ | @noprettierまたは@noformatプラグマがある場合はフォーマットしない | options.checkIgnorePragma === true かつプラグマ存在 |

### 計算ロジック

特になし

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

### 操作別データベース影響一覧

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UndefinedParserError | 入力エラー | パーサーが指定されず推論もできない | parserオプションまたはfilepathを指定 |
| ConfigError | 設定エラー | 指定されたパーサーが見つからない | 正しいパーサー名を指定またはプラグインを追加 |
| SyntaxError | パースエラー | ソースコードの構文エラー | 入力コードの構文を修正 |

### リトライ仕様

リトライは行わない。エラー発生時は即座に例外をスロー。

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

トランザクション管理は不要（ステートレスな処理）。

## パフォーマンス要件

- 一般的なソースファイル（1000行程度）のフォーマットは100ms以内
- 大規模ファイルでも安定した線形時間での処理

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

- 入力コードの実行は行わない（静的解析のみ）
- ファイルシステムへのアクセスはCLI経由のみ
- プラグインはユーザーが明示的に指定したもののみロード

## 備考

- format関数は内部的にformatWithCursor関数を呼び出している
- カーソル位置追跡が不要な場合はformat関数を使用することを推奨

---

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

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

### 推奨読解順序

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

format関数の定義と、formatWithCursorへの委譲を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.js | `src/index.js` | format関数のエクスポートと実装 |

**主要処理フロー**:
1. **68-74行目**: format関数の定義。formatWithCursorをcursorOffset: -1で呼び出し
2. **66行目**: formatWithCursorはwithPluginsでラップされている
3. **43-64行目**: withPlugins関数がプラグインをロードしてオプションにマージ

**読解のコツ**: withPlugins関数は高階関数であり、実際の処理はラップ先の関数が行う。

#### Step 2: コアフォーマット処理を理解する

formatWithCursor関数の実際の処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | core.js | `src/main/core.js` | formatWithCursor関数の本体 |

**主要処理フロー**:
- **324-367行目**: formatWithCursor関数
  - **325-328行目**: 入力とオプションの正規化
  - **330-340行目**: 早期リターン条件（範囲エラー、プラグマチェック）
  - **344-346行目**: 範囲フォーマットの判定と実行
  - **346-356行目**: 通常フォーマット（coreFormat呼び出し）
  - **358-364行目**: BOM復元処理

#### Step 3: 入力正規化を理解する

入力テキストとオプションの前処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | core.js | `src/main/core.js` | normalizeInputAndOptions関数 |
| 3-2 | normalize-format-options.js | `src/main/normalize-format-options.js` | オプション正規化 |

**主要処理フロー**:
- **270-312行目**: normalizeInputAndOptions関数
  - BOM検出と除去
  - 改行コードの自動検出と正規化
  - CR/CRLFの正規化

#### Step 4: パース処理を理解する

ソースコードのAST変換を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | parse.js | `src/main/parse.js` | パース処理のエントリーポイント |
| 4-2 | parser-and-printer.js | `src/main/parser-and-printer.js` | パーサー解決処理 |

**主要処理フロー**:
- **4-25行目** (parse.js): parse関数
  - パーサー解決
  - プリプロセス実行
  - ASTパース
  - エラーハンドリング

#### Step 5: Doc生成と出力を理解する

ASTから最終出力への変換を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ast-to-doc.js | `src/main/ast-to-doc.js` | ASTからDoc生成 |
| 5-2 | document/index.js | `src/document/index.js` | Doc出力処理 |

**主要処理フロー**:
- **33-102行目** (ast-to-doc.js): printAstToDoc関数
  - ASTの準備
  - AstPathの生成
  - 再帰的なDoc生成

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

```
format (src/index.js:68-74)
    │
    └─ formatWithCursor (src/index.js:66)
           │
           ├─ withPlugins (src/index.js:43-64)
           │      ├─ loadBuiltinPlugins
           │      └─ loadPlugins
           │
           └─ core.formatWithCursor (src/main/core.js:324-367)
                  │
                  ├─ normalizeFormatOptions (src/main/normalize-format-options.js)
                  │      ├─ inferParser
                  │      ├─ getParserPluginByParserName
                  │      └─ initPrinter
                  │
                  ├─ normalizeInputAndOptions (src/main/core.js:270-312)
                  │
                  ├─ hasPragma / hasIgnorePragma
                  │
                  └─ coreFormat (src/main/core.js:28-182)
                         │
                         ├─ parseText (src/main/parse.js)
                         │      └─ parser.parse
                         │
                         ├─ printAstToDoc (src/main/ast-to-doc.js)
                         │      ├─ prepareToPrint
                         │      ├─ printEmbeddedLanguages
                         │      └─ callPluginPrintFunction
                         │
                         └─ printDocToString (src/document/index.js)
```

### データフロー図

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

ソースコード ───────────▶ パーサー ───────────▶ AST
    │                                              │
    │                                              ▼
オプション ───────────▶ オプション正規化 ───▶ 正規化済みオプション
                                                   │
                                                   ▼
                                        プリンター/Doc生成 ───▶ Doc
                                                                 │
                                                                 ▼
                                              printDocToString ───▶ フォーマット済み
                                                                    ソースコード
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/index.js` | ソース | 公開APIのエクスポート |
| core.js | `src/main/core.js` | ソース | コアフォーマット処理 |
| parse.js | `src/main/parse.js` | ソース | パース処理 |
| parser-and-printer.js | `src/main/parser-and-printer.js` | ソース | パーサー/プリンター解決 |
| normalize-format-options.js | `src/main/normalize-format-options.js` | ソース | オプション正規化 |
| ast-to-doc.js | `src/main/ast-to-doc.js` | ソース | ASTからDoc生成 |
| index.js | `src/document/index.js` | ソース | Document出力処理 |
| errors.js | `src/common/errors.js` | ソース | エラークラス定義 |
| end-of-line.js | `src/common/end-of-line.js` | ソース | 改行コード処理 |
