# 機能設計書 70-整合性チェック（--debug-check）

## 概要

本ドキュメントは、Prettierのコードフォーマッタにおける「整合性チェック」機能の設計を記述する。この機能は、フォーマット処理の冪等性（べきとうせい）を検証するデバッグ用機能である。

### 本機能の処理概要

**業務上の目的・背景**：正しいフォーマッタは冪等性を持つべきである。つまり、既にフォーマットされたコードを再度フォーマットしても結果は変わらないはずである。--debug-checkオプションは、この冪等性を検証し、フォーマッタのバグを検出する。また、フォーマット前後でASTが変わっていないことも検証し、意味的な整合性も確認する。

**機能の利用シーン**：
- Prettier本体の開発・テスト
- プラグイン開発時の整合性検証
- フォーマット結果のバグ調査
- リグレッションテスト
- CI/CDパイプラインでのフォーマッタ検証

**主要な処理内容**：
1. CLIから--debug-checkオプションを受け取る
2. 入力をフォーマット（1回目）
3. フォーマット結果を再度フォーマット（2回目）
4. 1回目と2回目の結果が一致するか検証（冪等性チェック）
5. 入力とフォーマット結果のASTを比較（意味的整合性チェック）
6. 不一致があれば差分を出力してエラー

**関連システム・外部連携**：
- パーサーシステム: AST生成・比較
- フォーマッタコア: format関数
- diffライブラリ: 差分表示

**権限による制御**：特になし（CLI機能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 15 | Usage - CLI | 補助機能 | CLIでの整合性チェック機能を説明 |

## 機能種別

デバッグ機能 / 検証処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --debug-check | boolean | Yes | 整合性チェックを有効化 | - |
| file | string | Yes | フォーマット対象ファイル | 存在するファイルパス |
| --parser | string | No | 使用するパーサー | 有効なパーサー名 |

### 入力データソース

- CLIコマンドライン引数
- ファイルまたは標準入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| filepath | string | 検証したファイルパス（成功時） |
| error | string | エラーメッセージと差分（失敗時） |

### 出力先

- 成功時: 標準出力にファイルパス
- 失敗時: 標準エラー出力にエラーメッセージ

## 処理フロー

### 処理シーケンス

```
1. CLIでdebugCheckオプションを検出
   └─ cli-options.evaluate.jsで定義
2. format関数内でdebugCheck分岐
3. 1回目のフォーマット（pp = format(input)）
4. 2回目のフォーマット（pppp = format(pp)）
5. 冪等性チェック
   └─ pp !== ppppの場合、DebugErrorをスロー
   └─ 差分を表示
6. ASTチェック
   └─ ast = parse(input, {massage: true})
   └─ past = parse(pp, {massage: true})
   └─ ast !== pastの場合、DebugErrorをスロー
   └─ AST差分と入力差分を表示
7. 成功時、ファイルパスを返却
```

### フローチャート

