# 機能設計書 63-@generic

## 概要

本ドキュメントは、Lua Language Serverにおける`@generic`アノテーション機能の設計を記述する。`@generic`はジェネリック型（パラメトリック多相）を定義するためのLuaDocアノテーションであり、型パラメータを使用した汎用的な関数や型を定義する機能を提供する。

### 本機能の処理概要

`@generic`アノテーションは、関数やクラスにおいて型パラメータを宣言する機能である。これにより、同一の関数定義で異なる型に対応でき、型安全性を維持しながら汎用的なコードを記述できる。

**業務上の目的・背景**：汎用的なユーティリティ関数（配列操作、マッピング関数など）では、入力型と出力型の関係を表現する必要がある。静的型付け言語のジェネリクスに相当する機能を提供することで、型情報を失わずに汎用コードの型チェックと補完が可能となる。

**機能の利用シーン**：
- 配列やテーブルを操作する汎用関数（map、filter、reduce等）
- 任意の型の値を受け取り、同じ型を返す関数
- コンテナ型（リスト、辞書等）のジェネリック定義
- ファクトリ関数やビルダーパターンの型定義

**主要な処理内容**：
1. `---@generic`で始まるコメント行を検出
2. 型パラメータ名（T, K, V等）を解析
3. 型制約（`: BaseType`形式）がある場合は解析
4. 複数の型パラメータをカンマ区切りで処理
5. `doc.generic`ノードを生成し、後続の`@param`や`@return`で参照可能に
6. 関数定義にバインドし、ジェネリック型の解決に使用

**関連システム・外部連携**：
- パーサー（`script/parser/luadoc.lua`）：アノテーション構文の解析
- ジェネリック解決（`script/vm/generic.lua`）：型パラメータの具体化
- 型推論エンジン（`script/vm/infer.lua`）：ジェネリック型の推論
- バインディング処理：関数定義との関連付け

**権限による制御**：本機能に権限制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はエディタのコメント入力時に動作し、専用の画面は存在しない |

## 機能種別

コード解析 / 型定義

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| コメントテキスト | string | Yes | `---@generic`で始まるコメント行 | `@generic`キーワードの存在確認 |
| 型パラメータ名 | string | Yes | ジェネリック型の名前（T, K, V等） | 有効な識別子であること |
| 型制約 | string | No | `: BaseType`形式の型制約 | 有効な型構文であること |

### 入力データソース

Luaソースファイル内の`---@generic`形式のコメント行

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| doc.generic | table | ジェネリック定義のASTノード |
| doc.generic.generics | table | 型パラメータオブジェクトのリスト |
| doc.generic.object | table | 各型パラメータのオブジェクト |
| doc.generic.object.generic | table | 型パラメータ名ノード |
| doc.generic.object.extends | table | 型制約（オプション） |

### 出力先

パーサーの状態オブジェクト（`state.ast.docs`）に追加される

## 処理フロー

### 処理シーケンス

```
1. コメント解析開始
   └─ `---@generic`形式のコメントを検出
2. トークン解析
   └─ コメントテキストをトークンに分割
3. `generic`キーワード認識
   └─ docSwitch関数でgenericケースにディスパッチ
4. 型パラメータ解析ループ
   └─ 各パラメータについて：
      a. パラメータ名を解析（doc.generic.name）
      b. 型制約がある場合は解析（extends）
      c. doc.generic.objectノードを生成
      d. カンマがあれば次のパラメータへ
5. ASTノード構築
   └─ `doc.generic`ノードを生成し、generics配列を格納
6. ドキュメントリストに追加
   └─ `state.ast.docs`にノードを追加
7. ジェネリックバインディング
   └─ 後続の@param/@returnで型パラメータ名を解決
```

### フローチャート

