# 機能設計書 14-スニペット補完

## 概要

本ドキュメントは、serve-d LSPサーバーにおける「スニペット補完」機能の設計を記述する。コンテキストに応じたDCD補完・組み込みスニペット・カスタムスニペット・自動インポート補完を統合的に提供する内部機能である。

### 本機能の処理概要

テキスト補完（textDocument/completion）のサブ機能として、カーソル位置のコンテキスト（グローバルスコープ、メソッド内、値式内など）に応じたスニペットテンプレートを補完候補として提供する。SnippetsComponentからスニペット候補を取得し、CompletionItem形式に変換して補完リストに追加する。

**業務上の目的・背景**：スニペット補完は、定型的なコードパターン（if文、for文、unittest、try-catch等）の素早い入力を支援する。D言語特有のコード構造に対応したスニペットを提供することで、D言語開発の生産性を向上させる。また、依存パッケージ固有のスニペットも登録可能にすることで、ライブラリ利用時の補完体験を拡張している。

**機能の利用シーン**：開発者がD言語のソースコードを編集中に、コード補完がトリガーされた際、コンテキストに適したスニペットが候補リストに表示される。例えばメソッド内で "for" と入力すると、forループのスニペットが提示される。

**主要な処理内容**：
1. カーソル位置のコンテキスト判定（SnippetLevel: global/method/value等）
2. SnippetsComponentからコンテキスト適合スニペットを取得
3. スニペットをCompletionItem形式に変換（ラベル、ドキュメント、挿入テキスト設定）
4. dfmtフォーマット引数・インポート情報をdata属性に格納（遅延解決用）
5. '.'文字の直後ではスニペット補完を抑制

**関連システム・外部連携**：SnippetsComponent（workspace-d）、dfmt、`--provide context-snippets` オプション

**権限による制御**：`doCompleteSnippets` グローバル変数（`--provide context-snippets` コマンドライン引数で有効化）、SnippetsComponentのロード状態

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | コード補完（textDocument/completion） | 補助機能 | コード補完の一部としてコンテキストに応じたスニペット候補を提供する |

## 機能種別

データ取得・変換処理 / コードテンプレート管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| params | TextDocumentPositionParams | Yes | 補完要求の位置情報 | - |
| instance | WorkspaceD.Instance | Yes | ワークスペースインスタンス | SnippetsComponentが必要 |
| document | Document | Yes | 対象ドキュメント | - |
| config | UserConfiguration | Yes | ユーザー設定 | - |
| completion | CompletionItem[] | Yes | 追加先の補完リスト（参照） | - |
| byteOff | int | Yes | カーソルのバイトオフセット | 0以上 |

### 入力データソース

- provideDSourceCompleteからの内部呼び出し
- SnippetsComponentからのスニペット候補リスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (戻り値) | SnippetInfo | スニペットコンテキスト情報（level等） |
| completion (参照) | CompletionItem[] | スニペット補完アイテムが追加される |

### 出力先

呼び出し元（provideDSourceComplete）へのSnippetInfo返却、およびcompletion配列への参照追加

## 処理フロー

### 処理シーケンス

```
1. '.' 文字の直後判定
   └─ byteOff > 0 && document.rawText[byteOff-1] == '.' の場合、SnippetInfo.init を返却
2. SnippetsComponent からスニペット候補を取得
   └─ getSnippetsYield(file, rawText, byteOff) でコンテキスト適合スニペットを取得
3. 各スニペットの CompletionItem 変換
   3-1. snippetToCompletionItem でラベル・ドキュメント・挿入テキスト設定
   3-2. data に level, format(dfmt引数), uri, line, column, imports を格納
4. completion 配列に追加
5. SnippetInfo（コンテキスト情報）を返却
```

### フローチャート

