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

## 概要

本ドキュメントは、Lua Language Serverにおける「シグネチャヘルプ」機能の設計を記述する。この機能は、LSPの`textDocument/signatureHelp`リクエストに対応し、関数呼び出し時の引数情報を表示する機能を提供する。

### 本機能の処理概要

シグネチャヘルプ機能は、関数呼び出しの括弧内でカーソルが位置している時に、関数のシグネチャ（パラメータ名、型、説明）を表示する機能である。現在入力中のパラメータ位置をハイライト表示する。

**業務上の目的・背景**：関数を呼び出す際に、どのようなパラメータを渡す必要があるかを確認したいというニーズは非常に高い。この機能により、開発者は関数定義を参照することなく、呼び出し位置でパラメータ情報を確認でき、正確なコーディングが可能になる。

**機能の利用シーン**：
- 関数呼び出し時にパラメータの順序を確認したい場合
- パラメータの型を確認したい場合
- オプショナルパラメータかどうかを確認したい場合
- 可変長引数（...）の使い方を確認したい場合

**主要な処理内容**：
1. カーソル位置から最も近い関数呼び出しを検索
2. 現在のカーソル位置から引数インデックスを計算
3. 呼び出し対象の関数定義を取得
4. オーバーロードを含む全シグネチャを収集
5. 各シグネチャに対してラベルとパラメータ情報を生成
6. 戻り値部分を除去してパラメータ部分のみ表示

**関連システム・外部連携**：
- LSPプロトコルの`textDocument/signatureHelp`リクエストハンドラ
- ホバー情報のラベル生成機能（hoverLabel）

**権限による制御**：`Lua.signatureHelp.enable`設定で有効/無効を切り替え可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | シグネチャヘルプ | 主機能 | 関数呼び出し時の引数情報を表示する主処理 |

## 機能種別

情報表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | uri | Yes | 対象ファイルのURI | 有効なファイルURI |
| pos | integer | Yes | カーソル位置 | 正の整数 |

### トリガー条件

| トリガー文字 | 説明 |
|-------------|------|
| `(` | 関数呼び出しの開始 |
| `,` | 次の引数への移動 |

### 入力データソース

- 対象ファイルのAST状態（files.getState）
- 関数定義情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| signatures | SignatureInformation[] | シグネチャ情報の配列 |
| signatures[].label | string | 関数シグネチャの文字列表現 |
| signatures[].parameters | ParameterInformation[] | パラメータ情報の配列 |
| signatures[].parameters[].label | [number, number] | パラメータのラベル範囲 |
| signatures[].activeParameter | integer | 現在アクティブなパラメータのインデックス |
| signatures[].documentation | MarkupContent? | 関数の説明 |

### 出力先

LSPレスポンスとしてクライアントに返される

## 処理フロー

### 処理シーケンス

```
1. シグネチャヘルプが有効か確認
   └─ Lua.signatureHelp.enable設定をチェック
2. ワークスペースの準備を待機
   └─ workspace.awaitReady(uri)
3. ASTとテキストを取得
   └─ files.getState(uri)、files.getText(uri)
4. カーソル位置の空白をスキップ
   └─ lookback.skipSpaceで調整
5. 最も近い関数呼び出しを検索
   └─ findNearCall()で検索
6. 引数インデックスを計算
   └─ カーソル位置と各引数の位置を比較
7. 関数ノードを取得
   └─ vm.compileNode(func)
8. 各関数/オーバーロードに対してシグネチャを生成
   └─ makeOneSignature()
9. イベント型のマッチングを確認
   └─ isEventNotMatch()でフィルタリング
10. 結果をパラメータ数でソート
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{シグネチャヘルプ有効?}
    B -->|No| C[nil を返す]
    B -->|Yes| D[ワークスペース準備待機]
    D --> E[AST/テキスト取得]
    E --> F{取得成功?}
    F -->|No| C
    F -->|Yes| G[空白スキップ]
    G --> H[最も近いcall検索]
    H --> I{call存在?}
    I -->|No| C
    I -->|Yes| J[引数インデックス計算]
    J --> K[関数ノード取得]
    K --> L[各関数をループ]
    L --> M{function/doc.type.function?}
    M -->|No| L
    M -->|Yes| N{イベント型マッチ?}
    N -->|No| L
    N -->|Yes| O[シグネチャ生成]
    O --> P{全関数処理完了?}
    P -->|No| L
    P -->|Yes| Q{結果あり?}
    Q -->|No| C
    Q -->|Yes| R[パラメータ数でソート]
    R --> S[結果を返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 閉じ括弧除外 | カーソルがcall終了後（閉じ括弧の後）にある場合は表示しない | findNearCall時 |
| BR-02 | 戻り値除去 | シグネチャラベルから戻り値部分（-> ...）を除去 | ラベル生成時 |
| BR-03 | 可変長引数 | ...で終わるパラメータはインデックスをその位置に固定 | インデックス計算時 |
| BR-04 | イベント型フィルタ | イベント型引数が指定されている場合、マッチしないオーバーロードを除外 | シグネチャ収集時 |
| BR-05 | パラメータ数ソート | シグネチャはパラメータ数の少ない順にソート | 結果返却前 |
| BR-06 | オーバーロード除外 | vm.isVarargFunctionWithOverloadsがtrueの関数は直接処理しない | シグネチャ収集時 |

### 計算ロジック

引数インデックス計算:
```lua
-- カーソル位置から引数インデックスを計算
for i, arg in ipairs(args) do
    local startOffset = guide.positionToOffset(state, arg.start)
    startOffset = lookback.findTargetSymbol(text, startOffset, '(')
               or lookback.findTargetSymbol(text, startOffset, ',')
               or startOffset
    local startPos = guide.offsetToPosition(state, startOffset)
    if startPos > pos then
        index = i - 1
        break
    end
    if pos <= arg.finish then
        index = i
        break
    end
