# 帳票設計書 8-Doc出力

## 概要

本ドキュメントは、Prettierの内部ドキュメント表現（Doc）を出力する帳票「Doc出力」の設計仕様を定義する。

### 本帳票の処理概要

**業務上の目的・背景**：Prettierは、ASTをフォーマット済みテキストに変換する中間段階として、独自のドキュメント表現（Doc）を使用している。このDoc構造は、改行位置の決定やインデントの計算などを行う際の重要なデータ構造である。本帳票は、この内部Doc表現を可視化し、プラグイン開発者やPrettier本体の開発者がプリンターの動作を理解・デバッグすることを可能にする。

**帳票の利用シーン**：プラグイン開発時のプリンター動作確認、フォーマット結果の問題調査、Doc DSLの学習、カスタムプリンターの検証など。

**主要な出力内容**：
1. ASTからDoc変換結果
2. Doc要素（group, indent, line等）の構造

**帳票の出力タイミング**：CLIで`--debug-print-doc`オプションを指定した際に出力される。

**帳票の利用者**：Prettier開発者、プラグイン開発者

## 帳票種別

デバッグ出力

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| CLI-01 | コマンドライン | `prettier --debug-print-doc <file>` | コマンド実行 |
| API-01 | JavaScript API | `prettier.__debug.printToDoc(text, options)` | 関数呼び出し |
| API-02 | JavaScript API | `prettier.__debug.formatDoc(doc, options)` | 関数呼び出し |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（Doc DSL形式） |
| 出力先 | 標準出力 |
| 文字コード | UTF-8 |
| フォーマット | Prettier（__js_expressionパーサー）でフォーマット |

### Doc DSL形式例

```javascript
[
  group([
    "const",
    " ",
    "foo",
    " ",
    "=",
    " ",
    group(["{", indent([line, "bar:", " ", "1"]), line, "}"]),
  ]),
  hardline,
]
```

## 帳票レイアウト

### レイアウト概要

出力はDoc DSLをJavaScript式として表現したもの。

```
┌─────────────────────────────────────┐
│              Doc DSL形式              │
├─────────────────────────────────────┤
│  [                                   │
│    group([                           │
│      "text",                         │
│      line,                           │
│      indent([...]),                  │
│    ]),                               │
│    hardline,                         │
│  ]                                   │
└─────────────────────────────────────┘
```

### 主要Doc要素

| No | 要素名 | 説明 | 形式 |
|----|-------|------|------|
| 1 | 文字列 | リテラルテキスト | `"text"` |
| 2 | line | ソフト改行（折り返し時に改行） | `line` |
| 3 | softline | 折り返し時のみ改行 | `softline` |
| 4 | hardline | 強制改行 | `hardline` |
| 5 | group | グループ化（折り返し判定単位） | `group([...])` |
| 6 | indent | インデント追加 | `indent([...])` |
| 7 | fill | 充填モード | `fill([...])` |
| 8 | ifBreak | 折り返し時の条件分岐 | `ifBreak(breakDoc, flatDoc)` |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 入力ファイル | Doc変換対象のファイル | Yes |
| --parser | 使用するパーサー | No（自動推論可） |

### 処理条件

| 条件 | 処理 |
|------|------|
| --debug-print-doc指定 | Doc出力モードに切り替え |
| Doc生成成功 | formatDoc()でフォーマットして出力 |

## データフロー仕様

### 入力データ

| データ項目 | 型 | 説明 |
|-----------|-----|------|
| input | string | 変換対象のソースコード |
| opt | object | パースオプション（parser等） |
| context.argv.debugPrintDoc | boolean | Doc出力フラグ |

### 出力データ

| データ項目 | 型 | 説明 |
|-----------|-----|------|
| doc | Doc | 内部ドキュメント表現 |
| formatted | string | フォーマット済みDoc DSL文字列 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[format関数] --> B{debugPrintDoc?}
    B -->|Yes| C[prettier.__debug.printToDoc呼び出し]
    C --> D[parseText]
    D --> E[printAstToDoc]
    E --> F[prettier.__debug.formatDoc]
    F --> G[printDocToDebug]
    G --> H[formatWithCursor(__js_expression)]
    H --> I[結果返却]
    B -->|No| J[通常フォーマット処理]
