# 通知設計書 4-UnexpectedNodeError

## 概要

本ドキュメントは、Prettierにおいて予期しないASTノードタイプが検出された場合に発生するエラー通知「UnexpectedNodeError」の設計を記述する。

### 本通知の処理概要

UnexpectedNodeErrorは、コードの印刷（プリント）処理中に、プリンターが処理方法を知らないノードタイプに遭遇した場合に発生するエラー通知である。

**業務上の目的・背景**：Prettierは各言語パーサーが生成した抽象構文木（AST）を走査し、各ノードタイプに応じたフォーマット処理を行う。しかし、パーサーの更新により新しいノードタイプが追加されたり、予期しないノード構造が発生した場合、プリンターは処理方法を知らず、このエラーを発生させる。これは主に開発者向けの内部エラーであり、Prettierのバグまたはプラグインの不整合を示唆する。

**通知の送信タイミング**：`prettier.format()`等のAPI呼び出し時、またはCLI実行時に、各言語のプリンター（JavaScript/TypeScript、CSS、HTML、JSON、Markdown、YAML、GraphQL、Handlebars等）がノードの印刷処理中に未対応のノードタイプに遭遇した場合に発生する。

**通知の受信者**：CLIを使用しているユーザー、API経由でPrettierを呼び出しているアプリケーション開発者、またはPrettierプラグイン開発者。

**通知内容の概要**：予期しないノードタイプの名前、言語名、およびノードオブジェクトの情報。

**期待されるアクション**：ユーザーはPrettierのバージョンを最新にアップデートするか、Prettierのissueとしてバグ報告を行う。プラグイン使用時は対応するプラグインの更新が必要な場合がある。

## 通知種別

CLIエラー出力（標準エラー出力への出力）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | なし |

### 送信先決定ロジック

エラーが発生した時点で即座に例外としてスローされ、CLIではキャッチされて標準エラー出力（stderr）に出力される。プロセス終了コードは2に設定される。

## 通知テンプレート

### メール通知の場合

該当なし（CLI出力のみ）

### 本文テンプレート

```
[error] {filename}: UnexpectedNodeError: Unexpected {language} node {typeProperty}: "{nodeType}".
```

