# 機能設計書 30-ASTからDoc生成（__debug.printToDoc）

## 概要

本ドキュメントは、Prettier デバッグAPIにおける`__debug.printToDoc`関数の機能設計を記述する。この関数は、ASTをPrettierの中間表現（Doc）に変換するデバッグ用APIである。

### 本機能の処理概要

**業務上の目的・背景**：Prettierはソースコードをフォーマットする際、AST→Doc→文字列という2段階の変換を行う。Docはプリンターが生成する中間表現で、行の折り返しやインデントなどのレイアウト情報を含む。本機能は、このDoc生成段階の出力を確認し、プラグイン開発やフォーマット問題の調査を可能にする。

**機能の利用シーン**：
- プラグイン開発時のプリンター動作確認
- フォーマット結果の問題調査
- Playgroundでのデバッグパネル
- Docビルダーの動作検証

**主要な処理内容**：
1. 入力テキストのパース
2. カーソル位置の特定（指定時）
3. ASTからDocへの変換（printAstToDoc）
4. Doc中間表現の返却

**関連システム・外部連携**：
- パーサープラグイン
- プリンタープラグイン
- Document Builder API

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Playground | 補助機能 | デバッグパネルでDocを表示する際に使用 |
| 16 | Usage - API | 補助機能 | APIでのデバッグDoc生成関数の使い方を説明 |

## 機能種別

変換処理 / デバッグ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| text | string | Yes | 変換するソースコード | - |
| options | object | No | Prettierオプション | - |
| options.parser | string | Yes（推論不可の場合） | 使用するパーサー | 有効なパーサー名 |
| options.plugins | array | No | 使用するプラグイン | - |
| options.cursorOffset | number | No | カーソル位置 | 0以上の整数 |

### 入力データソース

- 関数引数

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| doc | Doc | Prettierの中間表現 |

### Doc構造

Docはネストした配列とオブジェクトで構成される。主要なDoc型：

| 型 | 説明 |
|-----|------|
| string | リテラル文字列 |
| concat | Docの連結 |
| indent | インデントブロック |
| group | 折り返し候補グループ |
| line | 改行または空白 |
| softline | 条件付き改行 |
| hardline | 強制改行 |
| fill | フィル（流し込み） |
| ifBreak | 条件分岐 |

### 出力先

- 戻り値（Promise<Doc>）

**使用例**：
```javascript
import { __debug } from "prettier";

const doc = await __debug.printToDoc("const x = 1;", { parser: "babel" });
console.log(doc);
// ["const", " ", "x", " ", "=", " ", "1", ";"]
```

## 処理フロー

### 処理シーケンス