```mermaid
flowchart TD
    A[CLI実行] --> B{debugCheck?}
    B -->|No| C[通常フォーマット処理]
    B -->|Yes| D[pp = format input]
    D --> E[pppp = format pp]
    E --> F{pp === pppp?}
    F -->|No| G[DebugError: 冪等性エラー]
    G --> H[diff pp, pppp を出力]
    F -->|Yes| I[ast = parse input, massage]
    I --> J[past = parse pp, massage]
    J --> K{ast === past?}
    K -->|No| L[DebugError: AST不整合]
    L --> M[AST差分を出力]
    K -->|Yes| N[成功: filepath返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-70-01 | 冪等性検証 | format(format(x)) === format(x) | 常時 |
| BR-70-02 | AST整合性 | parse(x) === parse(format(x))（massage後） | 常時 |
| BR-70-03 | AST差分サイズ制限 | 2MB超のAST差分は表示しない | 大きなファイルの場合 |
| BR-70-04 | massageオプション | AST比較前にmassageで正規化 | 不要な差異を除去 |

### 計算ロジック

検証の流れ:
1. pp = prettier.format(input, opt)
2. pppp = prettier.format(pp, opt)
3. if (pp !== pppp) → 冪等性エラー
4. ast = prettier.__debug.parse(input, opt, {massage: true})
5. past = prettier.__debug.parse(pp, opt, {massage: true})
6. if (ast !== past) → AST不整合エラー

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

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

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

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | DebugError | 冪等性違反 | フォーマッタのバグを調査 |
| - | DebugError | AST不整合 | フォーマッタのバグを調査 |
| - | パースエラー | ソースコードの構文エラー | エラーメッセージを出力 |

### リトライ仕様

該当なし

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

該当なし（データベース操作なし）

## パフォーマンス要件

- フォーマットを2回、パースを2回実行するため、通常の約4倍の処理時間
- 大きなファイルではAST比較に時間がかかる

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

- 特別なセキュリティ要件なし
- エラー出力にはソースコードの差分が含まれる

## 備考

- このオプションはデバッグ目的であり、通常の使用では必要ない
- DebugErrorクラスはformat.js内で定義されている
- massageオプションはASTから不要なプロパティを除去し、比較を容易にする

---

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

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

### 推奨読解順序

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

CLIオプションの定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cli-options.evaluate.js | `src/cli/cli-options.evaluate.js` | debugCheckオプションの定義 |

**読解のコツ**: オプションはtype: "boolean"として定義。コメントに"Run the formatting once again on the formatted output, throw if different"と記載。

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

CLIのフォーマット処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | format.js | `src/cli/format.js` | format関数内のdebugCheck処理 |

**主要処理フロー**:
- **22-24行目**: DebugErrorクラスの定義
- **126-159行目**: debugCheck処理の全体

#### Step 3: 冪等性チェックを理解する

フォーマット結果の比較ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | format.js | `src/cli/format.js` | 冪等性チェック部分 |

**主要処理フロー**:
- **127-128行目**: pp（1回目フォーマット）とpppp（2回目フォーマット）
- **129-132行目**: 冪等性違反時のDebugError
- **131行目**: diff(pp, pppp)で差分を表示

#### Step 4: AST整合性チェックを理解する

ASTの比較ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | format.js | `src/cli/format.js` | AST比較部分 |

**主要処理フロー**:
- **134-139行目**: ast（入力のAST）とpast（フォーマット結果のAST）の取得
- **136-137行目**: {massage: true}オプションでAST正規化
- **143-155行目**: AST不整合時のDebugError
- **144-148行目**: AST差分サイズチェック（2MB制限）

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

```
CLI (format.js)
    │
    └─ format (format.js)
           │
           └─ context.argv.debugCheck判定
                  │
                  ├─ prettier.format (1回目)
                  │      └─ pp
                  │
                  ├─ prettier.format (2回目)
                  │      └─ pppp
                  │
                  ├─ 冪等性チェック (pp !== pppp?)
                  │      └─ DebugError + diff(pp, pppp)
                  │
                  ├─ prettier.__debug.parse (入力)
                  │      └─ {massage: true}
                  │      └─ ast
                  │
                  ├─ prettier.__debug.parse (pp)
                  │      └─ {massage: true}
                  │      └─ past
                  │
                  └─ AST整合性チェック (ast !== past?)
                         └─ DebugError + diff(ast, past)
```

### データフロー図

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

input ────────────────▶ format (1回目) ────────────────▶ pp
                            │
                            ▼
pp ───────────────────▶ format (2回目) ────────────────▶ pppp
                            │
                            ▼
                       pp === pppp?
                            │
                        ┌───┴───┐
                       Yes      No
                        │        │
                        ▼        ▼
                       continue  DebugError + diff ─────▶ stderr
                        │
                        ▼
input ────────────────▶ parse {massage} ───────────────▶ ast
                            │
                            ▼
pp ───────────────────▶ parse {massage} ───────────────▶ past
                            │
                            ▼
                       ast === past?
                            │
                        ┌───┴───┐
                       Yes      No
                        │        │
                        ▼        ▼
                       return    DebugError + diff ─────▶ stderr
                        │
                        ▼
                       {formatted: pp, filepath} ───────▶ stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cli-options.evaluate.js | `src/cli/cli-options.evaluate.js` | ソース | CLIオプション定義 |
| format.js | `src/cli/format.js` | ソース | 整合性チェック実装、DebugErrorクラス |
| core.js | `src/main/core.js` | ソース | parse関数（massage対応） |
| massage-ast.js | `src/main/massage-ast.js` | ソース | AST正規化処理 |
| index.js | `src/index.js` | ソース | format、__debug.parseの公開 |
| diff | node_modules | 外部ライブラリ | 差分表示（createTwoFilesPatch） |
