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

## はじめに

このガイドラインは、Prettierのコードベースを効率的に理解するための手引きです。
JavaScript/TypeScriptに精通していないエンジニアでも、段階的に学習できるよう構成されています。

**対象読者:**
- プロジェクトに新規参画するエンジニア
- 他言語からの経験者
- コードレビューを行う担当者

**Prettierとは:**
Prettierは、コードを解析し、独自のルールで再整形する「opinionated（自己主張の強い）コードフォーマッター」です。JavaScript、TypeScript、CSS、HTML、Markdown、YAMLなど多数の言語をサポートしています。

---

## 1. 言語基礎

> このセクションでは、JavaScript/TypeScriptの基本構文と概念を解説します。

### 1.1 プログラム構造

PrettierはES Modules形式のJavaScriptで記述されています。ファイルの先頭でインポート、末尾でエクスポートを行います。

```javascript
// ファイル: src/index.js:8-12
import { createTwoFilesPatch } from "diff";
import fastGlob from "fast-glob";
import { closestMatch as closetLevenshteinMatch } from "leven";
import picocolors from "picocolors";
import * as vnopts from "vnopts";
```

**解説:**
- `import { name } from "module"` - 名前付きエクスポートをインポート
- `import name from "module"` - デフォルトエクスポートをインポート
- `import * as name from "module"` - 全エクスポートを名前空間としてインポート
- `as` キーワードでエイリアス（別名）を付けられる

### 1.2 データ型と変数

JavaScriptには以下の主要なデータ型があります。

```javascript
// ファイル: src/main/core.js:24
const BOM = "\uFEFF";  // 文字列リテラル
const CURSOR = Symbol("cursor");  // シンボル型

// ファイル: src/main/ast-to-doc.js:36-37
const cache = new Map();  // Map型（キーと値のペア）
const path = new AstPath(ast);  // オブジェクト
```

**変数宣言:**
- `const` - 再代入不可の定数（推奨）
- `let` - 再代入可能な変数
- `var` - 古い形式（非推奨）

### 1.3 制御構造

```javascript
// ファイル: src/main/core.js:28-31
// 条件分岐
if (!originalText || originalText.trim().length === 0) {
  return { formatted: "", cursorOffset: -1, comments: [] };
}

// ファイル: src/language-js/print/index.js:23-34
// 繰り返し処理
for (const printer of [
  printAngular,
  printJsx,
  printFlow,
  printTypescript,
  printEstree,
]) {
  const doc = printer(path, options, print, args);
  if (doc !== undefined) {
    return doc;
  }
}
```

**解説:**
- `for...of` - イテラブル（配列など）の各要素をループ
- `for...in` - オブジェクトのプロパティキーをループ
- `&&` と `||` - 短絡評価（条件付き実行に使用）

### 1.4 関数/メソッド定義

```javascript
// 通常の関数宣言
// ファイル: src/main/core.js:28
async function coreFormat(originalText, opts, addAlignmentSize = 0) {
  // ...
}

// アロー関数
// ファイル: src/index.js:68-74
async function format(text, options) {
  const { formatted } = await formatWithCursor(text, {
    ...options,
    cursorOffset: -1,
  });
  return formatted;
}

// 高階関数（関数を返す関数）
// ファイル: src/index.js:43-64
function withPlugins(
  fn,
  optionsArgumentIndex = 1,
) {
  return async (...args) => {
    // ...
    return fn(...args);
  };
}
```

**解説:**
- `async/await` - 非同期処理を同期的に記述するパターン
- `...args` - スプレッド構文（残余引数を配列として受け取る）
- `= 0` - デフォルト引数値
- 高階関数は関数の再利用性を高める重要なパターン

### 1.5 モジュール/インポート

```javascript
// 名前付きエクスポート
// ファイル: src/main/core.js:424-431
export {
  formatAst,
  formatDoc,
  formatWithCursor,
  parse,
  printDocToString,
  printToDoc,
};

// デフォルトエクスポート
// ファイル: src/common/ast-path.js:279
export default AstPath;

// 再エクスポート
// ファイル: src/index.js:139-142
export { default as getFileInfo } from "./common/get-file-info.js";
export * as doc from "./document/public.js";
export { default as version } from "./main/version.evaluate.js";
export * as util from "./utilities/public.js";
```

