# 機能設計書 4-宣言へジャンプ

## 概要

本ドキュメントは、Clojure LSP サーバーにおける宣言へジャンプ機能の設計仕様を記載する。この機能は LSP プロトコルの `textDocument/declaration` リクエストに対応し、シンボルの宣言位置（require/refer等の参照宣言）への移動を実現する。

### 本機能の処理概要

**業務上の目的・背景**：定義へジャンプとは異なり、宣言へジャンプはシンボルがどこで参照宣言されているか（例：require文でのエイリアス宣言、refer宣言）を特定する機能である。大規模なプロジェクトにおいて、外部ライブラリの関数がどのように require/refer されているかを素早く確認することで、依存関係の理解とコードの可読性向上を支援する。

**機能の利用シーン**：開発者がエディタ上で変数使用箇所にカーソルを置き、「宣言へジャンプ」コマンドを実行した際に本機能が呼び出される。例えば、`(str/join ...)` のような名前空間エイリアス経由の関数呼び出しから、`(:require [clojure.string :as str])` の宣言位置にジャンプできる。

**主要な処理内容**：
1. カーソル位置のシンボル要素を特定
2. 要素が var-usages の場合、対応する名前空間エイリアスまたは refer 宣言を検索
3. 宣言位置（URI、行、列）を Location オブジェクトとして返却

**関連システム・外部連携**：特になし

**権限による制御**：本機能に権限による実行制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本プロジェクトは LSP サーバー実装であり、UI 画面は存在しない。エディタの宣言ジャンプ機能から呼び出される。 |

## 機能種別

データ検索処理 / ナビゲーション処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| text-document.uri | string | Yes | 対象ドキュメントの URI | 有効な file:// URI |
| position.line | integer | Yes | カーソル行位置（0-indexed） | 0 以上 |
| position.character | integer | Yes | カーソル列位置（0-indexed） | 0 以上 |

### 入力データソース

- clj-kondo による静的解析結果（db の :analysis）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| uri | string | 宣言位置のドキュメント URI |
| range.start.line | integer | 宣言開始行（0-indexed） |
| range.start.character | integer | 宣言開始列（0-indexed） |
| range.end.line | integer | 宣言終了行（0-indexed） |
| range.end.character | integer | 宣言終了列（0-indexed） |

### 出力先

LSP プロトコルを通じてエディタクライアントへ Location オブジェクトとして返却

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ handlers/declaration が textDocument/declaration を受信

2. カーソル位置の要素特定
   └─ q/find-element-under-cursor でカーソル下の要素を取得

3. 宣言検索
   └─ q/find-declaration (multimethod) で要素種別に応じた検索

4. 位置変換
   └─ element->location で Location オブジェクトに変換

5. レスポンス返却
   └─ uri と range を含む Location を返却
