# 機能設計書 55-LuaDoc解析

## 概要

本ドキュメントは、Lua Language ServerにおけるLuaDoc解析機能の設計を記載する。この機能は、`---@`で始まるアノテーションコメントを解析し、型情報やドキュメント情報を抽出してAST（抽象構文木）に付加する。

### 本機能の処理概要

LuaDoc解析機能は、Luaソースコード内の特殊なコメント形式（`---@type`、`---@class`、`---@param`など）を解析し、型システムやドキュメント生成のための構造化データを生成する機能である。

**業務上の目的・背景**：Luaは動的型付け言語であり、言語仕様として型宣言を持たない。LuaDocアノテーションにより、開発者がコード内に型情報を記述でき、Language Serverがその情報を活用して型推論、コード補完、診断などの高度なIDE機能を提供できる。

**機能の利用シーン**：
- Luaファイルのコンパイル時に自動的に実行
- 型情報の定義（`@class`、`@type`、`@alias`等）
- 関数シグネチャの定義（`@param`、`@return`等）
- ドキュメントコメントの記述

**主要な処理内容**：
1. コメントテキストのトークン化
2. アノテーション種別の判定
3. 種別に応じた構文解析
4. ASTノードの生成
5. ソースコードとの紐付け（バインディング）

**関連システム・外部連携**：パーサー（compile.lua）、型推論（vm/infer.lua）、ホバー表示（core/hover/）と連携。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ホバー情報表示 | 補助機能 | アノテーションコメントから型・説明情報を抽出 |
| 40 | ドキュメント生成 | 補助機能 | アノテーションからドキュメント情報を抽出 |

## 機能種別

データ解析 / パース処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| state | table | Yes | パーサー状態オブジェクト | - |
| comment | parser.object | Yes | コメントASTノード | - |

### 入力データソース

- Luaソースコード内のコメント（`---@...`形式）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| doc | parser.object | LuaDocのASTノード |
| ast.docs | array | ファイル内の全LuaDocリスト |
| bindSource | parser.object | 紐付けられたソースノード |

### 出力先

- state.ast.docs（ASTのdocsフィールド）
- source.bindDocs（ソースノードのbindDocsフィールド）

## 処理フロー

### 処理シーケンス

```
1. コメント収集
   └─ ソースコードから全コメントを収集

2. トークン化
   └─ コメントテキストをトークンに分割

3. アノテーション判定
   └─ @の後のキーワードでアノテーション種別を判定

4. 種別別解析
   └─ docSwitchでアノテーション種別に応じた解析を実行

5. ASTノード生成
   └─ 解析結果からASTノードを生成

6. バインディング
   └─ 生成されたdocノードをソースコードに紐付け
```

### フローチャート