**パス規則:**
- `./` で始まる - 相対パス（同じプロジェクト内）
- `/` や `../` - 親ディレクトリへの参照
- パッケージ名のみ - node_modulesからのインポート

---

## 2. プロジェクト固有の概念

> このセクションでは、Prettier特有の概念を解説します。

### 2.1 Intermediate Representation (IR) / Document

Prettierの核心概念は「IR（中間表現）」または「Document」と呼ばれるデータ構造です。これは、コードをどのように整形すべきかを表現する抽象的なデータです。

```javascript
// ファイル: src/document/builders/index.js:1-48
// Document型の定義
/**
@typedef {
  | string
  | Align
  | BreakParent
  | Cursor
  | Fill
  | Group
  | IfBreak
  | Indent
  | IndentIfBreak
  | Label
  | Lines
  | LineSuffix
  | LineSuffixBoundary
  | Trim
} _DocUnit
@typedef {readonly Doc[]} _DocArray
@typedef {_DocUnit | _DocArray} Doc
*/
```

**主要なDocument Builder:**
- `group` - 要素をグループ化し、改行の有無を制御
- `indent` - インデントを追加
- `softline` - グループが展開された場合のみ改行
- `hardline` - 必ず改行
- `fill` - テキストを幅に合わせて埋める

### 2.2 AstPath（AST走査）

AstPathはASTを走査するためのスタックベースのデータ構造です。

```javascript
// ファイル: src/common/ast-path.js:1-30
class AstPath {
  constructor(value) {
    this.stack = [value];
  }

  get key() { /* ... */ }
  get index() { /* ... */ }
  get node() {
    return this.stack.at(-1);
  }
  get parent() {
    return this.getNode(1);
  }
  // ...
}
```

**主要なプロパティ/メソッド:**
- `node` - 現在のノード
- `parent` - 親ノード
- `call(callback, ...names)` - 子ノードを一時的に走査
- `map(callback, ...names)` - 子ノード配列を変換

### 2.3 Parser と Printer

Prettierは言語ごとにParserとPrinterを持っています。

```javascript
// ファイル: src/main/parse.js:4-25
async function parse(originalText, options) {
  const parser = await resolveParser(options);
  const text = parser.preprocess
    ? await parser.preprocess(originalText, options)
    : originalText;
  options.originalText = text;

  let ast;
  try {
    ast = await parser.parse(text, options, options);
  } catch (error) {
    handleParseError(error, originalText);
  }

  return { text, ast };
}
```

**処理フロー:**
1. Parser: ソースコード -> AST
2. Printer: AST -> Document (IR)
3. Printer: Document -> フォーマット済みコード

---

## 3. 命名規則

> このセクションでは、プロジェクト全体で使用される命名規則を解説します。

### 3.1 ファイル・ディレクトリ命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `language-*` | 言語固有の処理 | `language-js`, `language-css`, `language-html` |
| `*.evaluate.js` | ビルド時に評価されるファイル | `version.evaluate.js`, `languages.evaluate.js` |
| `*.d.ts` | TypeScript型定義ファイル | `index.d.ts`, `public.d.ts` |
| `index.js` | ディレクトリのエントリーポイント | `src/index.js`, `src/cli/index.js` |
| kebab-case | 一般的なファイル名 | `ast-to-doc.js`, `resolve-config.js` |

### 3.2 クラス・関数・変数命名

| プレフィックス/サフィックス | 意味 | 例 |
|---------------------------|------|-----|
| `print*` | 特定のASTノードをDocumentに変換 | `printEstree`, `printJsx`, `printArray` |
| `is*` | 真偽値を返す述語関数 | `isLiteral`, `isMethod`, `isIgnored` |
| `has*` | 存在確認の述語関数 | `hasComment`, `hasNewline`, `hasPragma` |
| `get*` | 値を取得する関数 | `getNode`, `getFileInfo`, `getSupportInfo` |
| `create*` | ファクトリ関数 | `createIsIgnoredFunction`, `createTypeCheckFunction` |
| `resolve*` | 解決・取得処理 | `resolveConfig`, `resolveParser` |
| `normalize*` | 正規化処理 | `normalizeOptions`, `normalizeEndOfLine` |

