# 機能設計書 17-シグネチャヘルプ (textDocument/signatureHelp)

## 概要

本ドキュメントは、serve-d LSPサーバーにおける「シグネチャヘルプ」機能の設計を記述する。LSPの `textDocument/signatureHelp` リクエストを処理し、関数呼び出し時にパラメータ情報を含むシグネチャヘルプを提供する機能である。

### 本機能の処理概要

関数呼び出しの括弧内にカーソルがある場合に、呼び出し対象の関数シグネチャ（パラメータ名・型・DDocドキュメント）を表示用に整形して返却する。D言語ソースコードとdietテンプレートの両方に対応する。DCDExtComponentで括弧位置のパラメータ解析を行い、DCDComponent で関数候補のシグネチャを取得する。

**業務上の目的・背景**：関数呼び出し時に引数の型・名前・説明を表示することは、コーディング中に最も頻繁に参照される補助情報の一つである。特にオーバーロードされた関数や多数のパラメータを持つ関数では、シグネチャヘルプなしでは開発効率が大きく低下する。

**機能の利用シーン**：開発者が関数名の後に '(' を入力した際、または関数引数内でカーソルを移動した際に自動的にトリガーされる。テンプレート引数('!' の後)とテンプレートパラメータの表示にも対応する。

**主要な処理内容**：
1. 言語ID判定（D / diet）
2. DCDExtComponentによるカーソル位置の関数呼び出しパラメータ解析
3. DCDComponentによる関数シグネチャ(calltips)の取得
4. DDocドキュメントのパース・パラメータドキュメント抽出
5. アクティブパラメータ・アクティブシグネチャの判定

**関連システム・外部連携**：DCDComponent、DCDExtComponent、DDoc処理ユーティリティ

**権限による制御**：DCDComponent・DCDExtComponentの両方が利用可能である必要がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | シグネチャヘルプ（textDocument/signatureHelp） | 主機能 | 関数呼び出し時にパラメータ情報を含むシグネチャヘルプを提供する |

## 機能種別

データ取得・変換処理 / コード解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| params | TextDocumentPositionParams | Yes | シグネチャヘルプ要求の位置情報 | - |
| params.textDocument.uri | DocumentUri | Yes | 対象ドキュメントのURI | 有効なURI文字列 |
| params.position | Position | Yes | カーソル位置（行・列） | 0ベースの行・列番号 |

### 入力データソース

- LSPクライアントからの `textDocument/signatureHelp` リクエスト
- DCDExtComponentからのパラメータ解析結果
- DCDComponentからの関数シグネチャ（calltips）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| signatures | SignatureInformation[] | 関数シグネチャ情報の配列 |
| signatures[].label | string | シグネチャの表示文字列（calltip文字列） |
| signatures[].documentation | MarkupContent | DDocドキュメント（Markdown変換済み） |
| signatures[].parameters | ParameterInformation[] | パラメータ情報配列 |
| signatures[].parameters[].label | string/uint[2] | パラメータラベルまたはオフセット範囲 |
| signatures[].parameters[].documentation | MarkupContent | パラメータのDDocドキュメント |
| activeSignature | int | 現在のアクティブシグネチャインデックス |
| activeParameter | int | 現在のアクティブパラメータインデックス |

### 出力先

LSPクライアントへのレスポンスメッセージ

## 処理フロー

### 処理シーケンス

```
1. ドキュメント取得と言語ID判定
   ├─ D言語: provideDSignatureHelp
   ├─ diet: provideDietSignatureHelp
   └─ その他: SignatureHelp.init 返却
2. D言語シグネチャヘルプ (provideDSignatureHelp):
   2-1. DCDComponent/DCDExtComponent の存在確認
   2-2. DCDExtComponent.extractCallParameters でカーソル位置の関数呼び出しパラメータ解析
   2-3. DCDComponent.listCompletion で関数括弧開始位置+1のcalltipsを取得
   2-4. convertDCDCalltips でLSP形式に変換
3. calltips変換 (convertDCDCalltips):
   3-1. 各calltip文字列に対してSignatureInformation生成
   3-2. DDocドキュメントのパース・Markdown変換
   3-3. DCDExtComponent.extractCallParameters でパラメータ範囲抽出
   3-4. テンプレート/関数パラメータに基づく切り替え
   3-5. 各パラメータのラベル(名前orオフセット)・ドキュメント設定
   3-6. アクティブパラメータ・アクティブシグネチャの決定
```

### フローチャート

