# 画面設計書 28-リネーム（textDocument/rename）

## 概要

本ドキュメントは、serve-d LSPサーバーにおける `textDocument/rename` および `textDocument/prepareRename` リクエストの処理仕様を定義する画面設計書である。カーソル位置のシンボルを新しい名前にリネームする機能を提供する。

### 本画面の処理概要

**業務上の目的・背景**：D言語開発において、変数名・関数名・型名などの識別子を一括でリネームする機能は、コードの可読性向上やリファクタリングの基本操作として不可欠である。本機能はLSPプロトコルの `textDocument/rename` を通じて、エディタの「シンボルのリネーム」機能を実現する。内部的にドキュメントハイライト機能（No.25）の `documentHighlightImpl` を活用し、ローカル変数の宣言箇所と使用箇所を検出してリネーム対象とする。

**画面へのアクセス方法**：エディタ上でD言語ソースファイルのシンボル上にカーソルを置き、「シンボルのリネーム」コマンド（通常はF2キー）を実行する。エディタが `textDocument/prepareRename` で事前確認を行い、続いて `textDocument/rename` でリネームを実行する。

**主要な操作・処理内容**：
1. `textDocument/prepareRename`: カーソル位置のシンボルがリネーム可能かを事前判定し、シンボルの範囲を返却する
2. `textDocument/rename`: カーソル位置のシンボルの宣言箇所と全使用箇所を検出し、新しい名前に置換するWorkspaceEditを返却する
3. 内部的に `documentHighlightImpl` を使用してローカル使用箇所を検出する

**画面遷移**：リネーム結果はWorkspaceEditとしてエディタに返却され、エディタ側で一括テキスト変更が適用される。画面遷移図の「シンボル操作」サブグラフにおいて「リネーム」として位置付けられている。

**権限による表示制御**：権限による表示制御は存在しない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | リネーム (textDocument/rename) | 主機能 | カーソル位置のシンボルを新しい名前にリネームするためのWorkspaceEditを返却する |
| 25 | リネーム準備 (textDocument/prepareRename) | 補助機能 | リネーム対象のシンボル範囲を返却しリネーム可能かどうかを事前判定する |

## 画面種別

編集操作（LSPプロトコルレスポンス）

## URL/ルーティング

- LSPメソッド: `textDocument/rename`
- LSPメソッド: `textDocument/prepareRename`

## 入出力項目

### textDocument/rename

| 項目名 | 型 | 入力/出力 | 必須 | 説明 |
|--------|-----|----------|------|------|
| params.textDocument.uri | DocumentUri | 入力 | Yes | 対象ドキュメントのURI |
| params.position | Position | 入力 | Yes | カーソル位置 |
| params.newName | string | 入力 | Yes | 新しいシンボル名 |
| Nullable!WorkspaceEdit | WorkspaceEdit | 出力 | - | リネーム用テキスト編集（リネーム不可の場合はnull） |

### textDocument/prepareRename

| 項目名 | 型 | 入力/出力 | 必須 | 説明 |
|--------|-----|----------|------|------|
| params.textDocument.uri | DocumentUri | 入力 | Yes | 対象ドキュメントのURI |
| params.position | Position | 入力 | Yes | カーソル位置 |
| Nullable!TextRange | TextRange | 出力 | - | リネーム対象シンボルの範囲（リネーム不可の場合はnull） |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|---------|------|
| リネームダイアログ | テキスト入力 | エディタがprepareRenameの結果を受けてリネームダイアログを表示する（エディタ側機能） |
| リネーム結果 | テキスト変更 | WorkspaceEditが適用され、全使用箇所が一括置換される |

## イベント仕様

### 1-リネーム準備（prepareRename）

リネーム操作の前にエディタが呼び出す事前確認処理（行34-45）。

1. ドキュメントのimmutableクローンを作成する（行37）
2. カーソル位置をバイトオフセットに変換する（行38）
3. `documentHighlightImpl` でシンボルのハイライト情報を取得する（行40）
4. ハイライト結果が存在し、最初の要素が `write` 種別（宣言箇所）の場合:
   a. 宣言箇所の範囲（`highlight[0].range`）を返却する（行42）
5. それ以外の場合は `null` を返却する（リネーム不可を意味する）（行44）

### 2-リネーム実行（rename）

ユーザーが新しい名前を入力してリネームを実行した際の処理フロー（行12-32）。