### 3.3 定数命名

```javascript
// ファイル: src/document/builders/types.js
// 大文字スネークケースでDocument型を定義
export const DOC_TYPE_ALIGN = "align";
export const DOC_TYPE_ARRAY = "array";
export const DOC_TYPE_BREAK_PARENT = "break-parent";
export const DOC_TYPE_GROUP = "group";
// ...
```

---

## 4. ディレクトリ構造

> このセクションでは、プロジェクトのディレクトリ構造を解説します。

```
prettier-main/
├── bin/                    # CLIエントリーポイント
│   └── prettier.cjs        # メインCLIスクリプト
├── src/                    # ソースコード
│   ├── index.js            # API エントリーポイント
│   ├── standalone.js       # ブラウザ向けスタンドアロン版
│   ├── cli/                # CLI関連
│   ├── common/             # 共通ユーティリティ
│   ├── config/             # 設定ファイル解析
│   ├── document/           # Document (IR) システム
│   ├── main/               # コアフォーマッティングロジック
│   ├── plugins/            # プラグインローダー
│   ├── language-*/         # 言語別処理
│   ├── universal/          # ブラウザ/Node.js共通コード
│   └── utilities/          # ユーティリティ関数
├── tests/                  # テストコード
├── scripts/                # ビルド・リリーススクリプト
├── website/                # ドキュメントサイト
└── packages/               # サブパッケージ
```

### 各ディレクトリの役割

| ディレクトリ | 役割 | 主要ファイル |
|-------------|------|-------------|
| `src/main/` | フォーマッティングのコアロジック | `core.js`, `ast-to-doc.js`, `parse.js` |
| `src/document/` | Document IR の定義とビルダー | `builders/`, `printer/`, `utilities/` |
| `src/language-js/` | JavaScript/TypeScript処理 | `print/`, `parse/`, `comments/` |
| `src/language-css/` | CSS/SCSS/Less処理 | `print/`, `parse/` |
| `src/language-html/` | HTML/Vue/Angular処理 | `print/`, `parse/` |
| `src/cli/` | CLIオプション解析、実行 | `index.js`, `format.js`, `options/` |
| `src/config/` | 設定ファイルの読み込み・解析 | `resolve-config.js`, `prettier-config/` |
| `src/utilities/` | 汎用ユーティリティ関数 | `get-string-width.js`, `ignore.js` |

---

## 5. アーキテクチャ

> このセクションでは、プロジェクトのアーキテクチャパターンを解説します。

### 5.1 全体アーキテクチャ

Prettierは**パイプラインアーキテクチャ**を採用しています。ソースコードは一連の変換ステップを経て、フォーマット済みコードになります。

```
┌─────────────────────────────────────────────────────────────────────┐
│                        Prettier Pipeline                             │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  [Source Code]                                                       │
│       │                                                              │
│       ▼                                                              │
│  ┌─────────┐     ┌─────────────┐     ┌──────────────┐              │
│  │ Parser  │ --> │     AST     │ --> │   Printer    │              │
│  └─────────┘     └─────────────┘     └──────────────┘              │
│                                             │                        │
│                                             ▼                        │
│                                      ┌─────────────┐                │
│                                      │  Document   │                │
│                                      │    (IR)     │                │
│                                      └─────────────┘                │
│                                             │                        │
│                                             ▼                        │
│                                  ┌──────────────────┐               │
│                                  │ printDocToString │               │
│                                  └──────────────────┘               │
│                                             │                        │
│                                             ▼                        │
│                                    [Formatted Code]                  │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘
```

### 5.2 レイヤー構成

