# 機能設計書 90-メタデータ構築

## 概要

本ドキュメントは、lua-language-serverにおけるメタデータ構築機能について記載する。この機能は、外部APIやフレームワークのメタデータ（クラス定義、メソッド定義、フィールド定義）からLuaDocアノテーション付きの型定義ファイルを生成する。

### 本機能の処理概要

**業務上の目的・背景**：Luaは動的型付け言語であるため、外部ライブラリやフレームワークのAPI情報をLanguage Serverに認識させるには、型定義ファイル（メタファイル）が必要となる。本機能は、構造化されたAPIメタデータからLuaDocアノテーション付きのLuaファイルを自動生成し、コード補完や型チェックを可能にする。C#やUnityなどの外部フレームワークをLuaから使用する際に特に有用である。

**機能の利用シーン**：外部フレームワーク（Unity、Love2D等）のAPI定義をインポートする際、カスタムAPIのドキュメント生成、ビルトイン関数のメタデータ更新などで利用される。

**主要な処理内容**：
1. メタデータ構造の解析（classes, methods, fields）
2. LuaDocアノテーションの生成（@class, @field, @param, @return）
3. ネームスペース別のファイル分割
4. ソース位置情報（@source）の付与
5. コメントのフォーマット処理
6. 非同期処理による大量データ対応

**関連システム・外部連携**：utilityモジュールのマルチテーブル機能、awaitモジュールの非同期処理、progressモジュールの進捗表示、言語モジュールのローカライズを使用。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 45 | APIレポート | 主機能 | APIメタデータをレポート・生成する内部処理 |

## 機能種別

ビルド / コード生成

## 入力仕様

### 入力パラメータ

#### m.build関数

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path | string | Yes | 出力先ディレクトリパス | 有効なパスであること |
| api | meta | Yes | メタデータ構造 | 必要なフィールドを持つこと |

### メタデータ構造（meta）

```lua
---@class meta
---@field root    string           -- ルートネームスペース名
---@field classes meta.class[]     -- クラス定義の配列

---@class meta.class
---@field name        string       -- クラス名
---@field comment     string       -- クラスのコメント
---@field location    string       -- ソース位置（file#line形式）
---@field namespace   string       -- ネームスペース
---@field baseClass   string       -- 基底クラス名
---@field attribute   string       -- 属性
---@field interface   string[]     -- 実装インターフェース
---@field fields      meta.field[] -- フィールド定義
---@field methods     meta.method[]-- メソッド定義

---@class meta.field
---@field name     string          -- フィールド名
---@field typeName string          -- 型名
---@field comment  string          -- コメント
---@field location string          -- ソース位置

---@class meta.method
---@field name           string    -- メソッド名
---@field comment        string    -- コメント
---@field location       string    -- ソース位置
---@field isStatic       boolean   -- 静的メソッドか
---@field returnTypeName string    -- 戻り値の型名
---@field params         {name: string, typeName: string}[] -- パラメータ
```

### 入力データソース

- 外部フレームワークのAPIメタデータ（JSON/Lua形式）
- ビルトイン関数の定義データ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ファイル群 | .lua | ネームスペース別のメタファイル（LuaDoc付き） |

### 出力ファイルフォーマット

```lua
---@meta

---
--クラスのコメント
---
---@source path/to/source.cs:123
---@class Namespace.ClassName: BaseClass
---
--フィールドのコメント
---
---@source path/to/source.cs:125
---@field fieldName FieldType
---@source path/to/source.cs:123
Namespace.ClassName = {}

---
--メソッドのコメント
---
---@source path/to/source.cs:130
---@param param1 ParamType
---@return ReturnType
function Namespace.ClassName:methodName(param1) end
```

### 出力先

- 指定されたpathディレクトリ配下
- ネームスペース別の.luaファイル

## 処理フロー

### 処理シーケンス

