# 機能設計書 78-FFIサポート

## 概要

本ドキュメントは、Lua Language ServerにおけるLuaJIT FFI定義解析機能の設計を記述する。この機能は、LuaJITのFFI（Foreign Function Interface）で使用されるC言語定義を解析し、型情報やLuaアノテーションを自動生成する。

### 本機能の処理概要

**業務上の目的・背景**：LuaJITプロジェクトでは、C言語ライブラリとの連携にFFIを使用する。`ffi.cdef`で定義されたC言語の構造体、関数、列挙型などに対して、Lua Language Serverが型情報を提供できれば、開発者の生産性が大幅に向上する。本機能はC言語定義を解析し、対応するLuaアノテーションを生成することで、FFIコードに対するインテリセンスを実現する。

**機能の利用シーン**：
- `ffi.cdef`内のC言語構造体の補完・ホバー情報表示
- FFI関数呼び出し時のシグネチャヘルプ
- C言語列挙型の値補完
- FFIメタデータの再読み込み

**主要な処理内容**：
1. `ffi.cdef`呼び出しからC言語コードを抽出
2. C言語パーサーによる構文解析
3. 構造体、共用体、関数、列挙型、typedefの処理
4. Luaアノテーション形式への変換
5. メタファイルとしての出力

**関連システム・外部連携**：
- C言語パーサー（c-parser/）
- ワークスペース管理システム
- ファイルシステム（メタファイル出力）
- VM（型参照解決）

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 35 | FFIメタデータ再読込 | 主画面 | FFIメタデータを再読み込みするコマンド処理 |

## 機能種別

コード解析 / 型情報生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| codes | string[] | Yes | ffi.cdefで定義されたCコード | C言語構文 |
| fileDir | fs.path | Yes | 出力先ディレクトリ | 書き込み可能なパス |
| uri | uri | Yes | 元のLuaファイルのURI | 有効なファイルURI |

### 入力データソース

- Luaファイル内の`ffi.cdef`呼び出し
- `ffi.cdef`の引数として渡されたC言語コード

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| metaFile | file | 生成されたLuaアノテーションファイル |

### 出力先

- ワークスペースのメタデータディレクトリ

## 処理フロー

### 処理シーケンス

```
1. ffi.cdef呼び出しの検出
   └─ searchCode()でコード抽出
2. C言語パーサーによる解析
   └─ cdriver.process_context()
3. AST走査と変換
   └─ 構造体、関数、列挙型等を処理
4. Luaアノテーション生成
   └─ ---@class, ---@field, ---@alias等
5. メタファイル出力
   └─ utility.saveFile()
```

### フローチャート

```mermaid
flowchart TD
    A[ffi.cdef検出] --> B[C言語コード抽出]
    B --> C[C言語パーサー解析]
    C --> D{AST種別判定}
    D -->|struct/union| E[buildStructOrUnion]
    D -->|function| F[buildFunction]
    D -->|enum| G[buildEnum]
    D -->|typedef| H[buildTypedef]
    E --> I[---@class生成]
    F --> J[---@param/return生成]
    G --> K[---@alias生成]
    H --> L[型エイリアス生成]
    I --> M[テキスト結合]
    J --> M
    K --> M
    L --> M
    M --> N[メタファイル出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-78-01 | 型マッピング | C基本型をLua型にマッピング（int→integer, float→number等） | 常時 |
| BR-78-02 | ポインタ参照解除 | 構造体/共用体へのポインタは参照解除 | 構造体ポインタ時 |
| BR-78-03 | Luaキーワード回避 | Luaの予約語は接頭辞_を付加 | 予約語使用時 |
| BR-78-04 | 名前空間 | 生成型はffi.namespace*.で修飾 | 常時 |

### 計算ロジック

**型変換ロジック**:
```lua
local knownTypes = {
    ["bool"] = 'boolean',
    ["char"] = 'integer',
    ["int"] = 'integer',
    ["float"] = 'number',
    ["double"] = 'number',
    -- ... 他の型
}

function builder:getType(name)
    if knownTypes[name] then
        return knownTypes[name]
    end
    return 'ffi.namespace*.' .. name
