# 機能設計書 2-補完アイテム解決

## 概要

本ドキュメントは、Clojure LSP サーバーにおける補完アイテム解決機能の設計仕様を記載する。この機能は LSP プロトコルの `completionItem/resolve` リクエストに対応し、補完候補選択時にドキュメントや追加テキスト編集を遅延ロードする。

### 本機能の処理概要

**業務上の目的・背景**：コード補完機能において、全ての補完候補に対して詳細情報（ドキュメント、追加編集等）を事前に計算すると、パフォーマンスが著しく低下する。特に数百件の補完候補がある場合、各候補のドキュメント取得やrequire追加のための編集計算は高コストである。本機能は、ユーザーが補完候補を選択した時点で初めて詳細情報を計算する遅延解決パターンを実装し、補完リスト表示の高速化を実現する。

**機能の利用シーン**：開発者が補完候補リストから特定の候補を選択（ハイライト）した際に、エディタが本機能を呼び出す。例えば、未インポートの名前空間の関数を補完候補から選択した場合、その関数のドキュメントと、require文を追加するための編集情報が遅延ロードされる。

**主要な処理内容**：
1. 補完アイテムの data フィールドから遅延解決タイプを抽出
2. 解決タイプに応じた処理の実行（ドキュメント取得、エイリアス追加編集）
3. 解決結果を補完アイテムに付与して返却

**関連システム・外部連携**：ホバー機能（ドキュメント生成）、add-missing-libspec（require追加編集）

**権限による制御**：本機能に権限による実行制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本プロジェクトは LSP サーバー実装であり、UI 画面は存在しない。エディタの補完候補詳細表示から呼び出される。 |

## 機能種別

データ検索処理 / 遅延評価処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| item | CompletionItem | Yes | 解決対象の補完アイテム | - |
| item.data | object | No | 遅延解決用データ | - |
| item.data.unresolved | array | No | 未解決項目のリスト | - |

### 入力データソース

- 補完リクエストで返却された補完アイテムの data フィールド
- 解析済みドキュメントデータ（db）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| label | string | 補完候補の表示名（入力から継承） |
| kind | integer | 補完候補の種類（入力から継承） |
| documentation | string/MarkupContent | 解決されたドキュメント文字列 |
| additional-text-edits | TextEdit[] | 解決された追加編集（require追加等） |

### 出力先

LSP プロトコルを通じてエディタクライアントへ返却

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ handlers/completion-resolve-item が completionItem/resolve を受信

2. 未解決項目の抽出
   └─ item.data.unresolved から解決すべき項目リストを取得

3. 解決タイプ別処理
   ├─ "documentation": ドキュメント取得
   └─ "alias": require追加編集の計算

4. 結果のマージ
   └─ 解決結果を補完アイテムに付与

5. レスポンス返却
   └─ data フィールドを除去して返却
