# 通知設計書 24-JSX attribute error

## 概要

本ドキュメントは、CoffeeScriptコンパイラにおけるJSX属性値の形式エラー（JSX attribute error）の通知仕様を記述する。

### 本通知の処理概要

本通知は、JSX構文を使用したCoffeeScriptソースコードにおいて、属性値が不正な形式で記述された場合に発生するエラーメッセージである。

**業務上の目的・背景**：JSX属性は、特定の形式でのみ記述が許可される。具体的には、文字列（クォートで囲まれた値）、波括弧で囲まれた式（`{expression}`）、またはスプレッド属性（`{...props}`）のいずれかでなければならない。これ以外の形式で属性値を指定した場合、コンパイル時にエラーを発生させることで、不正なJSX構文を早期に検出する。

**通知の送信タイミング**：コンパイル時、Rewriter（トークン書き換え）フェーズでJSX属性を検証する際に発生する。具体的には、`jsxColon`フラグが付いたトークンの直後のトークンを検証するタイミングで発生する。

**通知の受信者**：CoffeeScriptコンパイラを実行している開発者。コンソール出力またはエラーオブジェクトとして通知される。

**通知内容の概要**：エラーメッセージ「expected wrapped or quoted JSX attribute」とともに、不正な属性値の位置情報が提供される。

**期待されるアクション**：開発者は、属性値を文字列（`"value"`）、式（`{value}`）、またはスプレッド（`{...props}`）のいずれかの形式に修正する必要がある。

## 通知種別

コンソールエラー出力 / SyntaxError例外

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（コンパイル処理中に即時発生） |
| 優先度 | 高（コンパイルエラー） |
| リトライ | なし（即時エラー終了） |

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

コンパイラを実行しているプロセスの標準エラー出力、またはAPIとして呼び出された場合はSyntaxError例外として呼び出し元に返される。

## 通知テンプレート

### コンソール出力の場合

| 項目 | 内容 |
|-----|------|
| 出力先 | stderr |
| 形式 | テキスト |

### 本文テンプレート

```
[ファイル名]:[行番号]:[列番号]: error: expected wrapped or quoted JSX attribute
[該当行のソースコード]
[エラー位置を示すキャレット]
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| filename | ソースファイル名 | コンパイルオプション | Yes |
| line | エラー発生行番号 | next[2]（不正なトークンの位置） | Yes |
| column | エラー発生列番号 | next[2] | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コンパイル処理 | JSX属性の検証 | next[0] not in ['STRING_START', 'STRING', '('] | 属性値トークンがSTRING_START, STRING, または開き括弧でない場合 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 文字列属性値 | `attr="value"` または `attr='value'` 形式 |
| 式属性値 | `attr={expression}` 形式 |
| スプレッド属性 | `{...props}` 形式 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Rewriterフェーズ開始] --> B[enforceValidJSXAttributes呼び出し]
    B --> C[トークンをスキャン]
    C --> D{jsxColonフラグあり?}
    D -->|No| E[次のトークンへ]
    D -->|Yes| F{次のトークンタイプをチェック}
    F -->|STRING_START/STRING/(| G[正常処理継続]
    F -->|それ以外| H[throwSyntaxError呼び出し]
    H --> I[SyntaxError生成]
    I --> J[エラーメッセージ出力]
    J --> K[コンパイル中断]
    G --> E
    E --> L[スキャン完了]
```

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

### 参照テーブル一覧

該当なし（ファイルベースのコンパイル処理）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| SyntaxError | 属性値が不正な形式 | 文字列、式、またはスプレッド形式に修正 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | なし（コンパイル時エラー） |

### 配信時間帯

制限なし（コンパイル実行時に即時通知）

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

- エラーメッセージには属性名や属性値は含まれない
- 位置情報のみが出力されるため、機密情報漏洩リスクは低い

## 備考

- このエラーはRewriterフェーズで検出される（Lexerフェーズではない）
- 関連エラーとして、nodes.coffeeで「Unexpected token. Allowed JSX attributes are: id="val", src={source}, {props...} or attribute.」というメッセージも存在する
- JSX属性のコロン（`:`）は`jsxColon`フラグでマーク付けされる

---

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

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

### 推奨読解順序

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

JSX属性トークンの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lexer.coffee | `src/lexer.coffee` | jsxObjAttribute変数（53行目）- JSX属性の追跡 |
| 1-2 | lexer.coffee | `src/lexer.coffee` | jsxColon - 属性名と値の区切りマーキング |

**読解のコツ**: Lexerで生成されたトークンには、JSX固有のメタデータ（jsxColon等）が付加される。

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

Rewriterフェーズでの属性検証処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | rewriter.coffee | `src/rewriter.coffee` | enforceValidJSXAttributes関数（441-447行目） |

**主要処理フロー**:
1. **441行目**: 関数定義
2. **442行目**: scanTokensでトークンをスキャン
3. **443行目**: jsxColonフラグをチェック
4. **444行目**: 次のトークンを取得
5. **445行目**: トークンタイプが許可リストにあるかチェック
6. **446行目**: 許可外の場合、throwSyntaxErrorを呼び出し

#### Step 3: 許可されるトークンタイプを理解する

許可される属性値の形式を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rewriter.coffee | `src/rewriter.coffee` | 445行目 - ['STRING_START', 'STRING', '('] |

**主要処理フロー**:
- **STRING_START**: 補間を含む文字列の開始
- **STRING**: 単純な文字列リテラル
- **(**: 式を囲む開き括弧

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

```
CoffeeScript.compile()
    │
    ├─ Lexer.tokenize()
    │      └─ JSXトークン生成（jsxColonフラグ付加）
    │
    ├─ Rewriter.rewrite()
    │      └─ enforceValidJSXAttributes()
    │             └─ scanTokens()
    │                    ├─ token.jsxColon === true
    │                    ├─ next[0] チェック
    │                    │      └─ not in ['STRING_START', 'STRING', '(']
    │                    │             └─ throwSyntaxError()
    │                    └─ 許可 → 処理継続
    │
    └─ エラー時: SyntaxError例外をスロー
```

### データフロー図

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

<div attr=123 />      enforceValidJSXAttributes      エラーメッセージ
        │                     │                      "expected wrapped or
        ▼                     ▼                       quoted JSX attribute"
トークン列:          token.jsxColon === true
  IDENTIFIER attr            │
  CALL_START :              ▼
  NUMBER 123          next[0] = 'NUMBER'
                      'NUMBER' not in
                      ['STRING_START', 'STRING', '(']
                             │
                             ▼
                      throwSyntaxError()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| rewriter.coffee | `src/rewriter.coffee` | ソース | JSX属性検証（enforceValidJSXAttributes） |
| lexer.coffee | `src/lexer.coffee` | ソース | JSXトークン生成、jsxColonフラグ付加 |
| nodes.coffee | `src/nodes.coffee` | ソース | 追加のJSX属性エラー（1777行目） |
| helpers.coffee | `src/helpers.coffee` | ソース | throwSyntaxError関数 |
| error_messages.coffee | `test/error_messages.coffee` | テスト | エラーメッセージのテストケース（1623行目） |