end
```

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

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

本機能はデータベース操作を行わない。ファイルシステムへのメタファイル出力のみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | パースエラー | C言語構文エラー | nil返却、処理スキップ |
| - | 出力エラー | ファイル書き込み失敗 | エラーログ出力 |

### リトライ仕様

リトライは行わない。エラー発生時は該当部分をスキップ。

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

トランザクション管理は不要。

## パフォーマンス要件

- 大規模なCヘッダーファイルの処理に対応
- 非同期処理でブロッキングを回避

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

- C言語コードの解析のみで、実行は行わない
- 出力先はワークスペース内に限定

## 備考

- C99構文をサポート
- プリプロセッサディレクティブは部分的にサポート
- 複雑な型定義は簡略化される場合がある

---

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

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

### 推奨読解順序

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

FFIビルダーの構造と型マッピングを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | init.lua | `script/plugins/ffi/init.lua` | 10-57行目: knownTypes - C型→Lua型マッピング |
| 1-2 | init.lua | `script/plugins/ffi/init.lua` | 59-74行目: blackKeyWord - Lua予約語回避 |
| 1-3 | init.lua | `script/plugins/ffi/init.lua` | 84-85行目: ffi.builderクラス定義 |

**読解のコツ**: knownTypesでC言語の基本型がLuaのinteger/number/boolean等にマッピングされている。

#### Step 2: 型解決ロジックを理解する

型名からLua型への変換処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | init.lua | `script/plugins/ffi/init.lua` | 113-145行目: getType関数 |

**主要処理フロー**:
- **141-142行目**: knownTypesからの変換
- **144行目**: 未知の型はffi.namespace*.で修飾

#### Step 3: 構造体/共用体変換を理解する

C言語のstruct/unionをLuaクラスに変換。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | init.lua | `script/plugins/ffi/init.lua` | 177-185行目: buildStructOrUnion関数 |

**主要処理フロー**:
- **178行目**: ---@class生成
- **179-183行目**: 各フィールドを---@fieldに変換

#### Step 4: 関数変換を理解する

C言語関数をLua関数定義に変換。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | init.lua | `script/plugins/ffi/init.lua` | 187-203行目: buildFunction関数 |

**主要処理フロー**:
- **189-192行目**: 各パラメータを---@paramに変換
- **197-200行目**: 戻り値を---@returnに変換
- **202行目**: function m.name(params) end生成

#### Step 5: コード検索と結合を理解する

ffi.cdefからのコード抽出と最終出力。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | searchCode.lua | `script/plugins/ffi/searchCode.lua` | 49-69行目: メイン検索関数 |
| 5-2 | init.lua | `script/plugins/ffi/init.lua` | 338-353行目: compileCodes関数 |
| 5-3 | init.lua | `script/plugins/ffi/init.lua` | 356-371行目: build_single関数 |

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

```
m.build_single (公開API)
    │
    ├─ m.compileCodes(codes)
    │      │
    │      └─ cdriver.process_context(code)
    │             └─ C言語パーサー実行
    │
    ├─ compileCode(lines, asts, b)
    │      │
    │      └─ builder.switch_ast
    │             │
    │             ├─ buildStructOrUnion
    │             │      └─ ---@class, ---@field生成
    │             │
    │             ├─ buildFunction
    │             │      └─ ---@param, ---@return, function生成
    │             │
    │             ├─ buildEnum
    │             │      └─ ---@alias, m.ENUM_VALUE生成
    │             │
    │             └─ buildTypedef
    │                    └─ ---@alias生成
    │
    └─ utility.saveFile(fullPath, text)
           └─ メタファイル出力
```

### データフロー図

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

ffi.cdef("...") ─────▶ searchCode() ─────────────▶ C言語コード抽出
                             │
                             ▼
                      cdriver.process_context()
                             │
                             ▼
                      C言語AST
                             │
                             ▼
                      compileCode() ─────────────▶ Luaアノテーション
                             │                    ---@class
                             │                    ---@field
                             │                    ---@param
                             │                    ---@return
                             │                    ---@alias
                             ▼
                      build_single() ────────────▶ メタファイル
                                                  (.lua)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| init.lua | `script/plugins/ffi/init.lua` | ソース | FFIサポートのメインモジュール |
| searchCode.lua | `script/plugins/ffi/searchCode.lua` | ソース | ffi.cdefからのコード抽出 |
| cdefRerence.lua | `script/plugins/ffi/cdefRerence.lua` | ソース | cdef参照解決 |
| cdriver.lua | `script/plugins/ffi/c-parser/cdriver.lua` | ソース | C言語パーサードライバー |
| c99.lua | `script/plugins/ffi/c-parser/c99.lua` | ソース | C99文法定義 |
| ctypes.lua | `script/plugins/ffi/c-parser/ctypes.lua` | ソース | C型システム |
| typed.lua | `script/plugins/ffi/c-parser/typed.lua` | ソース | 型付きAST |