```

### フローチャート

```mermaid
flowchart TD
    A[completionItem/resolve 受信] --> B{data.unresolved あり?}
    B -->|No| C[item をそのまま返却]
    B -->|Yes| D[unresolved リストを取得]
    D --> E{解決タイプ?}
    E -->|documentation| F[find-element-by-ns/position]
    E -->|alias| G[add-known-alias 編集計算]
    F --> H[hover-documentation 呼び出し]
    G --> I[additional-text-edits 付与]
    H --> J[documentation 付与]
    I --> K[data フィールド除去]
    J --> K
    K --> L[解決済みアイテム返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 遅延解決対応 | クライアントが resolveSupport を持つ場合のみ遅延解決を使用 | 補完アイテム生成時 |
| BR-02 | データ除去 | 解決後は data フィールドを除去して返却 | 全解決処理 |
| BR-03 | 複数解決 | 複数の未解決項目がある場合は順次解決 | unresolved が複数要素 |

### 計算ロジック

- ドキュメント解決: find-element-by-ns または find-element-by-position で要素を特定し、hover-documentation を呼び出す
- エイリアス解決: add-known-alias で require 追加のための編集を計算

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 要素検索 | db :analysis | SELECT | シンボル定義の検索 |

### テーブル別操作詳細

#### db :analysis

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | :var-definitions | uri, name-row, name-col でマッチング | 要素特定用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 解決スキップ | 要素が見つからない場合 | 入力アイテムをそのまま返却 |

### リトライ仕様

リトライは行わない。

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

本機能は読み取り専用であり、トランザクション管理は不要。

## パフォーマンス要件

- 応答時間: 通常 50ms 以内（ドキュメント解決時）
- 解決処理はユーザーが候補を選択した時点で実行されるため、リアルタイム性が求められる

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

- 外部ネットワーク通信なし
- ファイルシステムアクセスは解析対象ファイルのみ

## 備考

- クライアントの resolveSupport.properties に "documentation" と "additionalTextEdits" が含まれる場合に遅延解決を活用
- js-require フラグにより ClojureScript の JavaScript require にも対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | completion.clj | `lib/src/clojure_lsp/feature/completion.clj` | add-unresolved（146-148行目）で遅延解決データの付与方法を確認 |
| 1-2 | completion.clj | `lib/src/clojure_lsp/feature/completion.clj` | completion-item-with-unresolved-documentation（177-184行目）でドキュメント遅延解決の設定を確認 |

**読解のコツ**: data フィールドの構造として、:unresolved キーの下に [タイプ, 引数マップ] のベクタが格納される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | completion-resolve-item 関数（270-273行目）が LSP リクエストのエントリーポイント |
| 2-2 | completion.clj | `lib/src/clojure_lsp/feature/completion.clj` | resolve-item 関数（774-785行目）がメインロジック |

**主要処理フロー**:
1. **774-776行目**: db を deref し、item から data を除去
2. **777行目**: unresolved リストが存在するか確認
3. **778-783行目**: reduce で各未解決項目を順次処理

#### Step 3: 解決処理の詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | completion.clj | `lib/src/clojure_lsp/feature/completion.clj` | resolve-unresolved マルチメソッド（753-771行目）で解決タイプ別の処理を確認 |
| 3-2 | completion.clj | `lib/src/clojure_lsp/feature/completion.clj` | "documentation" の解決（756-764行目）- 要素検索とドキュメント生成 |
| 3-3 | completion.clj | `lib/src/clojure_lsp/feature/completion.clj` | "alias" の解決（766-771行目）- require 追加編集の計算 |

**主要処理フロー**:
- **756-764行目**: ns がある場合は find-element-by-ns、ない場合は find-element-by-position で要素を特定し、completion-item-with-documentation を呼び出す
- **766-771行目**: safe-zloc-of-file でファイルを解析し、completion-item-with-alias-edit で編集を計算

#### Step 4: ドキュメント生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | completion.clj | `lib/src/clojure_lsp/feature/completion.clj` | completion-item-with-documentation（150-162行目）でドキュメント付与処理を確認 |
| 4-2 | hover.clj | `lib/src/clojure_lsp/feature/hover.clj` | hover-documentation 関数でドキュメント生成の詳細を確認 |

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

```
handlers/completion-resolve-item
    │
    └─ f.completion/resolve-item
           │
           ├─ [data.unresolved を reduce で処理]
           │
           └─ resolve-unresolved (multimethod)
                  │
                  ├─ "documentation"
                  │      ├─ find-element-by-ns
                  │      │      └─ q/find-definition
                  │      ├─ find-element-by-position
                  │      │      └─ q/find-element-under-cursor
                  │      └─ completion-item-with-documentation
                  │             └─ f.hover/hover-documentation
                  │
                  └─ "alias"
                         ├─ parser/safe-zloc-of-file
                         └─ completion-item-with-alias-edit
                                └─ f.add-missing-libspec/add-known-alias
```

### データフロー図

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

completionItem/resolve ──▶ handlers/completion-resolve-item ──▶ CompletionItem
  - CompletionItem               │
    - label                      ▼
    - kind                  resolve-item
    - data                       │
      - unresolved[]             ├──▶ "documentation" 解決
                                 │      └─ hover-documentation
                                 │
                                 ├──▶ "alias" 解決
                                 │      └─ add-known-alias
                                 │
                                 └──▶ data フィールド除去
                                        │
                                        ▼
                                   解決済み CompletionItem
                                     - label
                                     - kind
                                     - documentation
                                     - additional-text-edits
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| completion.clj | `lib/src/clojure_lsp/feature/completion.clj` | ソース | 補完アイテム解決のメインロジック |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | LSP リクエストハンドラー |
| hover.clj | `lib/src/clojure_lsp/feature/hover.clj` | ソース | ドキュメント生成 |
| add_missing_libspec.clj | `lib/src/clojure_lsp/feature/add_missing_libspec.clj` | ソース | require 追加編集 |
| queries.clj | `lib/src/clojure_lsp/queries.clj` | ソース | 要素検索クエリ |
| parser.clj | `lib/src/clojure_lsp/parser.clj` | ソース | コード解析 |
| completion_test.clj | `lib/test/clojure_lsp/feature/completion_test.clj` | テスト | ユニットテスト |