例：
```
[error] index.js: UnexpectedNodeError: Unexpected ESTree node type: "UnknownExpression".
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| filename | 対象ファイル名 | 引数filename | Yes |
| language | 言語名 | コンストラクタ引数 | Yes |
| typeProperty | ノードタイプを示すプロパティ名（デフォルト: "type"） | コンストラクタ引数 | No |
| nodeType | 予期しないノードタイプ値 | node[typeProperty] | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | format/formatWithCursor実行 | プリンターが未対応ノードを検出 | 各言語プリンターのswitchのdefault句で発生 |
| CLI実行 | prettierコマンド実行 | 同上 | 同上 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | UnexpectedNodeErrorは常に表示される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[format呼び出し] --> B[パース処理]
    B --> C[AST生成]
    C --> D[プリンター処理]
    D --> E{ノードタイプ判定}
    E -->|既知のタイプ| F[フォーマット処理]
    E -->|未知のタイプ| G[UnexpectedNodeError発生]
    G --> H[エラーをスロー]
    H --> I[handleError]
    I --> J[エラーメッセージ出力]
    J --> K[終了コード2設定]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（Prettierはデータベースを使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ESTree未対応ノード | JS/TS ASTの未対応ノード | Prettierをアップデート |
| TypeScript未対応ノード | TS固有ASTの未対応ノード | Prettierをアップデート |
| PostCSS未対応ノード | CSS ASTの未対応ノード | Prettierをアップデート |
| HTML未対応ノード | HTML ASTの未対応ノード | Prettierをアップデート |
| GraphQL未対応ノード | GraphQL ASTの未対応ノード（kindプロパティ使用） | Prettierをアップデート |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

該当なし

### 配信時間帯

該当なし

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

ノードタイプ名がエラーメッセージに含まれるが、これは内部的な識別子であり、機密情報ではない。ノードオブジェクト自体はエラーオブジェクトのプロパティとして保持されるが、通常は出力されない。

## 備考

- 主に内部エラー・開発者向けエラーとして位置づけられる
- Prettierのバグまたはパーサーとプリンターの不整合を示す
- GraphQLプリンターでは`typeProperty`として`"kind"`を使用
- エラーオブジェクトの`node`プロパティに問題のノードが格納される

---

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

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

### 推奨読解順序

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

UnexpectedNodeErrorクラスの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | unexpected-node-error.js | `src/utilities/unexpected-node-error.js` | UnexpectedNodeErrorクラスの定義（1-14行目） |

**読解のコツ**:
- 1行目: Errorクラスを継承
- 2行目: `name`プロパティで「UnexpectedNodeError」を定義
- 4行目: コンストラクタで`node`, `language`, `typeProperty`を受け取る
- 5-8行目: メッセージを構築 `Unexpected {language} node {typeProperty}: "{nodeType}".`
- 10行目: `this.node`に問題のノードを保持

#### Step 2: 各プリンターでのエラー発生箇所を理解する

代表的なプリンターでのUnexpectedNodeError使用例を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | estree.js | `src/language-js/print/estree.js` | ESTreeプリンターでのエラー発生（340行目） |
| 2-2 | typescript.js | `src/language-js/print/typescript.js` | TypeScriptプリンターでのエラー発生（220行目） |
| 2-3 | printer-postcss.js | `src/language-css/printer-postcss.js` | PostCSSプリンターでのエラー発生（583行目） |
| 2-4 | printer-graphql.js | `src/language-graphql/printer-graphql.js` | GraphQLプリンターでのエラー発生（430行目、kindを使用） |

**主要処理フロー**（ESTreeの例）:
- **340行目**: `throw new UnexpectedNodeError(node, "ESTree")`
- switchのdefault句で発生し、未対応のノードタイプを検出

#### Step 3: CLI層でのエラーハンドリングを理解する

CLIでUnexpectedNodeErrorがどのように処理されるかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | format.js | `src/cli/format.js` | handleError関数での一般的なエラー処理（64-68行目） |

**主要処理フロー**:
- **67行目**: 一般的なエラーとして`filename + ": " + (error.stack || error)`形式で出力
- UnexpectedNodeErrorは特別な処理がないため、一般的なエラーとして処理される

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

```
prettier.format() / CLI実行
    │
    ├─ parse() [各パーサー]
    │      └─ AST生成
    │
    ├─ print() [各プリンター]
    │      │
    │      ├─ ESTree: src/language-js/print/estree.js
    │      │      └─ switch(node.type) default: throw UnexpectedNodeError [340行目]
    │      │
    │      ├─ TypeScript: src/language-js/print/typescript.js
    │      │      └─ switch(node.type) default: throw UnexpectedNodeError [220行目]
    │      │
    │      ├─ PostCSS: src/language-css/printer-postcss.js
    │      │      └─ switch(node.type) default: throw UnexpectedNodeError [583行目]
    │      │
    │      ├─ GraphQL: src/language-graphql/printer-graphql.js
    │      │      └─ switch(node.kind) default: throw UnexpectedNodeError [430行目]
    │      │
    │      └─ その他プリンター...
    │
    └─ handleError() [src/cli/format.js:26] (CLI使用時)
           ├─ context.logger.error() [67行目]
           └─ process.exitCode = 2 [71行目]
```

### データフロー図

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

sourceCode           パーサー                  UnexpectedNodeError
    │                  │                         │
    v                  v                         │
                   AST生成                       │
                     │                          │
                     v                          v
                 プリンター              handleError()
                 ├─ node.type判定              │
                 └─ 未知タイプ                  v
                    │                      stderr出力
                    v                      [error] filename: UnexpectedNodeError: ...
              throw UnexpectedNodeError
              ├─ node
              ├─ language
              └─ typeProperty
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| unexpected-node-error.js | `src/utilities/unexpected-node-error.js` | ソース | UnexpectedNodeErrorクラス定義 |
| estree.js | `src/language-js/print/estree.js` | ソース | ESTreeプリンター（JavaScript） |
| typescript.js | `src/language-js/print/typescript.js` | ソース | TypeScriptプリンター |
| jsx.js | `src/language-js/print/jsx.js` | ソース | JSXプリンター |
| angular.js | `src/language-js/print/angular.js` | ソース | Angularテンプレートプリンター |
| module.js | `src/language-js/print/module.js` | ソース | ESモジュールプリンター |
| printer-postcss.js | `src/language-css/printer-postcss.js` | ソース | PostCSS（CSS）プリンター |
| printer-html.js | `src/language-html/printer-html.js` | ソース | HTMLプリンター |
| print/json.js | `src/language-json/print/json.js` | ソース | JSONプリンター |
| print/mdast.js | `src/language-markdown/print/mdast.js` | ソース | Markdownプリンター |
| printer-yaml.js | `src/language-yaml/printer-yaml.js` | ソース | YAMLプリンター |
| printer-graphql.js | `src/language-graphql/printer-graphql.js` | ソース | GraphQLプリンター |
| printer-glimmer.js | `src/language-handlebars/printer-glimmer.js` | ソース | Handlebarsプリンター |
| format.js | `src/cli/format.js` | ソース | CLIでのエラーハンドリング |