```

### フローチャート

```mermaid
flowchart TD
    A[declaration リクエスト受信] --> B[find-element-under-cursor]
    B --> C{要素あり?}
    C -->|No| D[nil 返却]
    C -->|Yes| E{要素の bucket?}
    E -->|var-usages| F{alias あり?}
    E -->|その他| G[nil 返却]
    F -->|Yes| H[namespace-alias から検索]
    F -->|No| I{refer あり?}
    I -->|Yes| J[var-usages から refer を検索]
    I -->|No| K[namespace-usages から検索]
    H --> L[element->location]
    J --> L
    K --> L
    L --> M[Location 返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | var-usages のみ対応 | 現在の実装は var-usages のみ宣言検索に対応 | 要素種別判定時 |
| BR-02 | エイリアス優先 | エイリアス付きの場合は namespace-alias から検索 | alias フィールドあり |
| BR-03 | refer 検索 | refer されている場合は var-usages から refer を検索 | alias なし、refer あり |
| BR-04 | 名前空間フォールバック | エイリアスも refer もない場合は namespace-usages から検索 | alias なし、refer なし |

### 計算ロジック

- 宣言検索: find-declaration マルチメソッドにより、var-usages の場合のみ検索を実行

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 要素検索 | db :analysis | SELECT | カーソル位置の要素を検索 |
| 宣言検索 | db :analysis[uri] | SELECT | 同一ファイル内の宣言を検索 |

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

#### db :analysis[uri]

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | :namespace-alias | :to, :alias でマッチング | エイリアス宣言検索 |
| SELECT | :var-usages | :to, :name, :refer でマッチング | refer 宣言検索 |
| SELECT | :namespace-usages | :name でマッチング | 名前空間宣言検索 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | nil 返却 | カーソル位置に要素がない | nil を返却 |
| - | nil 返却 | 宣言が見つからない | nil を返却 |
| - | nil 返却 | :clj-kondo/unknown-namespace の場合 | nil を返却 |

### リトライ仕様

リトライは行わない。

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

本機能は読み取り専用であり、トランザクション管理は不要。

## パフォーマンス要件

- 応答時間: 通常 30ms 以内
- 同一ファイル内の検索のため高速

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

- 外部ネットワーク通信なし
- ファイルシステムアクセスは解析対象ファイルのみ

## 備考

- 定義へジャンプ（definition）とは異なり、宣言へジャンプは同一ファイル内の参照宣言を対象とする
- var-usages 以外の要素では nil を返却する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | queries.clj | `lib/src/clojure_lsp/queries.clj` | find-declaration defmulti（386-388行目）で宣言検索の分岐を確認 |

**読解のコツ**: find-definition と同様のマルチメソッドパターンだが、実装は var-usages と default のみ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | declaration 関数（296-302行目）が LSP リクエストのエントリーポイント |

**主要処理フロー**:
1. **298-299行目**: position を row, col に変換
2. **301行目**: q/find-declaration-from-cursor を呼び出し
3. **302行目**: element->location で Location に変換

#### Step 3: 宣言検索のマルチメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | queries.clj | `lib/src/clojure_lsp/queries.clj` | find-declaration defmulti（386-388行目）で分岐ポイントを確認 |
| 3-2 | queries.clj | `lib/src/clojure_lsp/queries.clj` | var-usages の宣言検索（390-409行目） |
| 3-3 | queries.clj | `lib/src/clojure_lsp/queries.clj` | default（411行目）で nil 返却 |

**主要処理フロー**:
- **390-392行目**: :clj-kondo/unknown-namespace の場合は nil 返却
- **393-395行目**: 同一 URI のバケットを取得
- **399-402行目**: alias がある場合は namespace-alias から検索
- **403-408行目**: alias がない場合は refer か namespace-usages から検索

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

```
handlers/declaration
    │
    ├─ shared/position->row-col
    │
    └─ q/find-declaration-from-cursor
           │
           ├─ q/find-element-under-cursor
           │
           └─ q/find-declaration (multimethod)
                  │
                  ├─ :var-usages
                  │      ├─ (alias あり) namespace-alias から検索
                  │      ├─ (refer あり) var-usages から refer を検索
                  │      └─ (その他) namespace-usages から検索
                  │
                  └─ :default
                         └─ nil 返却
```

### データフロー図

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

textDocument/declaration ──▶ handlers/declaration ──▶ Location | nil
  - uri                          │
  - position (line, char)        ▼
                            find-declaration-from-cursor
                                 │
                                 ├──▶ find-element-under-cursor
                                 │      └─ db :analysis[uri]
                                 │
                                 ├──▶ find-declaration (multimethod)
                                 │      └─ db :analysis[uri]
                                 │         (namespace-alias, var-usages,
                                 │          namespace-usages)
                                 │
                                 └──▶ element->location
                                        │
                                        ▼
                                   Location {uri, range}
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | LSP リクエストハンドラー（declaration 関数） |
| queries.clj | `lib/src/clojure_lsp/queries.clj` | ソース | 宣言検索のマルチメソッド（find-declaration） |
| shared.clj | `lib/src/clojure_lsp/shared.clj` | ソース | 位置変換ユーティリティ |
| declaration_test.clj | `cli/integration-test/integration/declaration_test.clj` | テスト | 統合テスト |
