# 画面設計書 3-補完アイテム詳細

## 概要

本ドキュメントは、Lua Language Serverの「補完アイテム詳細」機能の設計を記載したものである。LSP（Language Server Protocol）の `completionItem/resolve` メソッドに対応し、補完リストで選択された候補の詳細情報を遅延取得する機能を提供する。

### 本画面の処理概要

**業務上の目的・背景**：
補完リストに多数の候補が含まれる場合、全候補の詳細情報を事前に計算すると応答速度が低下する。本機能は、ユーザーが補完候補を選択した時点で詳細情報を取得する「遅延ロード」パターンを実装し、初期応答速度と詳細情報の両立を実現する。これにより、大規模コードベースでも快適な補完体験を提供できる。

**画面へのアクセス方法**：
エディタ（VS Code等）上で補完リストが表示された状態で、矢印キーやマウスで候補を選択すると自動的に詳細情報がリクエストされる。ユーザーが明示的に操作する必要はなく、エディタが自動的に処理する。

**主要な操作・処理内容**：
1. エディタが補完候補を選択し、LSPサーバーへ `completionItem/resolve` リクエストを送信
2. リクエストに含まれる `data.id` からキャッシュされた補完情報を取得
3. `detail`（型情報）と `description`（ドキュメント）を計算
4. `additionalTextEdits`（追加編集、require文など）を計算
5. 拡張された補完アイテムをエディタへ返却
6. エディタが補完ポップアップの詳細欄を更新

**画面遷移**：
- 遷移元：コード補完（textDocument/completion）
- 遷移先：なし（同一ポップアップ内で更新）
- 関連遷移：補完確定後、additionalTextEditsが適用される

**権限による表示制御**：
本機能に権限による表示制御はない。補完機能が有効な場合、本機能も自動的に有効となる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | 補完項目解決 (completionItem/resolve) | 主機能 | 選択した補完候補の詳細情報を取得する主処理 |
| 17 | ホバー情報 (textDocument/hover) | 補助機能 | 補完候補のホバー情報を取得 |

## 画面種別

情報表示（ポップアップ詳細欄）

## URL/ルーティング

LSPメソッド: `completionItem/resolve`

**リクエストパラメータ**:
```json
{
  "label": "functionName",
  "kind": 3,
  "data": {
    "uri": "file:///path/to/file.lua",
    "id": 12345
  }
}
```

## 入出力項目

### 入力項目

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| label | string | Yes | 補完候補のラベル |
| kind | integer | Yes | 補完候補の種別 |
| data.uri | string | Yes | 対象ファイルのURI |
| data.id | integer | Yes | スタック内のコールバックID |

### 出力項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| label | string | 補完候補のラベル（変更なし） |
| kind | integer | 補完候補の種別（変更なし） |
| detail | string | 型情報などの詳細（追加/更新） |
| documentation | MarkupContent | ドキュメント情報（追加/更新） |
| additionalTextEdits | TextEdit[] | 追加のテキスト編集（追加） |

## 表示項目

### 補完詳細欄表示内容

| 表示項目 | 形式 | 説明 |
|---------|------|------|
| 詳細（detail） | テキスト | 型情報（例: `function (x: number, y: number) -> number`） |
| ドキュメント | Markdown | LuaDocからの説明文、使用例など |

## イベント仕様

### 1-補完アイテム解決処理

1. エディタが補完候補を選択し、LSPサーバーへ `completionItem/resolve` リクエストを送信
2. `provider.lua` の `completionItem/resolve` ハンドラが呼び出される
3. `item.data` が存在しない場合、そのまま `item` を返却
4. `data.id` を使用して `resolveStack` 関数を呼び出し
5. スタックに登録されたコールバック関数を実行
6. `buildDetail` で型情報を構築
7. `buildDesc` でドキュメントを構築
8. `additionalTextEdits` があれば追加
9. 拡張された `item` をエディタへ返却

### 2-スタック機構

補完処理時に詳細情報の計算を遅延するため、スタック機構が使用される：

1. `completion` 関数内で `stack(source, callback)` を呼び出し
2. 一意のIDを生成し、コールバック関数と共にスタックに保存
3. `resolve` 時に `resolveStack(id)` でコールバックを取得・実行
4. コールバックは新しいソースオブジェクトを使用して詳細を計算