```mermaid
flowchart TD
    A[コメント検出] --> B{@genericキーワード?}
    B -->|No| Z[終了]
    B -->|Yes| C[doc.generic初期化]
    C --> D[型パラメータ名解析]
    D --> E{パラメータ名あり?}
    E -->|No| F[LUADOC_MISS_GENERIC_NAME警告]
    F --> Z
    E -->|Yes| G[doc.generic.objectノード生成]
    G --> H{型制約 ':' あり?}
    H -->|Yes| I[extends解析]
    H -->|No| J{カンマあり?}
    I --> J
    J -->|Yes| D
    J -->|No| K[doc.genericノード完成]
    K --> L[ASTに追加]
    L --> M[bindGeneric処理]
    M --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 型パラメータ名必須 | ジェネリック定義には必ず型パラメータ名が必要 | @genericアノテーション使用時 |
| BR-02 | 複数パラメータ | カンマ区切りで複数の型パラメータを定義可能 | @genericアノテーション使用時 |
| BR-03 | 型制約サポート | `: BaseType`形式で型制約を指定可能 | 型パラメータに制約がある場合 |
| BR-04 | 関数バインド | 直後の関数定義に自動的にバインドされる | @genericの後に関数定義がある場合 |
| BR-05 | 名前解決 | @param/@returnで型パラメータ名を使用可能 | ジェネリック関数定義時 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベースを使用しない（メモリ上でAST操作を行う）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| LUADOC_MISS_GENERIC_NAME | Warning | 型パラメータ名が指定されていない | 正しい型パラメータ名を指定する |

### リトライ仕様

リトライは不要（構文解析時のエラーは即座に報告される）

## トランザクション仕様

トランザクション管理は不要（メモリ上の解析処理）

## パフォーマンス要件

- 単一のジェネリック定義解析は1ms以内に完了すること
- ジェネリック型の具体化は関数呼び出しごとに5ms以内

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

- 入力文字列の検証（不正な識別子の排除）
- 深くネストされたジェネリック型の処理制限

## 備考

- `@generic`は`@param`や`@return`と組み合わせて使用される
- 型パラメータ名は慣例的に大文字1文字（T, K, V等）が使用される
- 複数の`@generic`行を連続して記述することも可能

---

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

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

### 推奨読解順序

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

まず、`@generic`アノテーションがどのようなASTノードとして表現されるかを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | luadoc.lua | `script/parser/luadoc.lua` | `doc.generic`ノードの構造、`generics`配列、`doc.generic.object`の役割 |

**読解のコツ**: `doc.generic`ノードは以下のフィールドを持つ：
- `type`: `'doc.generic'`
- `generics`: `doc.generic.object`の配列
- 各`doc.generic.object`には：
  - `generic`: 型パラメータ名（`doc.generic.name`型）
  - `extends`: 型制約（オプション）
  - `start`, `finish`: 位置情報

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

`@generic`アノテーションの解析処理の起点を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | luadoc.lua | `script/parser/luadoc.lua` | `docSwitch`の`'generic'`ケース（1269-1306行目） |

**主要処理フロー**:
1. **1271-1273行目**: `doc.generic`テーブルを初期化、`generics`配列を作成
2. **1275-1303行目**: 型パラメータ解析ループ
3. **1276-1279行目**: `doc.generic.object`を作成
4. **1280行目**: `parseName`で型パラメータ名を解析
5. **1293-1296行目**: 型制約がある場合`parseType`を呼び出し
6. **1298行目**: `generics`配列に追加
7. **1299-1302行目**: カンマがあれば次のパラメータへ
8. **1304行目**: ノードのfinish位置を設定

#### Step 3: ジェネリックバインディングを理解する

ジェネリック型パラメータが後続のアノテーションで解決される仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | luadoc.lua | `script/parser/luadoc.lua` | `bindGeneric`関数（1883-1925行目） |
| 3-2 | generic.lua | `script/vm/generic.lua` | ジェネリック型の具体化処理 |

**主要処理フロー**:
- **1883-1925行目**: `bindGeneric`関数でジェネリック型パラメータを収集
- **1884-1899行目**: `doc.generic`と`doc.class`/`doc.alias`からジェネリック名を抽出
- **1909-1915行目**: `doc.type.name`を`doc.generic.name`に変換
- **1916-1922行目**: `doc.type.code`を`doc.generic.name`に変換（リテラル用）

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

```
luadoc (メイン関数)
    │
    ├─ buildLuaDoc
    │      └─ convertTokens
    │             └─ docSwitch('generic')
    │                    └─ 型パラメータ解析ループ
    │                           ├─ parseName (パラメータ名)
    │                           └─ parseType (型制約)
    │
    └─ bindDocs
           └─ bindDocWithSources
                  └─ bindGeneric
                         └─ 型名をdoc.generic.nameに変換
```

### データフロー図

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

---@generic T, K: string
---@param list T[]
---@return K
        │
        ▼
  parseTokens              ───▶  トークン配列
        │
        ▼
  docSwitch('generic')     ───▶  genericケース処理
        │
        ▼
  パラメータ解析ループ     ───▶  T, K を解析
        │
        ▼
  型制約解析               ───▶  K: string の制約を設定
        │
        ▼
  doc.genericノード構築    ───▶  {generics: [{generic: T}, {generic: K, extends: string}]}
        │
        ▼
  bindGeneric              ───▶  @param/@returnの型名を変換
        │
        ▼
  state.ast.docs に追加    ───▶  完成したASTノード
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| luadoc.lua | `script/parser/luadoc.lua` | ソース | LuaDocアノテーションの解析メイン処理 |
| generic.lua | `script/vm/generic.lua` | ソース | ジェネリック型の具体化処理 |
| infer.lua | `script/vm/infer.lua` | ソース | 型推論エンジン |
| compile.lua | `script/parser/compile.lua` | ソース | Luaソースコードのコンパイル |
| guide.lua | `script/parser/guide.lua` | ソース | AST操作のユーティリティ関数 |
