# 機能設計書 66-ファイルリネーム

## 概要

本ドキュメントは、Clojure LSPにおけるファイルリネーム機能（workspace/willRenameFiles, workspace/didRenameFiles）の設計を定義する。この機能は、ファイルのリネーム時に名前空間と参照を自動的に更新する。

### 本機能の処理概要

**業務上の目的・背景**：Clojureでは、ファイルパスと名前空間名が1対1で対応している（例：`src/my/namespace.clj` → `my.namespace`）。ファイルをリネームまたは移動した際、名前空間宣言と、他のファイルからの参照を自動的に更新する必要がある。この機能は、エディタのファイルリネーム操作と連携して、名前空間の整合性を自動的に維持する。

**機能の利用シーン**：
- 開発者がエディタのファイルエクスプローラーでファイルをリネーム/移動
- エディタが willRenameFiles を送信し、LSPが名前空間変更のワークスペース編集を返却
- エディタが編集を適用後、didRenameFiles で古いファイルの解析データをクリーンアップ

**主要な処理内容**：
1. willRenameFiles: 新ファイルパスから新名前空間を計算し、リネーム編集を生成
2. didRenameFiles: 古いファイルの解析データとドキュメント情報を削除

**関連システム・外部連携**：LSPクライアント（エディタ）との通信はJSON-RPC経由で行われる。既存のリネーム機能（rename.clj）を再利用する。

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

## 関連画面

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

## 機能種別

リファクタリング処理 / 解析更新

## 入力仕様

### 入力パラメータ

#### willRenameFiles

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| files | array | Yes | リネームするファイルリスト | 各要素は {old-uri, new-uri} 形式 |

#### didRenameFiles

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| files | array | Yes | リネームされたファイルリスト | 各要素は {old-uri, new-uri} 形式 |

### 入力データソース

- LSPクライアントからの workspace/willRenameFiles リクエスト
- LSPクライアントからの workspace/didRenameFiles 通知

## 出力仕様

### 出力データ

#### willRenameFiles

| 項目名 | 型 | 説明 |
|--------|-----|------|
| document-changes | array | テキスト編集リスト |
| document-changes[].text-document | object | 編集対象ドキュメント |
| document-changes[].edits | array | 編集内容 |

#### didRenameFiles

通知のため、直接の戻り値はない。

### 出力先

- willRenameFiles: LSPクライアント（JSON-RPC レスポンス）
- didRenameFiles: 内部DB（解析データ削除）

## 処理フロー

### 処理シーケンス

```
[willRenameFiles]
1. LSPクライアントから workspace/willRenameFiles リクエストを受信
2. 各ファイルについて:
   a. 新URIから新名前空間を計算
   b. 古いファイルの名前空間定義を取得
   c. 新旧名前空間が異なる場合、リネーム編集を生成
3. ワークスペース編集をレスポンスとして返却

[didRenameFiles]
1. LSPクライアントから workspace/didRenameFiles 通知を受信
2. 各ファイルの古いURIに対して:
   a. 解析データを削除
   b. ドキュメント情報を削除
   c. 診断情報を削除
```

### フローチャート