1. ドキュメントのimmutableクローンを作成する（行15）
2. カーソル位置をバイトオフセットに変換する（行16）
3. `documentHighlightImpl` でシンボルのハイライト情報を取得する（行18）
4. ハイライト結果が存在し、最初の要素が `write` 種別の場合:
   a. 各ハイライト箇所について `TextEdit(range, newName)` を生成する（行23-24）
   b. 最初の要素（宣言箇所）と同じ範囲のハイライトは重複として除外する（行23）
   c. TextEditをrange.startの降順でソートする（行26）
   d. `WorkspaceEdit` を構築し、対象ドキュメントのURIにTextEdit配列を設定する（行27）
5. ハイライト結果がないか `write` 種別でない場合は `null` を返却する（行31）

## データベース更新仕様

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

本機能はデータベースに対する操作を行わない。リネーム結果はWorkspaceEditとしてクライアントに返却され、クライアント側でドキュメントに適用される。

## メッセージ仕様

本機能は明示的なメッセージ表示を行わない。リネーム不可の場合はnullが返却され、エディタ側でリネーム不可を伝える表示が行われる（エディタ側の実装依存）。

## 例外処理

| 条件 | 挙動 |
|------|------|
| documentHighlightImplの結果が空 | `null` を返却（リネーム不可） |
| ハイライトの最初の要素がwrite種別でない | `null` を返却（宣言箇所が見つからない） |
| DCDコンポーネントが利用不可 | documentHighlightImplが `null` を返却→リネーム不可 |

## 備考

- リネーム機能はローカル変数のスコープ内でのみ動作する。これは内部的に `documentHighlightImpl` を使用しているため、DCDの `findLocalUse` の範囲に限定される
- TextEditの降順ソートは、エディタ側で適用する際に位置がずれないようにするための対策である
- 宣言箇所と同じ範囲のハイライトを除外する処理（行23）は、宣言箇所が使用箇所としても検出される場合の重複防止である
- 本機能はhighlight.dの `documentHighlightImpl` をpackageスコープでインポートして使用している

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protocol.d | `source/served/lsp/protocol.d` | `RenameParams`, `PrepareRenameParams`, `WorkspaceEdit`, `TextEdit` の定義を確認 |

**読解のコツ**: `WorkspaceEdit` の `changes` フィールドは `TextEdit[][DocumentUri]` 型の連想配列で、URI別にTextEdit配列を保持する。

#### Step 2: 前提となるハイライト機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | highlight.d | `source/served/commands/highlight.d` | `documentHighlightImpl` 関数（行26-58）: リネームの基盤となるローカル使用箇所検索 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rename.d | `source/served/commands/rename.d` | `provideRename` 関数（行12-32）と `prepareRename` 関数（行34-45）の2つのハンドラ |

**主要処理フロー（provideRename）**:
1. **行12**: `@protocolMethod("textDocument/rename")` でバインド
2. **行15**: ドキュメントのimmutableクローン作成
3. **行18**: `documentHighlightImpl` 呼び出し
4. **行19**: write種別の存在確認
5. **行21-24**: TextEdit配列の生成（重複除外付き）
6. **行26**: 降順ソート
7. **行27**: WorkspaceEditへの設定

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

```
textDocument/prepareRename リクエスト
    |
    +-- prepareRename (rename.d:34)
           |
           +-- documents[uri].clone() (immutableコピー)
           +-- documentHighlightImpl (highlight.d:26)
                  +-- DCDComponent.findLocalUse

textDocument/rename リクエスト
    |
    +-- provideRename (rename.d:12)
           |
           +-- documents[uri].clone() (immutableコピー)
           +-- documentHighlightImpl (highlight.d:26)
           |      +-- DCDComponent.findLocalUse
           +-- TextEdit[] 生成 (重複除外・降順ソート)
           +-- WorkspaceEdit 構築
```

### データフロー図

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

RenameParams -------------> provideRename --------------------> WorkspaceEdit
  textDocument.uri            |
  position                    +-- documentHighlightImpl
  newName                     |      --> DocumentHighlight[]
                              |      (write=宣言, read=使用)
                              +-- TextEdit(range, newName) 生成
                              +-- 重複除外 + 降順ソート
                              +-- WorkspaceEdit.changes[uri] = edits
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| rename.d | `source/served/commands/rename.d` | ソース | リネームの主処理 |
| highlight.d | `source/served/commands/highlight.d` | ソース | documentHighlightImpl（ローカル使用箇所検索） |
| types.d | `source/served/types.d` | ソース | 共通型定義 |
| protocol.d | `source/served/lsp/protocol.d` | ソース | LSPプロトコル型定義 |
