# 通知設計書 2-keyword_assignment_error

## 概要

本ドキュメントは、CoffeeScriptコンパイラがJavaScriptまたはCoffeeScriptのキーワードに代入しようとした際に発生する構文エラー「keyword assignment error」の通知仕様を定義する。

### 本通知の処理概要

CoffeeScriptコンパイラのレキサー（字句解析器）において、JavaScriptキーワード（true、false、null、this、new、delete、typeof、in、instanceof、return、throw、break、continue、debugger、yield、await、if、else、switch、for、while、do、try、catch、finally、class、extends、super、import、export、default）またはCoffeeScriptキーワード（undefined、Infinity、NaN、then、unless、until、loop、of、by、when、and、or、is、isnt、not、yes、no、on、off）に代入を試みた場合に、構文エラーとして通知を行う処理である。

**業務上の目的・背景**：キーワードへの代入はJavaScript/CoffeeScriptの言語仕様において禁止されている。キーワードは言語の構文要素として予約されており、これらに値を代入しようとするコードは明らかなバグまたは誤りである。この通知により、開発者は意図しないコードの問題を早期に発見できる。

**通知の送信タイミング**：レキサーのliteralToken()メソッドにおいて、代入演算子（=、+=、-=等）が検出され、その直前のトークンがキーワードであることが判明した時点で発生する。isUnassignable()ヘルパー関数によりチェックされる。

**通知の受信者**：CoffeeScriptソースコードをコンパイルしている開発者。

**通知内容の概要**：エラーメッセージとして「keyword '{keyword}' can't be assigned」という形式で、問題となったキーワードを特定できるようにしている。

**期待されるアクション**：開発者は該当するキーワードを変数名として使用せず、別の識別子名に変更する。

## 通知種別

コンパイラ出力（標準エラー出力 / SyntaxError例外）

## 送信仕様

### 基本情報

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

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

CoffeeScriptコンパイラを呼び出しているコンテキストに依存する。

## 通知テンプレート

### エラーメッセージ形式

| 項目 | 内容 |
|-----|------|
| 形式 | テキスト |

### 本文テンプレート

```
[filename]:[line]:[column]: error: keyword '{keyword}' can't be assigned
[source_code_line]
[marker]
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| keyword | 代入を試みられたキーワード | isUnassignable関数のdisplayName引数 | Yes |
| filename | ソースファイル名 | コンパイルオプションまたは標準入力 | No |
| line | エラー発生行番号 | locationData.first_line | Yes |
| column | エラー発生列番号 | locationData.first_column | Yes |
| source_code_line | エラーが発生した行のソースコード | 入力ソースコード | Yes |
| marker | エラー位置を示すマーカー（^記号） | 計算により生成 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コンパイル処理 | literalToken()メソッド実行中 | 代入演算子の直前トークンがJS_KEYWORDSまたはCOFFEE_KEYWORDSに含まれる場合 | 代入演算子検出時にキーワードチェック |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| PROPERTYタグ | プロパティアクセスの場合は抑止 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[literalToken開始] --> B{代入演算子か?}
    B -->|No| C[通常処理継続]
    B -->|Yes| D{直前トークンがPROPERTYか?}
    D -->|Yes| C
    D -->|No| E[isUnassignable呼び出し]
    E --> F{キーワードか?}
    F -->|No| C
    F -->|Yes| G[error関数呼び出し]
    G --> H[throwSyntaxError実行]
    H --> I[SyntaxError例外発生]
    I --> J[コンパイル中断]
```

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

### 参照テーブル一覧

該当なし（メモリ内の配列参照のみ）

### 内部データ構造

| 構造名 | 用途 | 備考 |
|--------|------|------|
| JS_KEYWORDS配列 | JavaScriptキーワードリスト | lexer.coffeeで定義（1226-1233行目） |
| COFFEE_KEYWORDS配列 | CoffeeScriptキーワードリスト | lexer.coffeeで定義（1236-1253行目） |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| SyntaxError | キーワードへの代入を試みた | 開発者が変数名を変更 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

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

- エラーメッセージにはソースコードの一部が含まれる

## 備考

- isUnassignable()関数は、名前とその表示名（エイリアス使用時）を引数として受け取り、適切なエラーメッセージを構築する
- CoffeeScriptエイリアス（and→&&、or→||等）も適切に処理される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lexer.coffee | `src/lexer.coffee` | JS_KEYWORDS配列（1226-1233行目） |
| 1-2 | lexer.coffee | `src/lexer.coffee` | COFFEE_KEYWORDS配列（1236-1253行目） |

**読解のコツ**: これらの配列がisUnassignable関数内でスプレッド演算子を使ってチェックされる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | lexer.coffee | `src/lexer.coffee` | literalToken()メソッド（755-823行目） |

**主要処理フロー**:
1. **764行目**: 代入演算子の検出
2. **778-781行目**: isUnassignableを呼び出してエラーチェック

#### Step 3: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | lexer.coffee | `src/lexer.coffee` | isUnassignable()関数（1190-1198行目） |

**主要処理フロー**:
- **1191-1192行目**: JS_KEYWORDSとCOFFEE_KEYWORDSに含まれる場合「keyword '{displayName}' can't be assigned」を返す

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

```
Lexer.tokenize()
    |
    +-- literalToken()
           |
           +-- 代入演算子検出 (764行目)
           |       |
           |       +-- isUnassignable() (1190-1198行目)
           |               |
           |               +-- JS_KEYWORDS/COFFEE_KEYWORDS チェック
           |               |
           |               +-- [キーワードの場合] エラーメッセージ返却
           |
           +-- error() (781行目)
                   |
                   +-- throwSyntaxError()
```

### データフロー図

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

ソースコード  -----> literalToken()     -----> トークンストリーム
    |                     |
    |                     v
    |               代入演算子検出
    |                     |
    |                     v
    |            isUnassignable()
    |                     |
    |              [キーワードの場合]
    |                     |
    |                     v
    +------------> error() + throwSyntaxError()
                          |
                          v
                   SyntaxError例外
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lexer.coffee | `src/lexer.coffee` | ソース | 字句解析器。キーワードチェックとエラー発生 |
| helpers.coffee | `src/helpers.coffee` | ソース | throwSyntaxError関数 |
| error_messages.coffee | `test/error_messages.coffee` | テスト | エラーメッセージテスト（38-46行目） |