| レイヤー | 責務 | 代表的なファイル |
|---------|------|-----------------|
| API層 | 外部インターフェース提供 | `src/index.js`, `src/standalone.js` |
| CLI層 | コマンドライン処理 | `src/cli/index.js`, `src/cli/format.js` |
| Core層 | フォーマッティングロジック | `src/main/core.js`, `src/main/ast-to-doc.js` |
| Document層 | IR定義・操作 | `src/document/builders/`, `src/document/printer/` |
| Language層 | 言語固有処理 | `src/language-js/`, `src/language-css/` |
| Config層 | 設定解析 | `src/config/resolve-config.js` |
| Utility層 | 共通処理 | `src/utilities/`, `src/common/` |

### 5.3 データフロー

1. **入力**: ソースコード + オプション
2. **Parser選択**: オプションまたはファイル拡張子からParserを特定
3. **解析**: Parser がソースコードをASTに変換
4. **前処理**: ASTにコメントをアタッチ、プラグインによる前処理
5. **Document生成**: Printer がASTをDocument IRに変換
6. **文字列化**: Document を printDocToString で文字列に変換
7. **後処理**: BOM追加、改行コード正規化など
8. **出力**: フォーマット済みコード

---

## 6. 主要コンポーネント

> このセクションでは、主要なコンポーネントとその連携を解説します。

### 6.1 エントリーポイント

**API エントリーポイント:**
```javascript
// ファイル: src/index.js:128-142
export {
  debugApis as __debug,
  sharedWithCli as __internal,
  check,
  clearCache as clearConfigCache,
  format,
  formatWithCursor,
  getSupportInfo,
  resolveConfig,
  resolveConfigFile,
};
export { default as getFileInfo } from "./common/get-file-info.js";
export * as doc from "./document/public.js";
export { default as version } from "./main/version.evaluate.js";
export * as util from "./utilities/public.js";
```

**CLI エントリーポイント:**
```javascript
// ファイル: bin/prettier.cjs:30-32
promise = dynamicImport("../src/cli/index.js").then(function runCli(cli) {
  return cli.run();
});
```

### 6.2 コアフォーマッティング

```javascript
// ファイル: src/main/core.js:324-367
async function formatWithCursor(originalText, originalOptions) {
  let { hasBOM, text, options } = normalizeInputAndOptions(
    originalText,
    await normalizeFormatOptions(originalOptions),
  );

  // プラグマチェック、範囲チェックなど
  if (
    (options.rangeStart >= options.rangeEnd && text !== "") ||
    (options.requirePragma && !(await hasPragma(text, options))) ||
    (options.checkIgnorePragma && (await hasIgnorePragma(text, options)))
  ) {
    return {
      formatted: originalText,
      cursorOffset: originalOptions.cursorOffset,
      comments: [],
    };
  }

  let result;
  if (options.rangeStart > 0 || options.rangeEnd < text.length) {
    result = await formatRange(text, options);
  } else {
    result = await coreFormat(text, options);
  }

  // BOM処理
  if (hasBOM) {
    result.formatted = BOM + result.formatted;
    if (result.cursorOffset >= 0) {
      result.cursorOffset++;
    }
  }

  return result;
}
```

### 6.3 AST to Document 変換

```javascript
// ファイル: src/main/ast-to-doc.js:33-66
async function printAstToDoc(ast, options) {
  ({ ast } = await prepareToPrint(ast, options));

  const cache = new Map();
  const path = new AstPath(ast);

  const ensurePrintingNode = createPrintPreCheckFunction(options);
  const embeds = new Map();

  await printEmbeddedLanguages(path, mainPrint, options, printAstToDoc, embeds);

  // ルートからの再帰的なDocument生成
  const doc = await callPluginPrintFunction(
    path,
    options,
    mainPrint,
    undefined,
    embeds,
  );

  ensureAllCommentsPrinted(options);

  return doc;
  // ...
}
```

### 6.4 言語別Printer

```javascript
// ファイル: src/language-js/print/index.js:22-35
function printWithoutParentheses(path, options, print, args) {
  for (const printer of [
    printAngular,
    printJsx,
    printFlow,
    printTypescript,
    printEstree,
  ]) {
    const doc = printer(path, options, print, args);
    if (doc !== undefined) {
      return doc;
    }
  }
}
```