```mermaid
flowchart TD
    A[コメント検出] --> B{---@で開始?}
    B -->|No| C[doc.commentとして保持]
    B -->|Yes| D[トークン化]
    D --> E[アノテーション種別判定]
    E --> F{種別}
    F -->|class| G[parseClass]
    F -->|type| H[parseType]
    F -->|param| I[parseParam]
    F -->|return| J[parseReturn]
    F -->|field| K[parseField]
    F -->|generic| L[parseGeneric]
    F -->|alias| M[parseAlias]
    F -->|その他| N[対応する解析処理]
    G --> O[ASTノード生成]
    H --> O
    I --> O
    J --> O
    K --> O
    L --> O
    M --> O
    N --> O
    O --> P[ast.docsに追加]
    P --> Q[bindDocs実行]
    Q --> R[ソースと紐付け]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-55-01 | アノテーション形式 | `---@`で始まるコメントのみ解析 | 常時 |
| BR-55-02 | 連続コメント | 連続するアノテーションはグループ化 | 隣接行のアノテーション |
| BR-55-03 | ソース紐付け | アノテーションは直後のソース要素に紐付け | 常時 |
| BR-55-04 | class-field連携 | @fieldは直前の@classに属する | @class後の@field |
| BR-55-05 | 長いコメント | `--[[...]]`形式も対応 | longコメント |

### 計算ロジック

**サポートするアノテーション**：
- `@class` - クラス定義
- `@type` - 型指定
- `@param` - パラメータ型
- `@return` - 戻り値型
- `@field` - フィールド定義
- `@generic` - ジェネリック型パラメータ
- `@alias` - 型エイリアス
- `@enum` - 列挙型
- `@deprecated` - 非推奨マーカー
- `@async` - 非同期関数
- `@overload` - オーバーロード定義
- `@diagnostic` - 診断制御
- `@see` - 参照リンク
- `@version` - バージョン制限
- その他多数

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

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| LUADOC_MISS_TYPE_NAME | 型名不足 | 型名が指定されていない | 警告を出力 |
| LUADOC_MISS_CLASS_NAME | クラス名不足 | クラス名が指定されていない | 警告を出力 |
| LUADOC_MISS_PARAM_NAME | パラメータ名不足 | パラメータ名が指定されていない | 警告を出力 |
| LUADOC_MISS_SYMBOL | シンボル不足 | 必要なシンボルがない | 警告を出力 |

### リトライ仕様

リトライは行わない。構文エラーは警告として報告。

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

トランザクションは使用しない。

## パフォーマンス要件

- コメントは順次処理
- 解析結果はASTに直接格納

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

特になし。

## 備考

- LuaDocはLua標準機能ではなく、Language Server独自の拡張
- EmmyLuaアノテーション形式との互換性を持つ

---

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

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

### 推奨読解順序

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

LuaDocで生成されるASTノードの種類を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | luadoc.lua | `script/parser/luadoc.lua` | parser.objectの拡張フィールド（143-162行目） |

**読解のコツ**:
- `doc.class`、`doc.type`、`doc.param`等がノード種別
- 各ノードは`type`、`start`、`finish`、`parent`等の共通フィールドを持つ
- アノテーション固有のフィールド（`class`、`extends`、`param`等）が追加される

#### Step 2: トークナイザを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | luadoc.lua | `script/parser/luadoc.lua` | Parserパターン（15-139行目） |
| 2-2 | luadoc.lua | `script/parser/luadoc.lua` | parseTokens関数（163-173行目） |

**主要処理フロー**:
- **15-139行目**: re.compileでトークンパターンを定義
- **103-138行目**: トークンコールバック（Name, String, Integer等）
- **163-173行目**: テキストからトークン配列を生成

#### Step 3: アノテーション解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | luadoc.lua | `script/parser/luadoc.lua` | docSwitch（1039-1728行目） |
| 3-2 | luadoc.lua | `script/parser/luadoc.lua` | convertTokens関数（1730-1744行目） |

**主要処理フロー**:
- **1039-1094行目**: `class`アノテーションの解析
- **1095-1111行目**: `type`アノテーションの解析
- **1112-1140行目**: `alias`アノテーションの解析
- **1141-1174行目**: `param`アノテーションの解析
- **1175-1215行目**: `return`アノテーションの解析
- **1216-1268行目**: `field`アノテーションの解析
- **1269-1306行目**: `generic`アノテーションの解析

#### Step 4: 型解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | luadoc.lua | `script/parser/luadoc.lua` | parseType関数（944-1037行目） |
| 4-2 | luadoc.lua | `script/parser/luadoc.lua` | parseTypeUnit関数（885-919行目） |

**主要処理フロー**:
- **944-1037行目**: Union型（`|`区切り）を含む型全体を解析
- **885-919行目**: 単一の型ユニットを解析
- **326-397行目**: テーブル型の解析
- **514-668行目**: 関数型（fun）の解析

#### Step 5: バインディングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | luadoc.lua | `script/parser/luadoc.lua` | bindDocs関数（2210-2256行目） |
| 5-2 | luadoc.lua | `script/parser/luadoc.lua` | bindDoc関数（1937-2040行目） |

**主要処理フロー**:
- **2210-2256行目**: ドキュメントグループをソースに紐付け
- **1937-2040行目**: 個別のドキュメントをソース要素に紐付け
- **1883-1925行目**: ジェネリック型名の紐付け

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

```
luadoc(state)
    │
    ├─ NextComment() [コメント取得]
    │
    ├─ buildLuaDoc(comment)
    │      │
    │      ├─ parseTokens(text, offset)
    │      │      └─ Parser:match(text) [トークン化]
    │      │
    │      └─ convertTokens(doc)
    │             │
    │             └─ docSwitch(text, doc)
    │                    │
    │                    ├─ [class] → parseClass
    │                    ├─ [type] → parseType
    │                    ├─ [param] → parseParam
    │                    ├─ [return] → parseReturn
    │                    ├─ [field] → parseField
    │                    └─ [その他] → 対応する解析
    │
    ├─ insertDoc(doc, comment)
    │      └─ ast.docs[#ast.docs+1] = doc
    │
    └─ bindDocs(state)
           │
           ├─ guide.eachSourceTypes(ast, bindDocAccept, ...)
           │
           └─ bindDocWithSources(sources, binded)
                  │
                  ├─ bindGeneric(binded)
                  ├─ bindCommentsAndFields(binded)
                  └─ bindDocsBetween(sources, binded, ...)
                         └─ bindDoc(src, binded)
```

### データフロー図

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

コメントテキスト       ───▶  parseTokens             ───▶  トークン配列
"---@param x number"        トークン化                    [name, name, name]
                                │
                           convertTokens
                           アノテーション解析
                                │
                                ▼
                           docSwitch             ───▶  doc.param
                           種別別解析                   ASTノード
                                │
                                ▼
                           bindDocs              ───▶  source.bindDocs
                           ソース紐付け                 紐付け完了
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| luadoc.lua | `script/parser/luadoc.lua` | ソース | LuaDoc解析メインロジック |
| compile.lua | `script/parser/compile.lua` | ソース | Luaパーサー |
| guide.lua | `script/parser/guide.lua` | ソース | ASTユーティリティ |
| relabel.lua | `script/parser/relabel.lua` | ソース | PEGパーサー |
| compiler.lua | `script/vm/compiler.lua` | ソース | 型推論（LuaDoc利用） |
| infer.lua | `script/vm/infer.lua` | ソース | 型ビュー生成 |