```mermaid
flowchart TD
    subgraph willRenameFiles
        A[willRenameFiles リクエスト] --> B[新URIから名前空間計算]
        B --> C[古い名前空間定義を取得]
        C --> D{名前空間が異なるか?}
        D -->|Yes| E[rename-element でリネーム編集生成]
        D -->|No| F[編集なし]
        E --> G[ワークスペース編集を返却]
        F --> G
    end

    subgraph didRenameFiles
        H[didRenameFiles 通知] --> I[files-deleted 処理]
        I --> J[古いURIの解析データ削除]
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 名前空間一致チェック | 新名前空間と既存名前空間が異なる場合のみ編集を生成 | willRenameFiles |
| BR-02 | 名前空間定義必須 | 名前空間定義がないファイルはスキップ | willRenameFiles |
| BR-03 | 深いマージ | 複数ファイルの編集は deep-merge で統合 | willRenameFiles |
| BR-04 | :rename-file モード | rename-element に :rename-file オプションを渡す | willRenameFiles |

### 計算ロジック

**新名前空間の計算**:
- shared/uri->namespace で新URIから名前空間を導出
- ソースパスとの相対パスから計算

**リネーム編集の生成**:
- rename.clj の rename-element を :rename-file モードで呼び出し
- プロジェクト全体の参照を更新

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 名前空間取得 | db[:analysis][old-uri] | SELECT | 古いファイルの名前空間定義を取得 |
| 解析削除 | db[:analysis][old-uri] | DELETE | 古いファイルの解析データを削除 |
| ドキュメント削除 | db[:documents][old-uri] | DELETE | 古いファイルのドキュメント情報を削除 |

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

#### willRenameFiles

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | namespace-definitions | uri = old-uri | find-namespace-definition-by-uri |

#### didRenameFiles

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | 解析データ全体 | uri = old-uri | files-deleted 経由 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 空編集 | 名前空間定義がないファイル | 空の document-changes を返却 |
| - | 空編集 | 新旧名前空間が同じ | 空の document-changes を返却 |

### リトライ仕様

リトライは不要。

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

- willRenameFiles: 読み取り専用
- didRenameFiles: swap! によるアトミック更新

## パフォーマンス要件

- 単一ファイルのリネームに対して数百ミリ秒以内で応答

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

- 特になし（ローカルファイルの操作）

## 備考

- LSPプロトコル仕様: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_willRenameFiles
- ファイルパターン: `**/*.{clj,cljs,cljc,cljd,edn,bb,clj_kondo}`

---

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

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

### 推奨読解順序

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

リネームリクエストと編集レスポンスの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | rename.clj | `lib/src/clojure_lsp/feature/rename.clj` | rename-element 関数の戻り値構造 |

**読解のコツ**: rename-element は {:document-changes [...]} の形式で編集を返す。各 document-change は {:text-document {:uri ...} :edits [...]} の形式。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | workspace/willRenameFiles ハンドラ（473-483行目） |
| 2-2 | server.clj | `cli/src/clojure_lsp/server.clj` | workspace/didRenameFiles ハンドラ（485-488行目） |
| 2-3 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | will-rename-files, did-rename-files ハンドラ（524-533行目） |

**主要処理フロー**:
1. **473-483行目（server.clj）**: URI正規化とハンドラ委譲
2. **524-528行目（handlers.clj）**: process-after-all-changes で変更待機後、will-rename-files 呼び出し
3. **530-533行目（handlers.clj）**: did-rename-files 処理

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | will-rename-files（402-411行目） |
| 3-2 | file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | did-rename-files（413-414行目） |
| 3-3 | rename.clj | `lib/src/clojure_lsp/feature/rename.clj` | rename-element 関数 |

**主要処理フロー**:
- **402-411行目**: will-rename-files
  - 各ファイルについて新URIから名前空間を計算
  - 古い名前空間定義を取得
  - 名前空間が異なる場合、rename-element で編集を生成
  - reduce + deep-merge で編集を統合
- **413-414行目**: did-rename-files
  - 古いURIのマップを抽出
  - files-deleted を呼び出し

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

```
server.clj (workspace/willRenameFiles リクエスト受信)
    │
    └─ handlers.clj::will-rename-files
           │
           └─ file_management.clj::will-rename-files
                  │
                  ├─ shared/uri->namespace (新名前空間計算)
                  │
                  ├─ queries/find-namespace-definition-by-uri
                  │
                  └─ rename.clj::rename-element
                         │
                         └─ (既存のリネーム処理)

server.clj (workspace/didRenameFiles 通知受信)
    │
    └─ handlers.clj::did-rename-files
           │
           └─ file_management.clj::did-rename-files
                  │
                  └─ files-deleted
                         │
                         └─ db-without-uri
```

### データフロー図

```
[willRenameFiles]

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

{:old-uri A                will-rename-files
 :new-uri B}  ───▶              │
                                ▼
                         uri->namespace(B) = new-ns
                                │
                                ▼
                         find-namespace-definition-by-uri(A) = old-ns-def
                                │
                                ▼
                         new-ns != old-ns ?
                                │
                                ▼
                         rename-element(new-ns, old-ns-def, :rename-file)
                                │
                                ▼
                         {:document-changes [...]}  ───▶  LSPクライアント

[didRenameFiles]

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

{:old-uri A                did-rename-files
 :new-uri B}  ───▶              │
                                ▼
                         files-deleted([A])
                                │
                                ▼
                         db-without-uri(A)  ───▶  内部DB更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | ソース | リネーム処理のコアロジック |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | LSPリクエストハンドラ |
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSPサーバーエントリーポイント |
| rename.clj | `lib/src/clojure_lsp/feature/rename.clj` | ソース | リネーム編集生成 |
| shared.clj | `lib/src/clojure_lsp/shared.clj` | ソース | uri->namespace など |
| file_management_test.clj | `lib/test/clojure_lsp/feature/file_management_test.clj` | テスト | ユニットテスト（317-352行目） |
