# 画面設計書 18-補完アイテム解決（completionItem/resolve）

## 概要

選択された補完アイテムの詳細情報（ドキュメント、追加テキスト編集等）を遅延解決するLSPメソッドの設計書である。

### 本画面の処理概要

本画面は、LSP標準の `completionItem/resolve` リクエストを処理し、補完リストで選択された補完アイテムの詳細情報を遅延的に解決して返却する処理を担当する。スニペットの解決、自動インポートの追加テキスト編集生成、dfmtによるコードフォーマットを行う。

**業務上の目的・背景**：補完リスト表示時に全アイテムの詳細情報を事前に計算するとパフォーマンスが低下するため、ユーザーがアイテムを選択した時点で詳細情報を遅延取得する方式を採用している。これにより、補完リスト表示の応答性を維持しつつ、選択時には完全な情報を提供できる。

**画面へのアクセス方法**：補完リスト（No.17）でユーザーが補完アイテムを選択（ハイライト）した際に、クライアントからcompletionItem/resolveリクエストが自動的に送信される。

**主要な操作・処理内容**：
1. クライアントからcompletionItem/resolveリクエストを受信
2. CompletionItemのdataフィールドからメタデータを取得
3. 未解決スニペット（resolved=false）の場合、SnippetsComponentで解決
4. importsフィールドが存在する場合、ImporterComponentで追加インポートのTextEditを生成
5. formatフィールドが存在する場合、dfmtでコードフォーマットを適用
6. 解決済みのCompletionItemを返却

**画面遷移**：コード補完（No.17）で補完候補が選択された後に呼び出される。resolve後のCompletionItemがエディタに適用される。

**権限による表示制御**：権限による表示制御は存在しない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | 補完アイテム解決 (completionItem/resolve) | 主機能 | 選択された補完アイテムの詳細情報（DDoc, 追加テキスト編集, dfmtフォーマット）を遅延解決する |
| 29 | ドキュメントフォーマット (textDocument/formatting) | 補助機能 | 補完アイテム解決時にdfmtによるコードフォーマットが適用される |

## 画面種別

LSPレスポンス（補完アイテム詳細）

## URL/ルーティング

LSP標準メソッド: `completionItem/resolve`

- リクエスト: `CompletionItem`
- レスポンス: `CompletionItem`（解決済み）

## 入出力項目

| 項目名 | 型 | 入力/出力 | 説明 |
|--------|-----|----------|------|
| item | CompletionItem | 入力 | 解決対象の補完アイテム |
| item.data | JsonValue | 入力 | メタデータ（uri, line, column, resolved, format, imports, level等） |
| item | CompletionItem | 出力 | 解決済みの補完アイテム |
| item.additionalTextEdits | TextEdit[] | 出力 | インポート文追加等の追加テキスト編集 |
| item.insertText | string | 出力 | フォーマット済みの挿入テキスト |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| insertText | テキスト | フォーマット済みの挿入テキスト |
| additionalTextEdits | テキスト編集 | 自動インポート追加のためのテキスト編集 |
| documentation | マークダウン | スニペットのドキュメント（解決後に更新される場合あり） |

## イベント仕様

### 1-スニペット解決

dataフィールドにresolved=falseが含まれる場合:

1. SnippetsComponentのresolveSnippetを呼び出し
2. スニペットの完全な情報（snippet.snippet, documentation等）を取得
3. CompletionItemに変換して返却

### 2-自動インポート追加

dataフィールドにimportsが含まれる場合:

1. ImporterComponentのadd関数を呼び出し
2. 各インポートについてCodeReplacementを取得
3. TextEditに変換してadditionalTextEditsに追加
4. additionalTextEditsをソート（末尾から先頭の順）

### 3-コードフォーマット

dataフィールドにformatが含まれる場合:

1. dfmt引数をタブ区切りで分割
2. スニペット形式（InsertTextFormat.snippet）の場合はformatSnippet関数を使用
3. それ以外の場合はformatCode関数を使用
4. SnippetLevelに応じたフォーマットを適用

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | なし | なし | データベースアクセスなし（読み取り専用操作） |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 条件 |
|-------------|------|---------------|------|
| なし | なし | なし | エラーメッセージの表示は行わない |

## 例外処理

| 例外条件 | 処理内容 |
|----------|----------|
| dataフィールドがnone | 入力をそのまま返却 |
| uri/line/columnが取得できない | 入力をそのまま返却 |
| SnippetsComponentが未初期化 | スニペット解決をスキップ |
| ImporterComponentが未初期化 | インポート追加をスキップ |

## 備考

- resolveProviderはdoCompleteSnippets設定がtrueの場合にサーバーケイパビリティで宣言される（initialize時）
- dataフィールドにはuri, line, column, resolved, format, imports, level, id, providerId等のメタデータが格納される
- additionalTextEditsはstart位置の降順でソートされる（末尾からの適用を保証）
- completionItemのlabelDetailsSupport非対応クライアントへのフォールバック処理がmigrateLabelDetailsSupport関数で行われる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | complete.d | `source/served/commands/complete.d` | snippetToCompletionItem関数（1021-1050行目）: スニペットとCompletionItemの変換 |
| 1-2 | complete.d | `source/served/commands/complete.d` | snippetFromCompletionItem関数（1052-1081行目）: CompletionItemからスニペットへの逆変換 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | complete.d | `source/served/commands/complete.d` | resolveCompletionItem関数（940-1019行目）がメインエントリーポイント |

**主要処理フロー**:
1. **943-951行目**: dataフィールドからuri, line, column, resolvedを取得
2. **963-973行目**: resolved=false時のスニペット解決
3. **975-993行目**: imports存在時の自動インポートTextEdit生成
4. **997-1011行目**: format存在時のdfmtフォーマット適用

#### Step 3: フォーマット処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | format.d | `source/served/commands/format.d` | formatCode関数とformatSnippet関数（dfmtによるフォーマット） |

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

```
completionItem/resolve
    |
    +-- resolveCompletionItem() [complete.d:940]
            |
            +-- [resolved=false] SnippetsComponent.resolveSnippet() [complete.d:969]
            |       +-- snippetToCompletionItem() [complete.d:1021]
            |
            +-- [imports存在] ImporterComponent.add() [complete.d:985]
            |       +-- TextEdit変換 [complete.d:989]
            |       +-- sort("a.range.start>b.range.start") [complete.d:991]
            |
            +-- [format存在] formatSnippet() / formatCode() [complete.d:1005/1009]
```

### データフロー図

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

CompletionItem         +-- resolveCompletionItem()      +-- CompletionItem (解決済み)
(data含む)                  |                                  |
                             +-- スニペット解決                  +-- insertText (フォーマット済)
                             +-- インポート追加TextEdit生成      +-- additionalTextEdits
                             +-- dfmtフォーマット適用            +-- documentation
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| complete.d | `source/served/commands/complete.d` | ソース | resolveCompletionItem関数（940-1019行目）メイン実装 |
| format.d | `source/served/commands/format.d` | ソース | formatCode / formatSnippet関数 |
| extension.d | `source/served/extension.d` | ソース | resolveProvider設定（274行目） |
