# 機能設計書 53-参照数表示

## 概要

本ドキュメントは、clojure-lspにおける参照数表示（Code Lens）機能の設計を記述する。この機能はLSPプロトコルの`textDocument/codeLens`リクエストを実装し、シンボルの参照数をエディタ上にインラインで表示する。

### 本機能の処理概要

**業務上の目的・背景**：
大規模なコードベースでは、関数や変数がどの程度使用されているかを把握することが重要である。参照数が多いシンボルは変更時の影響範囲が大きく、慎重なリファクタリングが必要となる。逆に、参照数が0のシンボルは未使用である可能性が高く、削除候補となる。Code Lens機能は、これらの情報をコード内にインラインで表示することで、開発者がコードの依存関係を即座に把握できるようにする。

**機能の利用シーン**：
1. 関数の利用状況を確認する場面
2. 未使用コードの特定
3. リファクタリングの影響範囲の把握
4. コードレビュー時の依存関係確認

**主要な処理内容**：
1. ドキュメント内の全シンボル定義（名前空間、変数、キーワード）を取得
2. 各シンボルの範囲情報とメタデータを返却（遅延評価）
3. Code Lens選択時に参照検索を実行（resolve）
4. 参照数をテキストとして整形して表示

**関連システム・外部連携**：
- clj-kondo：解析データの提供
- LSPクライアント（エディタ）：Code Lensの表示

**権限による制御**：
特に権限による制御はない。設定で機能を無効化可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | エディタ | 主画面 | 参照数のインライン表示 |

## 機能種別

情報表示処理 / 検索処理

## 入力仕様

### 入力パラメータ（codeLens）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| textDocument.uri | string | Yes | 対象ドキュメントのURI | 有効なファイルURI形式 |

### 入力パラメータ（codeLens/resolve）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| range | Range | Yes | Code Lensの範囲 | 有効なRange |
| data | array | Yes | [uri, row, col] | 配列形式 |

### 入力データソース

- LSPクライアントからの`textDocument/codeLens`リクエスト
- 解析データ（db.analysis）

## 出力仕様

### 出力データ（codeLens）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| range | Range | シンボルの位置範囲 |
| data | array | [uri, row, col]形式の位置情報 |

### 出力データ（codeLens/resolve）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| range | Range | シンボルの位置範囲 |
| command.title | string | 表示テキスト（例: "3 references"） |
| command.command | string | "code-lens-references" |
| command.arguments | array | [uri, row, col] |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
codeLens リクエスト:
1. リクエスト受信
   └─ textDocument/codeLensを受信
2. ドキュメント内シンボル収集
   └─ 名前空間定義、変数定義、キーワード定義を収集
3. フィルタリング
   └─ exclude-public-definition?で除外対象をフィルタ
4. Code Lens生成
   └─ 各シンボルのrangeとdataを生成
5. レスポンス返却

codeLens/resolve リクエスト:
1. リクエスト受信
   └─ codeLens/resolveを受信
2. 参照検索
   └─ find-references-from-cursorで参照を検索
3. 参照分類（オプション）
   └─ segregate-test-references設定に応じて分類
4. 表示テキスト生成
   └─ "N references" または "N references | M tests"
5. レスポンス返却
```

### フローチャート

```mermaid
flowchart TD
    subgraph codeLens
        A1[codeLens受信] --> B1[名前空間定義取得]
        B1 --> C1[変数定義取得]
        C1 --> D1[キーワード定義取得]
        D1 --> E1[除外対象フィルタ]
        E1 --> F1[Code Lens配列生成]
        F1 --> G1[レスポンス返却]
    end

    subgraph resolve
        A2[resolve受信] --> B2[参照検索]
        B2 --> C2{segregate-test-references?}
        C2 -->|Yes| D2[テスト参照分離]
        C2 -->|No| E2[全参照カウント]
        D2 --> F2[テキスト生成]
        E2 --> F2
        F2 --> G2[レスポンス返却]
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-53-01 | 対象シンボル | 名前空間定義、変数定義、キーワード定義をCode Lens対象 | 常時 |
| BR-53-02 | 除外ルール | exclude-public-definition?でマッチするシンボルは除外 | 設定による |
| BR-53-03 | 遅延評価 | 参照数の計算はresolve時まで遅延 | パフォーマンス最適化 |
| BR-53-04 | 複数形処理 | 1件は"reference"、複数は"references" | 表示時 |
| BR-53-05 | 自己参照除外 | 定義自体は参照カウントに含めない | 常時 |

### 計算ロジック

参照数の算出:
```clojure
(count (q/find-references-from-cursor db uri row col false))
```
- `false`パラメータで定義自体を参照カウントから除外

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| シンボル取得 | db.analysis | SELECT | 定義シンボルの取得 |
| 参照検索 | db.analysis | SELECT | 参照元の検索 |

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

#### db.analysis

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | namespace-definitions | uri = 対象URI | 名前空間定義 |
| SELECT | var-definitions | uri = 対象URI | 変数定義 |
| SELECT | keyword-definitions | uri = 対象URI | キーワード定義 |
| SELECT | var-usages | 参照検索時 | 参照元検索 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | タイムアウト | 変更待機が60秒超過 | request-failedエラー |
| - | キャンセル | クライアントがキャンセル | request-cancelledエラー |

