# 機能設計書 55-シグネチャ表示

## 概要

本ドキュメントは、clojure-lspにおけるシグネチャ表示（Signature Help）機能の設計を記述する。この機能はLSPプロトコルの`textDocument/signatureHelp`リクエストを実装し、関数呼び出し時にパラメータ情報を表示する。

### 本機能の処理概要

**業務上の目的・背景**：
Clojureの関数は複数のアリティ（引数パターン）を持つことがあり、どのような引数を渡せばよいか把握が難しい場合がある。Signature Help機能は、関数呼び出しの入力中にパラメータ情報をリアルタイムで表示し、現在カーソルがあるパラメータをハイライトすることで、開発者の生産性を向上させる。

**機能の利用シーン**：
1. 関数の引数を入力している際にパラメータ情報を確認する場面
2. 複数アリティを持つ関数でどのアリティを使用するか判断する場面
3. ドキュメントを参照せずに関数の使用方法を確認する場面

**主要な処理内容**：
1. カーソル位置から関数呼び出しを検出
2. 関数の定義情報を取得
3. アリティ（引数リスト）情報をシグネチャとして生成
4. 現在の引数位置とアクティブなシグネチャを計算
5. 結果をLSPレスポンスとして返却

**関連システム・外部連携**：
- clj-kondo：関数定義の解析データ（arglist-strs, fixed-arities）
- rewrite-clj：構文解析とカーソル位置からの関数検出
- LSPクライアント（エディタ）：シグネチャのUI表示

**権限による制御**：
特に権限による制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | エディタ | 主画面 | パラメータ情報のポップアップ表示 |

## 機能種別

情報表示処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| textDocument.uri | string | Yes | 対象ドキュメントのURI | 有効なファイルURI形式 |
| position.line | integer | Yes | カーソル行（0始まり） | 0以上の整数 |
| position.character | integer | Yes | カーソル列（0始まり） | 0以上の整数 |

### 入力データソース

- LSPクライアントからの`textDocument/signatureHelp`リクエスト
- 解析データ（db.analysis）
- ドキュメントテキスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| signatures | array | シグネチャ情報の配列 |
| signatures[].label | string | シグネチャ全体のラベル（例: "(my-fn arg1 arg2)"） |
| signatures[].parameters | array | パラメータ情報の配列 |
| signatures[].parameters[].label | string | パラメータのラベル |
| signatures[].documentation | string | 関数のドキュメント（あれば） |
| activeSignature | integer | アクティブなシグネチャのインデックス |
| activeParameter | integer | 現在のパラメータのインデックス |

### 出力先

LSPクライアントへのレスポンス

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ textDocument/signatureHelpを受信
2. 関数位置検出
   └─ カーソル位置から関数使用位置を逆探索
3. 引数ノード取得
   └─ 関数呼び出しの引数ノードを収集
4. 定義検索
   └─ 関数の定義情報を取得
5. シグネチャ生成
   └─ arglist-strsからシグネチャ配列を生成
6. アクティブシグネチャ計算
   └─ 引数数に基づいてマッチするアリティを特定
7. アクティブパラメータ計算
   └─ カーソル位置に基づいて現在のパラメータを特定
8. レスポンス生成
   └─ SignatureHelp形式で返却
```

### フローチャート

```mermaid
flowchart TD
    A[signatureHelp受信] --> B[ZLoc取得]
    B --> C[関数使用位置検出]
    C --> D{関数検出成功?}
    D -->|No| E[nilを返却]
    D -->|Yes| F[引数ノード取得]
    F --> G[関数定義取得]
    G --> H{定義取得成功?}
    H -->|No| E
    H -->|Yes| I[シグネチャ生成]
    I --> J[アクティブシグネチャ計算]
    J --> K[アクティブパラメータ計算]
    K --> L{シグネチャあり?}
    L -->|No| E
    L -->|Yes| M[SignatureHelp返却]
    E --> N[終了]
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-55-01 | 関数検出 | カーソル位置から上位を探索して関数呼び出しを検出 | 常時 |
| BR-55-02 | 複数アリティ対応 | fixed-aritiesからマッチするアリティを選択 | 関数が複数アリティを持つ場合 |
| BR-55-03 | 可変長引数 | & で始まる引数は可変長として"& args"形式で表示 | 常時 |
| BR-55-04 | パラメータ上限 | activeParameterはシグネチャのパラメータ数-1を上限とする | 常時 |
| BR-55-05 | ドキュメント付与 | :docメタデータがあればシグネチャに付与 | :docが存在する場合 |

### 計算ロジック

**アクティブシグネチャの計算**:
```clojure
;; fixed-aritiesからマッチするアリティを検索
;; 引数数と完全一致するものを優先、なければ最も近いものを選択
(let [arities (sort fixed-arities)
      args-count (count arglist-nodes)]
  (or (first (filter #(= % args-count) arities))
      (if (>= args-count (count arities))
        (apply max arities)
        (apply min arities))))
```

