# 帳票設計書 1-フォーマット済みコード

## 概要

本ドキュメントは、Prettierがソースコードをフォーマットした結果を出力する帳票「フォーマット済みコード」の設計仕様を定義する。

### 本帳票の処理概要

**業務上の目的・背景**：ソースコードの一貫したフォーマットは、コードの可読性向上、チーム開発における統一されたコーディングスタイルの維持、コードレビューの効率化において不可欠である。Prettierは「opinionated」なコードフォーマッターとして、開発者がフォーマットに関する議論に時間を費やすことなく、コードの本質的な部分に集中できる環境を提供する。本帳票は、Prettierのメイン機能であり、入力されたソースコードを解析し、定義されたルールに基づいて整形された結果を出力する。

**帳票の利用シーン**：日常的な開発作業において、コードを保存する際やコミット前のフォーマット確認、CI/CDパイプラインでの自動フォーマットチェック、エディタ・IDEとの統合によるリアルタイムフォーマットなど、多様な場面で利用される。

**主要な出力内容**：
1. フォーマット済みソースコード（インデント、改行、空白、引用符などが整形された状態）
2. カーソル位置情報（--cursor-offsetオプション使用時）

**帳票の出力タイミング**：CLIコマンド実行時にファイルパターンまたは標準入力が指定された場合に出力される。--writeオプション指定時はファイルへ直接書き込み、未指定時は標準出力へ出力される。

**帳票の利用者**：ソフトウェア開発者、DevOpsエンジニア、コードレビュアー、CI/CDシステム

## 帳票種別

テキスト出力（ソースコード）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| CLI-01 | コマンドライン | `prettier [options] [file/dir/glob ...]` | コマンド実行 |
| API-01 | JavaScript API | `prettier.format(source, options)` | 関数呼び出し |
| API-02 | JavaScript API | `prettier.formatWithCursor(source, options)` | 関数呼び出し |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（ソースコード） |
| 出力先 | 標準出力 / ファイル（--writeオプション時） |
| ファイル名 | 元ファイル名を維持（--write時） |
| 出力方法 | 標準出力 / ファイル上書き |
| 文字コード | UTF-8（BOM対応） |

### 出力固有設定

| 項目 | 内容 |
|-----|------|
| 改行コード | auto / lf / crlf / cr（--end-of-lineオプション） |
| インデント | スペース / タブ（--use-tabsオプション） |
| 行幅 | 数値指定（--print-widthオプション、デフォルト80） |

## 帳票レイアウト

### レイアウト概要

出力は入力ソースコードの構造を維持しつつ、フォーマットルールに従って整形されたテキストである。

```
┌─────────────────────────────────────┐
│         フォーマット済みコード         │
│   （入力コードと同じ構造を維持）        │
│                                     │
│   - インデント整形                   │
│   - 改行位置調整                     │
│   - 空白・引用符統一                  │
└─────────────────────────────────────┘
```

### 出力項目

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | フォーマット済みコード | 整形されたソースコード全体 | prettier.formatWithCursor戻り値.formatted | テキスト |
| 2 | カーソル位置 | フォーマット後のカーソルオフセット | prettier.formatWithCursor戻り値.cursorOffset | 標準エラー出力（数値） |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 入力ソース | ソースコード文字列またはファイル | Yes |
| パーサー指定 | 言語に対応するパーサー（自動推論可） | No |
| フォーマットオプション | printWidth, tabWidth等の設定 | No |

### 処理スキップ条件

| 条件 | 説明 |
|------|------|
| --require-pragma | @formatまたは@prettierプラグマがない場合スキップ |
| ignorePath指定 | .prettierignoreでマッチするファイルはスキップ |
| 空ファイル | 空またはホワイトスペースのみの入力は空文字列を返す |

## データフロー仕様

### 入力データ

| データ項目 | 型 | 説明 |
|-----------|-----|------|
| originalText | string | フォーマット対象のソースコード |
| options.parser | string | 使用するパーサー名 |
| options.plugins | array | 追加プラグイン |
| options.cursorOffset | number | カーソル位置（-1で無効） |
| options.rangeStart | number | フォーマット範囲開始位置 |
| options.rangeEnd | number | フォーマット範囲終了位置 |

### 出力データ

| データ項目 | 型 | 説明 |
|-----------|-----|------|
| formatted | string | フォーマット済みコード |
| cursorOffset | number | フォーマット後のカーソル位置 |
| comments | array | コメント情報（内部用） |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[入力受付] --> B[オプション正規化]
    B --> C{入力元判定}
    C -->|標準入力| D[formatStdin]
    C -->|ファイル| E[formatFiles]
    D --> F[getOptionsForFile]
    E --> F
    F --> G[format関数呼び出し]
    G --> H[prettier.formatWithCursor]
    H --> I{--writeオプション?}
    I -->|Yes| J[ファイル書き込み]
    I -->|No| K[標準出力]
    J --> L[終了]
    K --> L
```

### コアフォーマット処理フロー

```mermaid
flowchart TD
    A[formatWithCursor] --> B[normalizeFormatOptions]
    B --> C[normalizeInputAndOptions]
    C --> D{範囲指定?}
    D -->|Yes| E[formatRange]
    D -->|No| F[coreFormat]
    E --> G[結果返却]
    F --> G
    G --> H{BOM存在?}
    H -->|Yes| I[BOM付加]
    H -->|No| J[結果返却]
    I --> J
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| UndefinedParserError | パーサーが特定できない | No parser could be inferred for file | --parserオプションで明示指定 |
| SyntaxError | 構文解析エラー | {filename}: SyntaxError: {message} | ソースコードの構文を修正 |
| ConfigError | 設定値不正 | Invalid {option} value. | 設定値を修正 |
| ファイル読み取りエラー | ファイルアクセス不可 | Unable to read file "{filename}" | ファイルパーミッション確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データサイズ | 数KB〜数百KB/ファイル |
| 処理方式 | 非同期処理（async/await） |
| キャッシュ機能 | --cacheオプションで有効化可能 |

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