```
build処理:
1. ファイルテーブルを初期化
   └─ util.multiTable(2, function() return {'---@meta'} end)
2. ルートクラステキストを生成
   └─ buildRootText(api)
3. 各クラスを処理
   └─ for i, class in ipairs(api.classes) do
4. 進捗表示を更新
   └─ proc:setMessage(space)
5. クラステキストを生成
   └─ buildText(api.root, class)
6. ネームスペース別にファイルに追加
   └─ files[space][#files[space]+1] = text
7. 非同期遅延（UI応答性維持）
   └─ await.delay()
8. 各ファイルを書き出し
   └─ util.saveFile(path..space..'.lua', ...)

buildText処理:
1. コメントを追加
   └─ addComments(lines, class.comment)
2. @sourceアノテーションを追加
   └─ ---@source location
3. @classアノテーションを生成
   └─ 継承がある場合は: BaseClassを付与
4. 各フィールドを処理
   └─ @fieldアノテーションを追加
5. クラステーブル定義を追加
   └─ Namespace.ClassName = {}
6. 各メソッドを処理
   └─ addMethod(lines, name, method)
7. テキストを連結して返却
   └─ table.concat(lines, '\n')
```

### フローチャート

```mermaid
flowchart TD
    subgraph build["build処理"]
        B1[ファイルテーブル初期化] --> B2[ルートテキスト生成]
        B2 --> B3[クラスループ開始]
        B3 --> B4[進捗更新]
        B4 --> B5[buildText呼び出し]
        B5 --> B6[ファイルに追加]
        B6 --> B7[await.delay]
        B7 --> B8{次のクラス?}
        B8 -->|Yes| B3
        B8 -->|No| B9[ファイル書き出しループ]
        B9 --> B10[util.saveFile]
        B10 --> B11{次のファイル?}
        B11 -->|Yes| B9
        B11 -->|No| B12[完了]
    end

    subgraph buildText["buildText処理"]
        T1[lines初期化] --> T2[クラスコメント追加]
        T2 --> T3[@source追加]
        T3 --> T4{baseClass有り?}
        T4 -->|Yes| T5[@class:BaseClass]
        T4 -->|No| T6[@class]
        T5 --> T7[フィールドループ]
        T6 --> T7
        T7 --> T8[@field追加]
        T8 --> T9{次のフィールド?}
        T9 -->|Yes| T7
        T9 -->|No| T10[クラス定義追加]
        T10 --> T11[メソッドループ]
        T11 --> T12[addMethod呼び出し]
        T12 --> T13{次のメソッド?}
        T13 -->|Yes| T11
        T13 -->|No| T14[テキスト連結]
        T14 --> T15[返却]
    end

    subgraph addMethod["addMethod処理"]
        M1[コメント追加] --> M2[@source追加]
        M2 --> M3[パラメータループ]
        M3 --> M4[@param追加]
        M4 --> M5{次のパラメータ?}
        M5 -->|Yes| M3
        M5 -->|No| M6{戻り値有り?}
        M6 -->|Yes| M7[@return追加]
        M6 -->|No| M8[関数定義追加]
        M7 --> M8
        M8 --> M9[完了]
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-90-01 | 有効なメソッド名 | メソッド名は[a-zA-Z_][a-zA-Z0-9_]*形式のみ処理 | addMethod呼び出し時 |
| BR-90-02 | Void戻り値 | 戻り値がVoidまたは空の場合は@returnを省略 | addMethod呼び出し時 |
| BR-90-03 | 静的メソッド | isStatic=trueの場合は':'でなく'.'を使用 | addMethod呼び出し時 |
| BR-90-04 | ネームスペース分割 | ネームスペースが空の場合はrootを使用 | ファイル分割時 |
| BR-90-05 | ソース位置変換 | #を:に置換（file#line → file:line） | @source生成時 |
| BR-90-06 | コメント改行 | 改行コードをLua形式に変換（\n → \n--） | addComments呼び出し時 |

### 計算ロジック

ソース位置変換:
```lua
('---@source %s'):format(method.location:gsub('#', ':'))
```

完全修飾名の構築:
```lua
local function mergeString(...)
    local buf = {}
    for i = 1, select('#', ...) do
        local str = select(i, ...)
        if str ~= '' then
            buf[#buf+1] = str
        end
    end
    return table.concat(buf, '.')
end
```

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無効なメソッド名 | メソッド名が不正な形式 | スキップして処理継続 |
| - | ファイル書き込み失敗 | 出力先に書き込めない | エラーログを出力 |

### リトライ仕様

リトライは行わない。エラー発生時はスキップまたはログ出力して処理を継続する。

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

本機能はトランザクションを使用しない。

## パフォーマンス要件

- 大量のクラス（数千件以上）を処理できること
- await.delay()によりUI応答性を維持
- 進捗表示でユーザーに処理状況を通知

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

- 出力先パスの検証は呼び出し元で行う
- 生成されるコードは実行されず、型定義としてのみ使用

## 備考

生成されるファイルは`---@meta`で始まり、Language Serverにメタファイルとして認識される。メタファイル内のコードは実行されず、純粋に型情報として使用される。

---

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

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

### 推奨読解順序

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

メタデータの型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | build-meta.lua | `script/provider/build-meta.lua` | 型定義（8-35行目） |

**読解のコツ**:
- `meta`: ルートと全クラスを含む構造
- `meta.class`: 個々のクラス定義
- `meta.field`: フィールド定義
- `meta.method`: メソッド定義

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | build-meta.lua | `script/provider/build-meta.lua` | mergeString, addComments（39-57行目） |

**主要処理フロー**:
- **39-48行目**: mergeString - ドット区切りで文字列を結合
- **50-57行目**: addComments - コメントをLuaDoc形式に変換

#### Step 3: addMethod関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | build-meta.lua | `script/provider/build-meta.lua` | addMethod関数（62-84行目） |

**主要処理フロー**:
- **63-65行目**: メソッド名の検証
- **66-67行目**: コメントと@source追加
- **68-72行目**: @paramアノテーション生成
- **73-76行目**: @returnアノテーション生成
- **77-82行目**: 関数定義生成（静的/インスタンスメソッド）

#### Step 4: buildText関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | build-meta.lua | `script/provider/build-meta.lua` | buildText関数（89-116行目） |

**主要処理フロー**:
- **91-92行目**: クラスコメント追加
- **93-98行目**: @classアノテーション（継承対応）
- **100-104行目**: @fieldアノテーション
- **106-108行目**: クラステーブル定義
- **111-113行目**: メソッド追加

#### Step 5: build関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | build-meta.lua | `script/provider/build-meta.lua` | build関数（130-151行目） |

**主要処理フロー**:
- **132-134行目**: ファイルテーブル初期化
- **136行目**: ルートテキスト追加
- **138-146行目**: クラスループと進捗表示
- **148-150行目**: ファイル書き出し

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

```
m.build(path, api)
    │
    ├─ util.multiTable(2, fn) → files[namespace]
    │
    ├─ buildRootText(api)
    │      └─ @class/@source生成 → files[api.root]
    │
    ├─ for class in api.classes
    │      │
    │      ├─ progress.create() / setMessage / setPercentage
    │      │
    │      ├─ buildText(api.root, class)
    │      │      ├─ addComments(lines, class.comment)
    │      │      ├─ @class/@field生成
    │      │      └─ addMethod(lines, name, method)
    │      │             ├─ メソッド名検証
    │      │             └─ @param/@return/function生成
    │      │
    │      └─ await.delay()
    │
    └─ for space, texts in files
           └─ util.saveFile(path/space.lua, concat)
```

### データフロー図

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

api (meta構造)
    │
    ├─ root ───▶ buildRootText ───▶ files[root]
    │
    └─ classes[] ───▶ buildText ───▶ files[namespace]
           │
           ├─ comment ───▶ addComments ───▶ ---コメント行
           ├─ location ───▶ ---@source
           ├─ name/baseClass ───▶ ---@class
           ├─ fields[] ───▶ ---@field
           └─ methods[] ───▶ addMethod
                  │
                  ├─ params[] ───▶ ---@param
                  ├─ returnTypeName ───▶ ---@return
                  └─ function definition

files[namespace]
    │
    └───▶ util.saveFile ───▶ {namespace}.lua
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| build-meta.lua | `script/provider/build-meta.lua` | ソース | メタデータ構築の実装 |
| utility.lua | `script/utility.lua` | ソース | multiTable, saveFile |
| await.lua | `script/await.lua` | ソース | 非同期処理 |
| progress.lua | `script/progress.lua` | ソース | 進捗表示 |
| language.lua | `script/language.lua` | ソース | ローカライズ |