```

### Doc生成フロー

```mermaid
flowchart TD
    A[printToDoc] --> B[normalizeFormatOptions]
    B --> C[parseText]
    C --> D{cursorOffset >= 0?}
    D -->|Yes| E[getCursorLocation]
    D -->|No| F[printAstToDoc]
    E --> F
    F --> G[printer.print呼び出し]
    G --> H[Doc返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| SyntaxError | 構文エラー | {filename}: SyntaxError: {message} | ソースコード修正 |
| プリンターエラー | print関数エラー | 内部エラー | プラグイン確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 処理方式 | 非同期処理（async/await） |
| 出力サイズ | ソースコードサイズの数倍程度 |

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

- Doc表現にはソースコードの構造情報が含まれる
- デバッグ目的のため、プロダクション環境での使用は非推奨

## 備考

- Doc DSLは内部APIであり、バージョン間で変更される可能性がある
- formatDocは`__js_expression`パーサーを使用してJavaScript式としてフォーマット
- 出力末尾に改行が自動付加される

---

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

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

### 推奨読解順序

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

まず、Doc構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | public.js | `src/document/public.js` | Doc要素のexport |
| 1-2 | builders.js | `src/document/builders.js` | Doc要素の定義 |

**読解のコツ**: Docは配列、文字列、オブジェクト（type付き）で構成される再帰的なデータ構造。

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

Doc出力のトリガーを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | format.js | `src/cli/format.js` | debugPrintDoc処理（103-106行目） |

**主要処理フロー**:
1. **103行目**: debugPrintDoc判定
2. **104行目**: prettier.__debug.printToDoc呼び出し
3. **105行目**: formatDoc呼び出しと改行付加

#### Step 3: Doc生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | core.js | `src/main/core.js` | printToDoc関数（403-415行目） |
| 3-2 | ast-to-doc.js | `src/main/ast-to-doc.js` | printAstToDoc関数 |

**主要処理フロー**:
- **404行目**: オプション正規化
- **405行目**: parseText呼び出し
- **407-412行目**: カーソル位置処理
- **414行目**: printAstToDoc呼び出し

#### Step 4: Doc整形処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | core.js | `src/main/core.js` | formatDoc関数（393-401行目） |
| 4-2 | debug.js | `src/document/debug.js` | printDocToDebug関数 |

**主要処理フロー**:
- **394行目**: printDocToDebugでDoc DSL文字列化
- **395-399行目**: formatWithCursorで整形

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

```
CLI: format() [src/cli/format.js:102]
    │
    └─ (--debug-print-doc時)
           │
           ├─ prettier.__debug.printToDoc() [src/index.js:122]
           │      │
           │      └─ core.printToDoc() [src/main/core.js:403]
           │             │
           │             ├─ normalizeFormatOptions()
           │             │
           │             ├─ parseText() [src/main/parse.js]
           │             │
           │             ├─ getCursorLocation() [src/main/get-cursor-node.js]
           │             │
           │             └─ printAstToDoc() [src/main/ast-to-doc.js]
           │                    │
           │                    └─ printer.print()
           │
           └─ prettier.__debug.formatDoc() [src/index.js:121]
                  │
                  └─ core.formatDoc() [src/main/core.js:393]
                         │
                         ├─ printDocToDebug() [src/document/debug.js]
                         │
                         └─ formatWithCursor(__js_expression)
```

### データフロー図

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

ソースコード ──────────▶ parseText()
                              │
                              ▼
                           AST
                              │
                              ▼
                    printAstToDoc()
                              │
                              ▼
                           Doc
                              │
                              ▼
                    printDocToDebug()
                              │
                              ▼
                    Doc DSL文字列
                              │
                              ▼
                    formatWithCursor(__js_expression)
                              │
                              ▼
                    整形済みDoc DSL ──────────▶ 標準出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| format.js | `src/cli/format.js` | ソース | debugPrintDoc処理 |
| index.js | `src/index.js` | ソース | __debug.printToDoc, formatDoc export |
| core.js | `src/main/core.js` | ソース | printToDoc, formatDoc関数 |
| ast-to-doc.js | `src/main/ast-to-doc.js` | ソース | printAstToDoc関数 |
| debug.js | `src/document/debug.js` | ソース | printDocToDebug関数 |
| builders.js | `src/document/builders.js` | ソース | Doc要素定義 |
| public.js | `src/document/public.js` | ソース | Doc要素export |