### リトライ仕様

リトライは行わない。クライアント側で再度リクエスト。

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

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

## パフォーマンス要件

- Code Lens取得: 通常数十ミリ秒
- Resolve: 通常数百ミリ秒以内（参照数に依存）

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

- 特になし

## 備考

- Code Lensは`code-lens-provider`設定で有効/無効を切り替え可能
- `workspace/codeLens/refresh`でクライアントに再取得を要求可能

---

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

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

### 推奨読解順序

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

Code Lensのデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | code_lens.clj | `lib/src/clojure_lsp/feature/code_lens.clj` | Code Lens応答の構造（range, data, command） |

**読解のコツ**: Code Lensは2段階で動作。初回は軽量なデータのみ返却し、resolve時に重い処理（参照検索）を実行。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | **341-346行目**: codeLensハンドラ |
| 2-2 | server.clj | `cli/src/clojure_lsp/server.clj` | **348-352行目**: codeLens/resolveハンドラ |

**主要処理フロー**:
1. **341-346行目**: `textDocument/codeLens`リクエストを`handler/code-lens`に委譲
2. **348-352行目**: `codeLens/resolve`リクエストを`handler/code-lens-resolve`に委譲

#### Step 3: ハンドラ層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | **440-446行目**: `code-lens`関数 |
| 3-2 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | **448-452行目**: `code-lens-resolve`関数 |

**主要処理フロー**:
- **442行目**: `skip-feature-for-uri?`でignore-pathsチェック
- **443-446行目**: `process-after-changes`で変更待機後に`f.code-lens/reference-code-lens`呼び出し
- **449-452行目**: `f.code-lens/resolve-code-lens`で参照検索実行

#### Step 4: Code Lens生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | code_lens.clj | `lib/src/clojure_lsp/feature/code_lens.clj` | **23-31行目**: `reference-code-lens`関数 |

**主要処理フロー**:
- **24-27行目**: 各要素をCode Lensに変換（range, data）
- **28行目**: 名前空間定義を取得
- **29-31行目**: 変数定義とキーワード定義を取得し、除外対象をフィルタ

#### Step 5: Code Lens解決処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | code_lens.clj | `lib/src/clojure_lsp/feature/code_lens.clj` | **39-67行目**: `resolve-code-lens`関数 |

**主要処理フロー**:
- **40-45行目**: segregate-test-references設定とtest-locations-regexを取得
- **46行目**: `q/find-references-from-cursor`で参照を検索
- **47-63行目**: segregate-lens?に応じて参照を分類
- **55-58行目**: テスト参照がある場合は"N references | M tests"形式
- **60-62行目**: テスト参照がない場合は"N references"形式

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

```
textDocument/codeLens (server.clj:341-346)
    │
    ├─ handler/code-lens (handlers.clj:440-446)
    │      │
    │      ├─ skip-feature-for-uri?
    │      │
    │      └─ f.code-lens/reference-code-lens (code_lens.clj:23-31)
    │             │
    │             ├─ q/find-namespace-definitions
    │             ├─ q/find-var-definitions
    │             ├─ q/find-keyword-definitions
    │             └─ q/exclude-public-definition?
    │
    └─ conform-or-log

codeLens/resolve (server.clj:348-352)
    │
    ├─ handler/code-lens-resolve (handlers.clj:448-452)
    │      │
    │      └─ f.code-lens/resolve-code-lens (code_lens.clj:39-67)
    │             │
    │             ├─ settings/get :segregate-test-references
    │             ├─ settings/get :test-locations-regex
    │             ├─ q/find-references-from-cursor
    │             └─ test-reference? (code_lens.clj:33-37)
    │
    └─ conform-or-log
```

### データフロー図

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

textDocument/codeLens    ┌──────────────────────────────────┐
Request                  │                                  │
  └─ uri ───────────────►│  reference-code-lens             │
                         │    ├─ namespace-definitions ───►│────►  CodeLens[]
db.analysis             │    ├─ var-definitions ─────────►│         ├─ range
  ├─ namespace-defs ────►│    └─ keyword-definitions ─────►│         └─ data
  ├─ var-definitions ───►│                                  │
  └─ keyword-defs ──────►└──────────────────────────────────┘

codeLens/resolve        ┌──────────────────────────────────┐
Request                  │                                  │
  ├─ range ─────────────►│  resolve-code-lens               │
  └─ data ──────────────►│    ├─ find-references ─────────►│────►  CodeLens
       [uri,row,col]     │    └─ test-reference? ─────────►│         ├─ range
                         │                                  │         └─ command
settings                │                                  │              ├─ title
  ├─ segregate-test... ─►│                                  │              ├─ command
  └─ test-locations... ─►└──────────────────────────────────┘              └─ arguments
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSPサーバーハンドラ定義 |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | 各機能のハンドラ実装 |
| code_lens.clj | `lib/src/clojure_lsp/feature/code_lens.clj` | ソース | Code Lens機能の実装 |
| queries.clj | `lib/src/clojure_lsp/queries.clj` | ソース | 解析データのクエリ |
| code_lens_test.clj | `lib/test/clojure_lsp/feature/code_lens_test.clj` | テスト | Code Lens機能のテスト |