```
1. オプションの正規化
   └─ normalizeFormatOptionsで正規化

2. テキストのパース
   └─ parseTextでASTを生成

3. カーソル位置の特定（指定時）
   └─ getCursorLocationでカーソルノードを特定

4. ASTからDocへの変換
   └─ printAstToDocでDoc生成
   └─ 各ノードをプリンター関数で処理
   └─ コメントの処理

5. 結果返却
   └─ Docオブジェクトを返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[オプション正規化]
    B --> C[テキストパース]
    C --> D{cursorOffset >= 0?}
    D -->|Yes| E[カーソル位置特定]
    D -->|No| F[printAstToDoc呼び出し]
    E --> F
    F --> G[コメント処理]
    G --> H[埋め込み言語処理]
    H --> I[各ノードをプリント]
    I --> J[Doc構築]
    J --> K[Promise<Doc>]
    K --> L[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-30-1 | パーサー・プリンター対応 | パーサーに対応するプリンターが必要 | 常時 |
| BR-30-2 | コメント処理 | ASTのコメントはDocに適切に挿入 | コメントあり時 |
| BR-30-3 | 埋め込み言語 | JSX内のCSS等、埋め込み言語も処理 | 埋め込み言語あり時 |
| BR-30-4 | カーソル追跡 | cursorOffset指定時はDoc内にカーソル位置を記録 | cursorOffset >= 0時 |
| BR-30-5 | キャッシュ | 同一ノードは再計算せずキャッシュを使用 | ノード再訪問時 |

### 計算ロジック

**Doc生成**：
再帰的にASTを走査し、各ノードに対してプリンター関数を呼び出す。プリンター関数はノードタイプに応じたDocを返す。

```javascript
// プリンター関数の基本形
function print(path, options, print) {
  const node = path.node;
  // ノードタイプに応じたDoc生成
  return [node.name, " = ", print("value")];
}
```

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | UndefinedParserError | パーサーが指定されておらず推論もできない | 適切なパーサーを指定 |
| - | Error | 対応するプリンターが存在しない | プラグインを確認 |
| - | SyntaxError | 入力テキストが不正な構文 | ソースコードを修正 |

### リトライ仕様

リトライは行わない。

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

トランザクション管理は不要。

## パフォーマンス要件

- 大規模ファイルではDoc生成に時間がかかる可能性
- ノードキャッシュにより重複計算を削減

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

- 任意のコードをパース・変換するが、実行はしない
- Doc構造のみを返す

## 備考

- `__debug`プレフィックスはAPIが不安定であることを示す
- CLIの`--debug-print-doc`オプションはこの関数を内部で使用
- Docの可視化には`__debug.formatDoc`を使用

---

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

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

### 推奨読解順序

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

Doc中間表現の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | public.js | `src/document/public.js` | Docビルダー（builders）の種類 |

**読解のコツ**: `line`, `softline`, `hardline`, `indent`, `group`などの基本的なDoc型を理解する。

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

API公開の流れを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `src/index.js` | debugApis.printToDocの定義とエクスポート |

**主要処理フロー**:
- **118-126行目**: debugApisオブジェクト定義
- **122行目**: withPlugins(core.printToDoc)でラップ

#### Step 3: 本体実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | core.js | `src/main/core.js` | printToDoc関数の実装 |

**主要処理フロー**:
- **403-415行目**: printToDoc関数
- **404行目**: normalizeFormatOptionsで正規化
- **405行目**: parseTextでパース
- **407-412行目**: cursorOffset処理
- **414行目**: printAstToDoc呼び出し

#### Step 4: Doc生成ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ast-to-doc.js | `src/main/ast-to-doc.js` | printAstToDoc関数の実装 |

**主要処理フロー**:
- **33-66行目**: printAstToDoc関数
- **34行目**: prepareToPrintでAST準備
- **36-37行目**: キャッシュとAstPath初期化
- **39-40行目**: プリプリントチェック関数作成
- **42行目**: 埋め込み言語処理
- **46-53行目**: プラグインのprint関数呼び出し
- **67-77行目**: mainPrint関数（再帰処理）

#### Step 5: プリンター呼び出しを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ast-to-doc.js | `src/main/ast-to-doc.js` | callPluginPrintFunction関数 |

**主要処理フロー**:
- **104-144行目**: callPluginPrintFunction関数
- **111-112行目**: prettierIgnoreの処理
- **113-114行目**: 埋め込みDocの使用
- **116行目**: printer.print呼び出し
- **133-141行目**: コメントの印刷

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

```
src/index.js::__debug.printToDoc()
    │
    └─ withPlugins()
           │
           ├─ loadBuiltinPlugins()
           │
           ├─ loadPlugins()
           │
           └─ src/main/core.js::printToDoc()
                  │
                  ├─ normalizeFormatOptions()
                  │
                  ├─ parseText()
                  │
                  ├─ getCursorLocation() [cursorOffset >= 0時]
                  │
                  └─ src/main/ast-to-doc.js::printAstToDoc()
                         │
                         ├─ prepareToPrint()
                         │      └─ attachComments()
                         │
                         ├─ printEmbeddedLanguages()
                         │
                         └─ callPluginPrintFunction()
                                ├─ printer.print()
                                ├─ printIgnored() [prettierIgnore時]
                                └─ printComments()
```

### データフロー図

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

text (ソースコード) ────▶ オプション正規化 ───────────────▶ 正規化オプション
options ─────────────────▶│
                               ▼
                         パース ───────────────────────▶ AST
                               │
                               ▼
cursorOffset ────────────▶ カーソル位置特定 ────────────▶ cursorNode
                               │
                               ▼
                         prepareToPrint ────────────────▶ 準備済みAST
                         (コメント付与)
                               │
                               ▼
                         printEmbeddedLanguages ────────▶ 埋め込みDoc
                               │
                               ▼
AST ──────────────────────▶ printAstToDoc ──────────────▶ Doc中間表現
                         (再帰的にノードをプリント)
                               │
                               ▼
                         結果返却 ─────────────────────▶ Promise<Doc>
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| core.js | `src/main/core.js` | ソース | printToDoc関数実装 |
| ast-to-doc.js | `src/main/ast-to-doc.js` | ソース | printAstToDoc関数実装 |
| index.js | `src/index.js` | ソース | API公開エントリーポイント |
| public.js | `src/document/public.js` | ソース | Docビルダー公開 |
| parse.js | `src/main/parse.js` | ソース | パース処理 |
| get-cursor-node.js | `src/main/get-cursor-node.js` | ソース | カーソル位置特定 |
| multiparser.js | `src/main/multiparser.js` | ソース | 埋め込み言語処理 |
| comments/print.js | `src/main/comments/print.js` | ソース | コメント印刷 |