- 入力ソースコードはそのまま処理され、外部送信は行わない
- プラグインは信頼できるソースからのみ読み込むべき
- ファイル書き込み時は元ファイルのパーミッションを維持

## 備考

- --debug-checkオプションで冪等性（prettier(input) === prettier(prettier(input))）を検証可能
- --debug-benchmarkオプションでパフォーマンス計測可能
- カーソル位置追跡はdiffアルゴリズムを使用して計算

---

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

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

### 推奨読解順序

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

まず、フォーマット処理で受け渡されるデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.js | `src/index.js` | formatWithCursor, format関数の公開インターフェースを確認（66-78行目） |

**読解のコツ**: withPlugins関数がプラグインの遅延読み込みを実現している。引数のoptionsArgumentIndexでオプションの位置を指定。

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

CLIからの処理起点となるファイル・関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `src/cli/index.js` | run関数がCLIエントリーポイント（13-37行目） |
| 2-2 | index.js | `src/cli/index.js` | main関数でコマンド分岐（39-118行目） |

**主要処理フロー**:
1. **13-37行目**: run関数でコンテキスト初期化
2. **97-114行目**: useStdinの判定とformatStdin/formatFilesの呼び出し分岐

#### Step 3: フォーマット処理層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | format.js | `src/cli/format.js` | formatStdin関数（225-270行目）とformatFiles関数（272-504行目） |
| 3-2 | format.js | `src/cli/format.js` | format関数（102-211行目）でデバッグオプション処理と実際のフォーマット呼び出し |

**主要処理フロー**:
- **102-106行目**: debugPrintDocオプション処理
- **108-117行目**: debugPrintCommentsオプション処理
- **119-124行目**: debugPrintAstオプション処理
- **210行目**: prettier.formatWithCursor呼び出し

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | core.js | `src/main/core.js` | formatWithCursor関数（324-367行目）が本体 |
| 4-2 | core.js | `src/main/core.js` | coreFormat関数（28-182行目）で実際のフォーマット処理 |

**主要処理フロー**:
- **324-328行目**: オプション正規化とBOM/改行処理
- **344-346行目**: 範囲フォーマット呼び出し
- **355行目**: coreFormat呼び出し
- **33行目**: parseTextでAST生成
- **42行目**: printAstToDocでドキュメント生成
- **49行目**: printDocToStringで文字列化

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

```
CLI: run() [src/cli/index.js:13]
    │
    ├─ Context.init() [src/cli/context.js:29]
    │      └─ parseArgv() [src/cli/options/parse-cli-arguments.js]
    │
    └─ main() [src/cli/index.js:39]
           │
           ├─ formatStdin() [src/cli/format.js:225]
           │      │
           │      ├─ getOptionsForFile() [src/cli/options/get-options-for-file.js]
           │      │
           │      └─ format() [src/cli/format.js:102]
           │             └─ prettier.formatWithCursor() [src/index.js:66]
           │
           └─ formatFiles() [src/cli/format.js:272]
                  │
                  ├─ expandPatterns() [src/cli/expand-patterns.js]
                  │
                  └─ format() [src/cli/format.js:102]
                         └─ prettier.formatWithCursor() [src/index.js:66]
                                │
                                └─ core.formatWithCursor() [src/main/core.js:324]
                                       │
                                       ├─ normalizeFormatOptions() [src/main/normalize-format-options.js]
                                       │
                                       ├─ coreFormat() [src/main/core.js:28]
                                       │      │
                                       │      ├─ parseText() [src/main/parse.js]
                                       │      │
                                       │      ├─ printAstToDoc() [src/main/ast-to-doc.js]
                                       │      │
                                       │      └─ printDocToString() [src/document/index.js]
                                       │
                                       └─ formatRange() [src/main/core.js:184]
```

### データフロー図

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

ソースコード文字列 ───▶ normalizeInputAndOptions() ───▶ 正規化テキスト
                              │
                              ▼
                        parseText()
                              │
                              ▼
                         AST (抽象構文木)
                              │
                              ▼
                        printAstToDoc()
                              │
                              ▼
                         Doc (中間表現)
                              │
                              ▼
                        printDocToString()
                              │
                              ▼
                        formatted (整形済み文字列) ───▶ 標準出力 / ファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/cli/index.js` | ソース | CLIエントリーポイント |
| format.js | `src/cli/format.js` | ソース | CLI用フォーマット処理 |
| context.js | `src/cli/context.js` | ソース | CLI実行コンテキスト管理 |
| index.js | `src/index.js` | ソース | API公開インターフェース |
| core.js | `src/main/core.js` | ソース | コアフォーマットロジック |
| parse.js | `src/main/parse.js` | ソース | パース処理 |
| ast-to-doc.js | `src/main/ast-to-doc.js` | ソース | AST→Doc変換 |
| normalize-format-options.js | `src/main/normalize-format-options.js` | ソース | オプション正規化 |
| get-options-for-file.js | `src/cli/options/get-options-for-file.js` | ソース | ファイル別オプション取得 |
| utilities.js | `src/cli/utilities.js` | ソース | ユーティリティ関数群 |