end
```

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

この機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無視 | AST/テキストが取得できない | nilを返す |
| - | 無視 | 関数呼び出しが見つからない | nilを返す |
| - | 無視 | シグネチャが生成できない | nilを返す |

### リトライ仕様

リトライは行わない。

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

該当なし

## パフォーマンス要件

- シグネチャ生成は非同期処理（@async）で実行
- LSPの応答性を維持するためprogress表示（0.5秒以上の処理時）

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

特になし

## 備考

- テーブルコンストラクタ`{}`内でもシグネチャヘルプが動作（テーブルを引数として渡す場合）
- ネストした関数呼び出しでは最も近い呼び出しが優先される
- doc.type.functionもオーバーロードとして表示される

---

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

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

### 推奨読解順序

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

シグネチャ情報の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | signature.lua | `script/core/signature.lua` | makeOneSignature戻り値構造（88-93行目） |

**読解のコツ**: `params`配列には各パラメータの`label`（範囲）が含まれ、LSPクライアントがハイライト表示に使用する。

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

メイン関数の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | signature.lua | `script/core/signature.lua` | メイン関数（206-227行目）がモジュールの戻り値 |
| 2-2 | provider.lua | `script/provider/provider.lua` | textDocument/signatureHelp ハンドラ（773-823行目） |

**主要処理フロー**:
1. **208-212行目**: AST/テキスト取得
2. **213-214行目**: 空白スキップ
3. **215-218行目**: findNearCall実行
4. **219-225行目**: makeSignatures実行とソート

#### Step 3: 関数呼び出し検索を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | signature.lua | `script/core/signature.lua` | findNearCall関数（8-42行目） |

**主要処理フロー**:
- **15-33行目**: guide.eachSourceContainでcall/table/functionを検索
- **38-41行目**: callノードのみを返す

#### Step 4: シグネチャ生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | signature.lua | `script/core/signature.lua` | makeOneSignature関数（45-94行目） |
| 4-2 | signature.lua | `script/core/signature.lua` | makeSignatures関数（133-204行目） |

**主要処理フロー**:
- **46-48行目**: hoverLabelでラベル生成
- **51行目**: 戻り値部分を除去
- **54-68行目**: パラメータ範囲を計算（ネスト構造を考慮）

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

```
provider.lua ('textDocument/signatureHelp' ハンドラ)
    │
    └─ signature.lua (メイン関数)
           │
           ├─ files.getState() [AST取得]
           ├─ files.getText() [テキスト取得]
           ├─ lookback.skipSpace() [空白スキップ]
           │
           ├─ findNearCall()
           │      └─ guide.eachSourceContain() [ノード検索]
           │
           └─ makeSignatures()
                  │
                  ├─ vm.compileNode() [関数ノード取得]
                  ├─ isEventNotMatch() [イベント型チェック]
                  │
                  └─ makeOneSignature()
                         ├─ hoverLabel() [ラベル生成]
                         └─ hoverDesc() [説明生成]
```

### データフロー図

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

URI ─────────────────────┐
                         │
カーソル位置 ─────────────┼──▶ signature() ──▶ SignatureHelp
                         │         │
                         │         ▼
                         │   ┌────────────────┐
                         │   │ findNearCall   │
                         │   └────────────────┘
                         │         │
                         │         ▼
                         │   ┌────────────────┐
                         │   │ 引数インデックス │
                         │   │   計算          │
                         │   └────────────────┘
                         │         │
                         │         ▼
                         │   ┌────────────────┐
                         │   │ vm.compileNode │
                         │   └────────────────┘
                         │         │
                         │         ▼
                         │   ┌────────────────┐
                         │   │ makeSignatures │
                         │   └────────────────┘
                         │         │
                         │         ▼
                         └─ [signatures[], activeParameter]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| signature.lua | `script/core/signature.lua` | ソース | シグネチャヘルプのメイン実装 |
| provider.lua | `script/provider/provider.lua` | ソース | LSPハンドラ、シグネチャヘルプリクエストを処理 |
| label.lua | `script/core/hover/label.lua` | ソース | ラベル生成（hoverLabel） |
| description.lua | `script/core/hover/description.lua` | ソース | 説明生成（hoverDesc） |
| look-backward.lua | `script/core/look-backward.lua` | ソース | 後方検索ユーティリティ |
| guide.lua | `script/parser/guide.lua` | ソース | AST操作ユーティリティ |
| vm/init.lua | `script/vm/init.lua` | ソース | compileNode関数を提供 |
