# 機能設計書 25-リネーム準備 (textDocument/prepareRename)

## 概要

本ドキュメントは、serve-d LSPサーバーにおけるリネーム準備機能（textDocument/prepareRename）の設計を記述する。リネーム対象のシンボル範囲を返却し、リネーム可能かどうかを事前判定する機能である。

### 本機能の処理概要

**業務上の目的・背景**：リネーム操作を実行する前に、カーソル位置のシンボルがリネーム可能かどうかを判定し、リネーム可能な場合はシンボルの範囲を返すことで、エディタが入力ダイアログのデフォルト値を正しく表示できるようにする。

**機能の利用シーン**：開発者がエディタ上でリネームコマンドを実行した直後に呼び出される。リネーム不可の場合はエディタがリネーム入力ダイアログの表示を中止する。

**主要な処理内容**：
1. ドキュメントハイライト機能（No.22）のdocumentHighlightImplを呼び出してシンボルの使用箇所を取得する
2. 最初のハイライトがwrite種別（宣言箇所）であることを確認する
3. リネーム可能と判定した場合、宣言箇所の範囲を返却する

**関連システム・外部連携**：DCDComponent（documentHighlightImpl経由で使用）、ドキュメントハイライト機能（No.22）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 28 | リネーム（textDocument/rename） | 補助機能 | リネーム対象のシンボル範囲を返却しリネーム可能かどうかを事前判定する |

## 機能種別

バリデーション（リネーム可能性の事前判定）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| textDocument.uri | DocumentUri | Yes | 対象ドキュメントのURI | 有効なドキュメントURIであること |
| position | Position | Yes | カーソル位置（行・列） | ドキュメント範囲内であること |

### 入力データソース

- LSPクライアントからのtextDocument/prepareRenameリクエストのPrepareRenameParams

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| range | TextRange | リネーム対象シンボルの宣言箇所範囲。Nullable型でリネーム不可時はnull |

### 出力先

LSPクライアント（JSON-RPCレスポンスとして返却。Nullable!TextRange型）

## 処理フロー

### 処理シーケンス

```
1. textDocument/prepareRenameリクエスト受信
   └─ PrepareRenameParamsからURI・位置を取得
2. ドキュメントのimmutableクローン取得
   └─ cast(immutable)documents[uri].clone()
3. カーソル位置をバイトオフセットに変換
   └─ document.positionToBytes(params.position)
4. documentHighlightImplを呼び出し
   └─ ドキュメントハイライト機能のDCD実装を直接利用
5. リネーム可能性判定
   └─ highlight.length > 0 かつ highlight[0].kind == write
6. 結果返却
   └─ 可能な場合: 宣言箇所のrange
   └─ 不可の場合: Nullable.init（null）
```

### フローチャート

```mermaid
flowchart TD
    A[prepareRename リクエスト受信] --> B[ドキュメントimmutableクローン取得]
    B --> C[カーソル位置をバイトオフセットに変換]
    C --> D[documentHighlightImpl呼び出し]
    D --> E{結果あり and 最初がwrite種別?}
    E -->|No| F[Nullable.init返却 リネーム不可]
    E -->|Yes| G[宣言箇所のrange返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-25-01 | 宣言箇所必須 | 最初のハイライトがwrite種別でない場合はリネーム不可 | リネーム可能性判定時 |
| BR-25-02 | 範囲返却 | リネーム可能な場合、最初のハイライト（宣言箇所）のrangeを返す | 結果返却時 |

### 計算ロジック

特になし。

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

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

データベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | リネーム不可 | ハイライト結果が空の場合 | Nullable.init（null）を返却 |
| - | リネーム不可 | 最初のハイライトがwrite種別でない場合 | Nullable.init（null）を返却 |

### リトライ仕様

リトライは不要。

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

トランザクションは使用しない（読み取り専用操作）。

## パフォーマンス要件

- リネーム操作のUI表示前に呼ばれるため、低レイテンシが求められる
- documentHighlightImplのDCDレスポンスに依存

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

特になし。

## 備考

- 本機能はリネーム機能（No.24）と全く同じdocumentHighlightImplを使用しており、判定ロジックも同一（最初のハイライトがwrite種別であること）
- provideRenameとprepareRenameは同じrename.dファイルに実装されている
- prepareRenameはリネームダイアログの表示前に呼ばれる軽量な判定処理であり、実際のリネーム編集はprovideRenameで行われる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.d | `source/served/types.d` | TextRange, Nullable!TextRange, PrepareRenameParamsの型定義 |

**読解のコツ**: D言語のNullable型は、値が存在しない場合を安全に表現する。`typeof(return).init`で「値なし」状態のNullableを返す。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | rename.d | `source/served/commands/rename.d` | prepareRename関数（34-45行目）がLSPプロトコルメソッドのエントリーポイント |

**主要処理フロー**:
1. **37行目**: `cast(immutable)documents[...].clone()` ドキュメントのimmutableクローン取得
2. **38行目**: `document.positionToBytes` バイトオフセット変換
3. **40行目**: `documentHighlightImpl(document, currOffset)` ハイライト機能の呼び出し
4. **41行目**: `highlight[0].kind == DocumentHighlightKind.write` 宣言箇所の確認
5. **42行目**: `typeof(return)(highlight[0].range)` 宣言箇所のrange返却

#### Step 3: リネーム機能との比較

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rename.d | `source/served/commands/rename.d` | provideRename関数（12-32行目）との比較。同じdocumentHighlightImplと同じ判定条件を使用 |

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

```
prepareRename (rename.d:35)
    |
    +-- documentHighlightImpl (highlight.d:26) [package]
    |       |
    |       +-- DCDComponent.findLocalUse
    |       +-- Document.wordRangeAt
    |       +-- Document.nextPositionBytes
    |
    +-- highlight[0].range 返却
```

### データフロー図

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

PrepareRenameParams -------> prepareRename --------------------> Nullable!TextRange
  (uri, position)                  |
                                   v
                            documentHighlightImpl
                                   |
                                   v
                            DocumentHighlight[] (宣言+使用箇所)
                                   |
                                   v
                            highlight[0].kind == write ?
                                   |
                              Yes: highlight[0].range
                              No:  null
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| rename.d | `source/served/commands/rename.d` | ソース | リネーム準備のメイン実装（prepareRename: 34-45行目） |
| highlight.d | `source/served/commands/highlight.d` | ソース | documentHighlightImpl関数（packageスコープ）の提供元 |
| types.d | `source/served/types.d` | ソース | LSP型定義（TextRange, PrepareRenameParams等） |
| dcd.d (workspaced) | `workspace-d/source/workspaced/com/dcd.d` | ソース | DCDComponent.findLocalUse APIの実装 |