## データベース更新仕様

本機能はデータベース操作を行わない（読み取り専用）。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|---------------|---------|
| なし | - | - | - |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| data が存在しない | 元の item をそのまま返却 |
| data.id が無効 | 警告ログ出力、元の item を返却 |
| ファイルが存在しない | 元の item をそのまま返却 |
| コールバックが nil を返却 | 元の item をそのまま返却 |

## 備考

- スタックは `clearStack()` により補完処理開始時にクリアされる
- コールバック関数は非同期（async）で実行される
- ソースオブジェクトは `findSource` で再取得されるため、ファイル変更に対応
- `additionalTextEdits` は require 文の自動挿入などに使用される

---

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

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

### 推奨読解順序

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

補完アイテム解決で扱うデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | completion.lua | `script/core/completion/completion.lua` | スタック機構の定義 |

**読解のコツ**: `stack` 関数と `stacks` テーブルの関係を理解する。

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

処理の起点となるプロバイダーファイルを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | provider.lua | `script/provider/provider.lua` | LSPメソッドの登録とリクエスト処理 |

**主要処理フロー**:
1. **732-771行目**: `completionItem/resolve` ハンドラの定義
2. **736-738行目**: data チェック
3. **746行目**: `core.resolve(id)` 呼び出し
4. **750-754行目**: detail と documentation の更新
5. **755-768行目**: additionalTextEdits の処理

#### Step 3: コア解決ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | completion.lua | `script/core/completion/completion.lua` | スタック機構と解決処理 |

**主要処理フロー（completion.lua）**:
- **34-56行目**: `stack` 関数 - コールバックをスタックに登録
- **58-60行目**: `clearStack` 関数 - スタックをクリア
- **62-71行目**: `resolveStack` 関数 - IDからコールバックを取得・実行
- **236-244行目**: `buildDetail` 関数 - 型情報の構築
- **278-285行目**: `buildDesc` 関数 - ドキュメントの構築
- **2399-2403行目**: `resolve` 関数 - 公開インターフェース

#### Step 4: 補助モジュールを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | find-source.lua | `script/core/find-source.lua` | ソースオブジェクトの再取得 |
| 4-2 | hover/init.lua | `script/core/hover/init.lua` | ホバー情報取得（ドキュメント用） |

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

```
completionItem/resolve (provider.lua:732)
    │
    ├─ item.data チェック
    │      └─ data なし: item をそのまま返却
    │
    ├─ files.getState(uri)
    │
    └─ core.resolve(id)
           │
           └─ resolveStack(id)
                  │
                  ├─ stacks[id] からコールバック取得
                  │
                  └─ callback() 実行
                         │
                         ├─ files.getState(uri)
                         │
                         ├─ findSource(state, pos, accept)
                         │
                         ├─ buildDetail(newSource)
                         │      └─ vm.getInfer().view()
                         │
                         └─ buildDesc(newSource)
                                └─ getHover.get(source, 1)
```

### データフロー図

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

CompletionItem      ───▶ data.id 取得
                         │
                         ▼
                    resolveStack(id)               ───▶  callback関数
                         │
                         ▼
                    findSource(state, pos)         ───▶  新Source
                         │
                         ▼
                    buildDetail() + buildDesc()    ───▶  detail, documentation
                         │
                         ▼
                    additionalTextEdits処理        ───▶  TextEdit[]
                         │
                         ▼
                    item更新                       ───▶  拡張CompletionItem
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| provider.lua | `script/provider/provider.lua` | ソース | LSPプロバイダー・エントリーポイント |
| completion.lua | `script/core/completion/completion.lua` | ソース | 補完処理・スタック機構 |
| find-source.lua | `script/core/find-source.lua` | ソース | ソースオブジェクト検索 |
| hover/init.lua | `script/core/hover/init.lua` | ソース | ホバー情報取得 |
| vm/init.lua | `script/vm/init.lua` | ソース | 型推論エンジン |
| converter.lua | `script/proto/converter.lua` | ソース | LSP位置変換 |