**解説**: 各言語のPrinterは「責任の連鎖」パターンを使用。最初にマッチしたPrinterが処理を担当します。

---

## 7. よく使われるパターン

> このセクションでは、コード内で頻出するパターンを解説します。

### パターン一覧

| パターン | 説明 | 出現頻度 | 代表的なファイル |
|---------|------|---------|-----------------|
| Chain of Responsibility | 複数のハンドラーが順番に処理を試みる | 高 | `src/language-js/print/index.js` |
| Factory Function | オブジェクト/関数を生成する関数 | 高 | `src/utilities/create-*.js` |
| Visitor Pattern | ASTを走査して処理 | 高 | `src/common/ast-path.js` |
| Higher-Order Function | 関数を引数/戻り値とする関数 | 高 | `src/index.js` |
| Memoization | 計算結果をキャッシュ | 中 | `src/main/ast-to-doc.js` |

### 各パターンの詳細

#### パターン1: Higher-Order Function (withPlugins)

**目的:** プラグインの自動読み込みを各API関数に適用

**実装例:**
```javascript
// ファイル: src/index.js:43-64
function withPlugins(
  fn,
  optionsArgumentIndex = 1,
) {
  return async (...args) => {
    const options = args[optionsArgumentIndex] ?? {};
    const { plugins = [] } = options;

    args[optionsArgumentIndex] = {
      ...options,
      plugins: (
        await Promise.all([
          loadBuiltinPlugins(),
          loadPlugins(plugins),
        ])
      ).flat(),
    };

    return fn(...args);
  };
}

const formatWithCursor = withPlugins(core.formatWithCursor);
```

**解説:** `withPlugins` は任意の関数をラップし、呼び出し前にプラグインを自動的に読み込む処理を追加します。これにより、各API関数でプラグイン読み込みコードを重複させる必要がなくなります。

#### パターン2: Visitor Pattern (AstPath)

**目的:** ASTを再帰的に走査しながら、現在位置のコンテキストを保持

**実装例:**
```javascript
// ファイル: src/common/ast-path.js:126-140
call(callback, ...names) {
  const { stack } = this;
  const { length } = stack;
  let value = stack.at(-1);

  for (const name of names) {
    value = value?.[name];
    stack.push(name, value);
  }
  try {
    return callback(this);
  } finally {
    stack.length = length;  // スタックを復元
  }
}
```

**解説:** `call` メソッドは一時的に子ノードに移動し、コールバックを実行後、元の位置に戻ります。`finally` ブロックでスタックを確実に復元することで、例外が発生しても状態が壊れません。

#### パターン3: Chain of Responsibility (Print関数)

**目的:** 複数のプリンターが順番にノードの処理を試み、最初に対応できるものが処理

**実装例:**
```javascript
// ファイル: src/language-js/print/index.js:22-35
function printWithoutParentheses(path, options, print, args) {
  for (const printer of [
    printAngular,
    printJsx,
    printFlow,
    printTypescript,
    printEstree,
  ]) {
    const doc = printer(path, options, print, args);
    if (doc !== undefined) {
      return doc;
    }
  }
}
```

**解説:** 各プリンター関数は、自分が処理できないノードには `undefined` を返します。これにより、特定の言語拡張（Angular、JSX、Flow、TypeScript）の処理を共通のEStreeプリンターと組み合わせられます。

#### パターン4: Memoization (キャッシュ)

**目的:** 同じノードの再処理を防ぎ、パフォーマンスを向上

**実装例:**
```javascript
// ファイル: src/main/ast-to-doc.js:79-101
function mainPrintInternal(args) {
  ensurePrintingNode(path);

  const value = path.node;
  if (value === undefined || value === null) {
    return "";
  }

  const shouldCache = isObject(value) && args === undefined;

  if (shouldCache && cache.has(value)) {
    return cache.get(value);  // キャッシュから返す
  }

  const doc = callPluginPrintFunction(path, options, mainPrint, args, embeds);

  if (shouldCache) {
    cache.set(value, doc);  // キャッシュに保存
  }

  return doc;
}
```