**アクティブパラメータの計算**:
```clojure
;; カーソル位置以前で最後の引数ノードを特定
(->> arglist-nodes
     reverse
     (filter #(or (< (:row %) cursor-row)
                  (and (= (:row %) cursor-row)
                       (<= (:col %) cursor-col))))
     first
     (.indexOf arglist-nodes))
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 定義検索 | db.analysis | SELECT | 関数定義の取得 |

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

#### db.analysis

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | var-definitions | 関数のFQN | arglist-strs, fixed-arities, docを取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 関数未検出 | カーソルが関数呼び出し内にない | nilを返却 |
| - | 定義未検出 | 関数の定義情報がない | nilを返却 |
| - | パース失敗 | 構文エラー | nilを返却 |

### リトライ仕様

リトライは行わない。

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

読み取り専用のため、トランザクション管理は不要。

## パフォーマンス要件

- タイピング中にリアルタイムで呼び出されるため、高速な応答が必要
- 通常数十ミリ秒以内

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

- 特になし

## 備考

- edamameライブラリを使用して引数リスト文字列をパース
- `signature-help-provider`は空配列で初期化（トリガー文字なし）

---

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

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

### 推奨読解順序

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

SignatureHelp応答のデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | signature_help.clj | `lib/src/clojure_lsp/feature/signature_help.clj` | SignatureHelpレスポンス構造（signatures, activeParameter, activeSignature） |

**読解のコツ**: Clojureの関数は複数のアリティ（引数パターン）を持てる。各アリティがsignatures配列の要素になる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | **313-318行目**: signatureHelpハンドラ |
| 2-2 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | **395-399行目**: signature-help関数 |

**主要処理フロー**:
1. **313-318行目**: `textDocument/signatureHelp`リクエストを受信
2. **395-399行目**: `f.signature-help/signature-help`を呼び出し

#### Step 3: シグネチャヘルプ本体を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | signature_help.clj | `lib/src/clojure_lsp/feature/signature_help.clj` | **77-91行目**: `signature-help`関数 |

**主要処理フロー**:
- **78-81行目**: ドキュメントテキストからZLocを取得し、カーソル位置から関数使用位置を検出
- **83行目**: 関数呼び出しの引数ノードを取得
- **84行目**: 関数位置のメタデータを取得
- **85行目**: 関数の定義情報を検索
- **86行目**: シグネチャ情報を生成
- **87行目**: アクティブなシグネチャを計算
- **88-91行目**: シグネチャがあればレスポンスを構築

#### Step 4: 各ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | signature_help.clj | `lib/src/clojure_lsp/feature/signature_help.clj` | **16-22行目**: `function-loc->arglist-nodes` |
| 4-2 | signature_help.clj | `lib/src/clojure_lsp/feature/signature_help.clj` | **44-56行目**: `get-active-signature-index` |
| 4-3 | signature_help.clj | `lib/src/clojure_lsp/feature/signature_help.clj` | **24-42行目**: `get-active-parameter-index` |
| 4-4 | signature_help.clj | `lib/src/clojure_lsp/feature/signature_help.clj` | **58-68行目**: `arglist-str->parameters` |
| 4-5 | signature_help.clj | `lib/src/clojure_lsp/feature/signature_help.clj` | **70-75行目**: `definition->signature-informations` |

**主要処理フロー**:
- **16-22行目**: 関数呼び出しの引数ノードリストを取得
- **44-56行目**: 引数数に基づいてマッチするシグネチャを特定
- **24-42行目**: カーソル位置に基づいて現在のパラメータを特定
- **58-68行目**: 引数リスト文字列をパラメータ配列に変換
- **70-75行目**: 定義情報からシグネチャ配列を生成

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

```
textDocument/signatureHelp (server.clj:313-318)
    │
    ├─ handler/signature-help (handlers.clj:395-399)
    │      │
    │      └─ f.signature-help/signature-help (signature_help.clj:77-91)
    │             │
    │             ├─ f.file-management/force-get-document-text
    │             │
    │             ├─ parser/safe-zloc-of-string
    │             │
    │             ├─ parser/to-pos
    │             │
    │             ├─ edit/find-function-usage-name-loc
    │             │
    │             ├─ function-loc->arglist-nodes (signature_help.clj:16-22)
    │             │
    │             ├─ q/find-definition-from-cursor
    │             │
    │             ├─ definition->signature-informations (signature_help.clj:70-75)
    │             │      │
    │             │      └─ arglist-str->parameters (signature_help.clj:58-68)
    │             │
    │             ├─ get-active-signature-index (signature_help.clj:44-56)
    │             │
    │             └─ get-active-parameter-index (signature_help.clj:24-42)
    │
    └─ conform-or-log
```

### データフロー図

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

signatureHelp              ┌──────────────────────────────────┐
Request                    │                                  │
  ├─ uri ─────────────────►│  signature-help                  │
  └─ position ────────────►│                                  │
                           │    ├─ ZLoc取得                   │
db.documents               │    │                             │
  └─ text ────────────────►│    ├─ 関数位置検出               │
                           │    │                             │
db.analysis                │    ├─ 引数ノード取得             │
  └─ var-definitions      │    │                             │
       ├─ arglist-strs ───►│    ├─ シグネチャ生成            │
       ├─ fixed-arities ──►│    │                             │         SignatureHelp
       └─ doc ────────────►│    ├─ アクティブシグネチャ計算   │────────►  ├─ signatures[]
                           │    │                             │           │    ├─ label
                           │    └─ アクティブパラメータ計算   │           │    ├─ parameters[]
                           │                                  │           │    └─ documentation
                           └──────────────────────────────────┘           ├─ activeSignature
                                                                          └─ activeParameter
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSPサーバーハンドラ定義 |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | 各機能のハンドラ実装 |
| signature_help.clj | `lib/src/clojure_lsp/feature/signature_help.clj` | ソース | シグネチャヘルプの実装 |
| edit.clj | `lib/src/clojure_lsp/refactor/edit.clj` | ソース | find-function-usage-name-loc |
| signature_help_test.clj | `lib/test/clojure_lsp/feature/signature_help_test.clj` | テスト | シグネチャヘルプのテスト |