```mermaid
flowchart TD
    A[textDocument/signatureHelp 受信] --> B{言語ID判定}
    B -->|D言語| C[provideDSignatureHelp]
    B -->|diet| D[provideDietSignatureHelp]
    B -->|その他| E[空のSignatureHelp返却]
    C --> F{DCDComponent/DCDExtComponent利用可?}
    F -->|No| E
    F -->|Yes| G[extractCallParameters でパラメータ解析]
    G --> H{解析結果あり?}
    H -->|No| E
    H -->|Yes| I[DCDComponent.listCompletion でcalltips取得]
    I --> J{calltips結果?}
    J -->|calltips| K[convertDCDCalltips]
    J -->|その他| E
    K --> L[SignatureHelp 返却]
    D --> M[dietファイルからDコード抽出]
    M --> N[DCDで補完・変換]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-17-01 | テンプレート引数判定 | inTemplateParametersフラグに基づきテンプレート引数と関数引数を切り替え | calltips変換時 |
| BR-17-02 | 可変長引数対応 | 最後のパラメータがvariadicの場合、パラメータ数をint.maxとして扱う | アクティブシグネチャ判定時 |
| BR-17-03 | パラメータラベル形式 | クライアントのlabelOffsetSupport能力に応じてUTF-16オフセットまたは文字列を使用 | パラメータラベル設定時 |
| BR-17-04 | テンプレートのみシグネチャ除外 | テンプレート引数内でテンプレートを持たないシグネチャはスキップ | convertDCDCalltips |
| BR-17-05 | DDocパラメータドキュメント | DDocのParamsセクションから各パラメータのドキュメントを抽出 | パラメータドキュメント設定時 |

### 計算ロジック

アクティブシグネチャの決定:
- 入力済みパラメータ数 <= シグネチャのパラメータ数 の条件を満たす最初のシグネチャをアクティブに設定

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | コンポーネント不在 | DCDComponent/DCDExtComponent未起動 | SignatureHelp.init返却 |
| - | 解析失敗 | extractCallParametersがinit返却 | SignatureHelp.init返却 |
| - | DCD結果不正 | calltips以外の結果種別 | SignatureHelp.init返却 |

### リトライ仕様

リトライなし。

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

トランザクション管理なし。読み取り専用操作。

## パフォーマンス要件

リアルタイムのキー入力に伴うシグネチャ表示のため、低遅延が必要。DCDのcalltips取得はgetYieldで非同期結果を取得。

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

特になし。

## 備考

- パラメータのラベルオフセットはUTF-16カウントで計算される（LSPプロトコル仕様に準拠）
- dietテンプレートの場合は、テンプレートからDコードを抽出した上でDCD処理を実行する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | calltips.d | `source/served/commands/calltips.d` | SignatureHelp、SignatureInformation、ParameterInformation の型構造を理解する |

**読解のコツ**: `CalltipsSupport` はDCDExtComponentが返却するパラメータ解析結果。`templateArgs` と `functionArgs` の2つのパラメータ配列を持ち、`inTemplateParameters` でどちらを使用するかが決まる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | calltips.d | `source/served/commands/calltips.d` | `provideSignatureHelp` 関数（121-132行目）がLSPメソッドのエントリーポイント |

**主要処理フロー**:
1. **121行目**: `@protocolMethod("textDocument/signatureHelp")` でLSPメソッド登録
2. **124行目**: ドキュメント取得
3. **126行目**: D言語の場合 `provideDSignatureHelp` を呼び出し
4. **128行目**: dietの場合 `provideDietSignatureHelp` を呼び出し

#### Step 3: D言語シグネチャヘルプ処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | calltips.d | `source/served/commands/calltips.d` | `provideDSignatureHelp` 関数（134-166行目）のDCD呼び出しフロー |

**主要処理フロー**:
- **137-138行目**: DCDComponent/DCDExtComponentの存在確認
- **145行目**: `extractCallParameters` でカーソル位置のパラメータ解析
- **149-150行目**: `listCompletion` でcalltips取得（括弧開始位置+1をオフセットとして使用）
- **157-159行目**: calltips結果の場合 `convertDCDCalltips` で変換

#### Step 4: calltips変換処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | calltips.d | `source/served/commands/calltips.d` | `convertDCDCalltips` 関数（25-119行目）のシグネチャ変換・パラメータ抽出ロジック |

**主要処理フロー**:
- **32-103行目**: 各calltip文字列に対するSignatureInformation生成ループ
- **39-43行目**: DDocドキュメントのパース・Markdown変換
- **45-46行目**: calltip文字列のパラメータ範囲抽出
- **60-96行目**: 各パラメータのラベル・ドキュメント設定
- **105-116行目**: アクティブパラメータ・アクティブシグネチャの決定

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

```
provideSignatureHelp (calltips.d:122)
    │
    ├─ [D言語] provideDSignatureHelp (calltips.d:134)
    │      ├─ DCDExtComponent.extractCallParameters
    │      ├─ DCDComponent.listCompletion
    │      └─ convertDCDCalltips (calltips.d:25)
    │             ├─ parseDdoc (ddoc.d)
    │             ├─ DCDExtComponent.extractCallParameters
    │             └─ getParamDocumentation (ddoc.d)
    │
    └─ [diet] provideDietSignatureHelp (calltips.d:168)
           ├─ updateDietFile (diet.d)
           └─ DCDComponent.listCompletion → convertDCDCalltips
```

### データフロー図

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

TextDocumentPosition ──▶ provideSignatureHelp ──────▶ SignatureHelp
                              │                          ├─ signatures[]
                              ├─ DCDExtComponent         │    ├─ label
                              │    └─ CallParams解析     │    ├─ documentation
                              ├─ DCDComponent            │    └─ parameters[]
                              │    └─ calltips取得       ├─ activeSignature
                              └─ DDoc                    └─ activeParameter
                                   └─ パラメータドキュメント
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| calltips.d | `source/served/commands/calltips.d` | ソース | provideSignatureHelp, convertDCDCalltips |
| ddoc.d | `source/served/utils/ddoc.d` | ソース | DDocパース・Markdown変換・パラメータドキュメント抽出 |
| diet.d | `source/served/utils/diet.d` | ソース | dietテンプレートからのDコード抽出 |
| extension.d | `source/served/extension.d` | ソース | コマンド登録 |