**解説:** 同じASTノードが複数回参照される場合（例：変数参照）、キャッシュを使用して再計算を避けます。

---

## 8. 業務フロー追跡の実践例

> このセクションでは、実際の業務フローをコードで追跡する方法を解説します。

### 8.1 フロー追跡の基本手順

1. エントリーポイントを特定
2. 処理の流れを追跡（呼び出し関係を追う）
3. データの変換を確認
4. 最終的な出力を確認

### 8.2 フロー追跡の実例

#### 例1: format() API の呼び出しフロー

**概要:** `prettier.format()` を呼び出した時の処理フロー

**処理フロー:**
```
format() → formatWithCursor() → coreFormat() → parse() → printAstToDoc() → printDocToString()
```

**詳細な追跡:**

1. **format() の呼び出し** (`src/index.js:68-74`)
   ```javascript
   async function format(text, options) {
     const { formatted } = await formatWithCursor(text, {
       ...options,
       cursorOffset: -1,
     });
     return formatted;
   }
   ```

2. **formatWithCursor() でプラグイン読み込み** (`src/index.js:66`)
   ```javascript
   const formatWithCursor = withPlugins(core.formatWithCursor);
   ```

3. **core.formatWithCursor() で入力正規化** (`src/main/core.js:324-328`)
   ```javascript
   async function formatWithCursor(originalText, originalOptions) {
     let { hasBOM, text, options } = normalizeInputAndOptions(
       originalText,
       await normalizeFormatOptions(originalOptions),
     );
     // ...
   }
   ```

4. **coreFormat() でAST生成とDocument変換** (`src/main/core.js:28-49`)
   ```javascript
   async function coreFormat(originalText, opts, addAlignmentSize = 0) {
     // ...
     const { ast, text } = await parseText(originalText, opts);
     // ...
     let doc = await printAstToDoc(ast, opts, addAlignmentSize);
     // ...
     const result = printDocToStringWithoutNormalizeOptions(doc, opts);
     // ...
   }
   ```

5. **printDocToString() で最終出力** (`src/document/printer/printer.js`)
   ```javascript
   // Document IR を実際の文字列に変換
   ```

#### 例2: JavaScript ノードの print 処理

**概要:** JavaScriptの `if` 文がどのようにフォーマットされるか

**処理フロー:**
```
printEstree() → switch case "IfStatement" → printIfStatement()
```

**詳細な追跡:**

1. **printEstree() でノードタイプ判定** (`src/language-js/print/estree.js:85-92`)
   ```javascript
   function printEstree(path, options, print, args) {
     const { node } = path;

     if (isLiteral(node)) {
       return printLiteral(path, options);
     }

     switch (node.type) {
       // 各ノードタイプに応じた処理
     }
   }
   ```

2. **該当するcase文で専用関数を呼び出し**
   ```javascript
   case "IfStatement":
     return printIfStatement(path, options, print);
   ```

### 8.3 フロー追跡チェックリスト

- [ ] エントリーポイントを特定したか
- [ ] 呼び出し関係を把握したか
- [ ] データの変換ポイントを確認したか
- [ ] エラーハンドリングを確認したか
- [ ] 最終的な出力を確認したか

---

## 9. 設計書の参照順序

> このセクションでは、プロジェクト理解のための設計書参照順序を案内します。

### 9.1 目的別ロードマップ

#### 全体像を把握したい場合
1. `README.md` - プロジェクト概要
2. `CONTRIBUTING.md` - 開発参加方法、テスト方法
3. `commands.md` - Document IRの詳細説明

#### 特定機能を理解したい場合
1. 対象言語の `src/language-*/` ディレクトリ
2. `src/main/` のコアロジック
3. `tests/format/` の関連テスト

#### 改修作業を行う場合
1. 対象機能のソースコード
2. `tests/format/` の関連テスト
3. `CONTRIBUTING.md` のテスト方法

