# 機能設計書 63-連動編集範囲

## 概要

本ドキュメントは、Clojure LSPにおける連動編集範囲機能（textDocument/linkedEditingRange）の設計を定義する。この機能は、名前空間エイリアスなど、同一シンボルの複数箇所を同時に編集するための範囲情報を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Clojureでは名前空間のエイリアス（`:as` で定義）を使って短い名前でライブラリを参照する。エイリアス名を変更する際、定義箇所と使用箇所を同時に変更したいニーズがある。この機能は、エディタの連動編集（Linked Editing）機能と連携して、エイリアスの全ての出現箇所を一括で編集可能にする。

**機能の利用シーン**：開発者が名前空間エイリアス上にカーソルを置き、編集を開始すると、エディタがこの機能を呼び出す。LSPサーバーは、同じエイリアスの全ての出現箇所を返し、エディタはそれらを同時に編集モードにする。

**主要な処理内容**：
1. 指定されたURI・位置からカーソル下の要素を特定
2. 要素が名前空間エイリアス（:namespace-alias バケット）であることを確認
3. 同一エイリアスの全参照箇所を検索し、その範囲を返却

**関連システム・外部連携**：LSPクライアント（エディタ）との通信はJSON-RPC経由で行われる。clj-kondoの解析結果を利用して参照箇所を特定する。

**権限による制御**：特に権限制御は存在しない。全ユーザーが同等にこの機能を利用できる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 該当なし | 該当なし | 該当なし | 本機能はLSPプロトコルを通じてエディタから呼び出される |

## 機能種別

データ取得処理 / 参照検索処理 / LSPレスポンス生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | string | Yes | 対象ファイルのURI | 有効なファイルURIであること |
| position | object | Yes | カーソル位置 | {line, character} 形式 |

### 入力データソース

- LSPクライアントからの textDocument/linkedEditingRange リクエスト
- 内部DB（解析済みの要素情報）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ranges | array | 連動編集対象の範囲リスト |
| ranges[].start | object | 範囲の開始位置 {line, character} |
| ranges[].end | object | 範囲の終了位置 {line, character} |

### 出力先

LSPクライアント（JSON-RPC レスポンス）

## 処理フロー

### 処理シーケンス

```
1. LSPクライアントから textDocument/linkedEditingRange リクエストを受信
   └─ handlers.clj の linked-editing-ranges ハンドラが呼び出される
2. カーソル位置の要素を特定
   └─ queries.clj の find-element-under-cursor を使用
3. 要素が名前空間エイリアスか確認
   └─ :bucket が :namespace-alias であることを確認
4. 同一エイリアスの全参照を検索
   └─ queries.clj の find-references を使用
5. 各参照箇所からエイリアス名部分の範囲を計算
   └─ エイリアスの長さに基づいて終了位置を計算
6. LinkedEditingRanges 形式でレスポンスを返却
```

### フローチャート

```mermaid
flowchart TD
    A[textDocument/linkedEditingRange リクエスト受信] --> B[カーソル位置の要素を特定]
    B --> C{名前空間エイリアスか?}
    C -->|No| D[nil を返却]
    C -->|Yes| E[find-references で全参照を取得]
    E --> F[各参照のエイリアス範囲を計算]
    F --> G[LinkedEditingRanges レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | エイリアス限定 | 名前空間エイリアス（:namespace-alias）のみが対象 | 常時 |
| BR-02 | 定義を含む | find-references の include-definition を true にして定義箇所も含める | 常時 |
| BR-03 | 範囲計算 | エイリアスの長さから終了位置を計算 | 常時 |

### 計算ロジック

**エイリアス範囲の計算（alias-range）**:
- start = {name-row, name-col}（参照の名前開始位置）
- end = {name-row, name-col + alias-length}（開始位置 + エイリアス長）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 要素検索 | db[:analysis][uri] | SELECT | カーソル位置の要素を取得 |
| 参照検索 | db[:analysis] | SELECT | 同一エイリアスの全参照を検索 |

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

#### db[:analysis][uri]

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | :namespace-alias, :var-usages, :keyword-usages | uri = 指定URI | find-element-under-cursor, find-references 経由 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | nil | 名前空間エイリアス以外の要素上 | nil を返却 |
| - | nil | カーソル位置に要素がない | nil を返却 |

### リトライ仕様

リトライは不要。

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

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

## パフォーマンス要件

- 通常のClojureファイルに対して数十ミリ秒以内で応答

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

- 特になし（ローカルファイルの読み取り専用）

## 備考

- LSPプロトコル仕様: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_linkedEditingRange
- 現在の実装では名前空間エイリアスのみ対応

---

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

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

### 推奨読解順序

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

名前空間エイリアスの解析データ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | queries.clj | `lib/src/clojure_lsp/queries.clj` | find-element-under-cursor 関数（625-629行目） |

**読解のコツ**: :namespace-alias バケットは、require の :as で定義されたエイリアスを表す。各要素は :alias, :to, :name-row, :name-col などを持つ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | textDocument/linkedEditingRange リクエストハンドラ（422-427行目） |
| 2-2 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | linked-editing-ranges ハンドラ関数（500-507行目） |

**主要処理フロー**:
1. **422-427行目（server.clj）**: LSPリクエストを受信し、ハンドラに委譲
2. **500-507行目（handlers.clj）**: DBを取得し、f.linked-editing-range/ranges を呼び出し

#### Step 3: コア機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | linked_editing_range.clj | `lib/src/clojure_lsp/feature/linked_editing_range.clj` | 連動編集範囲のコアロジック（全19行） |

**主要処理フロー**:
- **8-10行目**: alias-range - エイリアスの範囲を計算する補助関数
- **12-18行目**: ranges - メイン関数
  - find-element-under-cursor でカーソル下の要素を取得
  - :namespace-alias であることを確認（fast=）
  - find-references で全参照を取得
  - 各参照に対して alias-range を適用

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

```
server.clj (textDocument/linkedEditingRange リクエスト受信)
    │
    └─ handlers.clj::linked-editing-ranges
           │
           └─ feature/linked_editing_range.clj::ranges
                  │
                  ├─ queries.clj::find-element-under-cursor
                  │
                  └─ queries.clj::find-references
                         │
                         └─ find-references :namespace-alias (multimethod)
```

### データフロー図

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

URI + Position  ───▶  ranges
                          │
                          ▼
                   find-element-under-cursor
                          │
                          ▼
                   element (e.g., {:bucket :namespace-alias
                                   :alias 'baz
                                   :to 'bar ...})
                          │
                          ▼
                   :namespace-alias か確認
                          │
                          ▼
                   find-references
                          │
                          ▼
                   参照リスト
                          │
                          ▼
                   alias-range (map)
                          │
                          ▼
                   {:ranges [{:start {...} :end {...}} ...]}  ───▶  LSPクライアント
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| linked_editing_range.clj | `lib/src/clojure_lsp/feature/linked_editing_range.clj` | ソース | 連動編集範囲のコアロジック |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | LSPリクエストハンドラ |
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSPサーバーエントリーポイント |
| queries.clj | `lib/src/clojure_lsp/queries.clj` | ソース | 解析データクエリ関数群 |
| linked_editing_range_test.clj | `lib/test/clojure_lsp/feature/linked_editing_range_test.clj` | テスト | ユニットテスト |