```mermaid
flowchart TD
    A[provideSnippetComplete 呼び出し] --> B{前文字が '.' ?}
    B -->|Yes| C[SnippetInfo.init 返却]
    B -->|No| D[SnippetsComponent.getSnippetsYield]
    D --> E[各スニペットをCompletionItemに変換]
    E --> F[data属性にメタデータ格納]
    F --> G[completion配列に追加]
    G --> H[SnippetInfo 返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-14-01 | ドット後抑制 | '.'文字の直後ではスニペット補完を提供しない | byteOff > 0 かつ前文字が '.' |
| BR-14-02 | コンテキスト判定 | SnippetLevel（global/method/value等）に基づきスニペットをフィルタ | 全スニペット取得時 |
| BR-14-03 | ソートプレフィックス | スニペットには sortPrefixSnippets("2_5_") を付与 | スニペット変換時 |
| BR-14-04 | スニペットサポート判定 | クライアントのsnippetSupport能力に応じてsnippet/plainTextを切り替え | CompletionItem変換時 |
| BR-14-05 | フォーマット情報 | unformatted==falseのスニペットにはdfmt引数をdata.formatに格納 | スニペット変換時 |

### 計算ロジック

特になし

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | コンポーネント不在 | SnippetsComponentが未ロード | スニペット補完をスキップ（getSnippetInfoのみ実行） |

### リトライ仕様

リトライなし。

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

トランザクション管理なし。

## パフォーマンス要件

コード補完のサブ処理として並列実行されるため、低遅延が求められる。

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

特になし。

## 備考

- `doCompleteSnippets` が false の場合は `getSnippetInfo` のみ実行される（スニペット候補は生成しないがコンテキスト情報は取得する）
- スニペットのドキュメントにはMarkdownフォーマットでDコードブロック付きのプレビューが含まれる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | complete.d | `source/served/commands/complete.d` | `doCompleteSnippets` グローバル変数（300行目）、`sortPrefixSnippets` 定数（35行目）を確認 |

**読解のコツ**: SnippetInfo、Snippet、PlainSnippet 等の型は workspace-d サブパッケージで定義されている。`SnippetLevel` はスコープレベル（global/method/value等）を表す列挙型。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | complete.d | `source/served/commands/complete.d` | `provideSnippetComplete` 関数（841-870行目）がスニペット補完のエントリーポイント |

**主要処理フロー**:
1. **845-846行目**: '.' 文字直後のスニペット抑制判定
2. **848行目**: SnippetsComponent取得
3. **849行目**: `getSnippetsYield` でコンテキスト適合スニペット取得
4. **853-867行目**: 各スニペットのCompletionItem変換とdata属性設定
5. **869行目**: SnippetInfo返却

#### Step 3: スニペット→CompletionItem変換

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | complete.d | `source/served/commands/complete.d` | `snippetToCompletionItem` 関数（1021-1050行目）のスニペットからCompletionItemへの変換ロジック |

**主要処理フロー**:
- **1024行目**: label にショートカット名を設定
- **1025行目**: sortText にソートプレフィックス付きショートカット名
- **1027行目**: kind を CompletionItemKind.snippet に設定
- **1028-1029行目**: ドキュメントをMarkdownフォーマット（コードブロック付き）で設定
- **1031-1039行目**: クライアントのsnippetSupportに応じたinsertText設定
- **1043-1048行目**: data属性にresolved, id, providerId, dataを格納

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

```
provideDSourceComplete (complete.d:550)
    │
    └─ provideSnippetComplete (complete.d:841)
           │
           ├─ SnippetsComponent.getSnippetsYield
           │
           ├─ snippetToCompletionItem (complete.d:1021)
           │
           └─ generateDfmtArgs (format.d)
```

### データフロー図

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

Document + Position ────▶ provideSnippetComplete ──▶ completion[] (参照追加)
                              │                         + SnippetInfo
                              └── SnippetsComponent
                                    └── Snippet[] ──▶ CompletionItem[]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| complete.d | `source/served/commands/complete.d` | ソース | provideSnippetComplete, snippetToCompletionItem |
| format.d | `source/served/commands/format.d` | ソース | generateDfmtArgs関数 |
| extension.d | `source/served/extension.d` | ソース | コマンド登録 |