### 9.2 ドキュメント一覧

| ドキュメント | 概要 | 参照タイミング |
|-------------|------|---------------|
| `README.md` | プロジェクト概要、基本的な使い方 | 初回参照 |
| `CONTRIBUTING.md` | 開発参加方法、テスト実行方法 | 開発開始時 |
| `commands.md` | Document IRの仕様書 | Document層の理解 |
| `website/` | 公式ドキュメント生成元 | API仕様確認 |
| `changelog_unreleased/` | 未リリースの変更点 | 最新変更の確認 |

---

## 10. トラブルシューティング

> このセクションでは、コードリーディング時によくある問題と解決法を解説します。

### よくある疑問と回答

#### Q: `*.evaluate.js` ファイルとは何ですか？
A: ビルド時に評価（実行）されるファイルです。例えば `version.evaluate.js` はビルド時に現在のバージョン番号を返します。これにより、バージョン情報がバンドルに埋め込まれます。

#### Q: `#` で始まるメソッドは何ですか？
A: JavaScriptのプライベートクラスフィールド/メソッドです。クラス外からアクセスできません。
```javascript
// ファイル: src/common/ast-path.js:267
*#getAncestors() {
  // プライベートジェネレータメソッド
}
```

#### Q: `@import` と `@typedef` のJSDocコメントは何ですか？
A: TypeScriptの型をJavaScript内で使用するためのJSDoc注釈です。
```javascript
/**
 * @import AstPath from "../../common/ast-path.js"
 * @import {Doc} from "../../document/index.js"
 */
```

#### Q: Document IRの種類を調べるには？
A: `src/document/builders/` ディレクトリ内の各ファイルが1つのDocument型に対応しています。

### デバッグのヒント

1. **AST確認**: Prettier Playgroundの「Show AST」機能を使用
2. **Document確認**: `prettier.doc.debug.printDocToDebug()` でDocument IRを可視化
3. **ステップ実行**: `yarn debug <file>` でNode.jsデバッガを起動
4. **テスト実行**: `yarn test <pattern>` で特定のテストのみ実行

---

## 付録

### A. 用語集

| 用語 | 説明 |
|-----|------|
| AST | Abstract Syntax Tree（抽象構文木）- ソースコードの構造を表すツリー |
| Document / IR | Intermediate Representation - フォーマット方法を表す中間表現 |
| Parser | ソースコードをASTに変換するモジュール |
| Printer | ASTをDocumentに変換するモジュール |
| Plugin | 新しい言語やフォーマット機能を追加する拡張 |
| Pragma | `@format` などの特殊コメント |
| hardline | 必ず改行するDocument要素 |
| softline | グループが展開された時のみ改行するDocument要素 |
| group | 改行の有無を制御するためのDocument要素 |

### B. ファイル一覧

| ファイル/ディレクトリ | 説明 | 主な内容 |
|---------------------|------|---------|
| `src/index.js` | API エントリーポイント | format, check, getSupportInfo等のエクスポート |
| `src/main/core.js` | コアフォーマッティング | formatWithCursor, coreFormat, formatRange |
| `src/main/ast-to-doc.js` | AST→Document変換 | printAstToDoc, callPluginPrintFunction |
| `src/main/parse.js` | ソースコード解析 | parse関数 |
| `src/common/ast-path.js` | AST走査クラス | AstPath クラス |
| `src/document/builders/` | Document ビルダー | group, indent, hardline等 |
| `src/language-js/print/` | JS Printer | printEstree, printJsx等 |
| `src/config/resolve-config.js` | 設定解決 | resolveConfig, resolveConfigFile |

### C. 参考資料

- [Prettier 公式ドキュメント](https://prettier.io/docs/)
- [Wadler's Paper: A prettier printer](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf) - Prettierのアルゴリズムの基礎
- [commands.md](../../commands.md) - Document IRの詳細仕様
- [ESTree Spec](https://github.com/estree/estree) - JavaScript AST仕様
- [Babel Parser](https://babeljs.io/docs/babel-parser) - 使用しているパーサーの1つ
