# 機能設計書 11-名前空間クリーンアップ

## 概要

本ドキュメントは、clojure-lspの名前空間クリーンアップ（clean-ns）機能の設計を記述する。この機能はClojureファイルのns宣言から未使用のrequire/refer/importを削除し、エントリをアルファベット順にソートする。

### 本機能の処理概要

名前空間クリーンアップ機能は、Clojureファイルのns宣言を整理・最適化するリファクタリング機能である。

**業務上の目的・背景**：Clojure開発において、名前空間宣言は時間とともに肥大化し、使用されていないrequireやimportが残りがちである。これらの不要な宣言はコードの可読性を下げ、コンパイル時間を増加させ、依存関係の把握を困難にする。本機能はこれらの問題を自動的に解決し、コードベースの品質を維持する。

**機能の利用シーン**：
- ファイル編集後にns宣言を整理したい場合
- コードレビュー前にコードを整形したい場合
- リファクタリング後に不要になった依存関係を削除したい場合
- プロジェクト全体の依存関係を見直す場合

**主要な処理内容**：
1. 未使用のエイリアス（:as）を持つrequireの検出と削除
2. 未使用のrefer（:refer [...]）の検出と削除
3. 未使用のimportの検出と削除
4. 重複するrequireの検出と削除
5. require/import内のエントリをアルファベット順にソート
6. インデントとフォーマットの正規化

**関連システム・外部連携**：clj-kondoによる静的解析結果を利用して未使用のシンボルを検出する。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | エディタ | 主画面 | LSPクライアント（VS Code等）からコードアクションまたはコマンドとして実行 |

## 機能種別

リファクタリング / コード整形

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | string | Yes | 対象ファイルのURI | file://形式のURI |
| row | integer | No | カーソル位置の行番号（1-indexed） | 正の整数 |
| col | integer | No | カーソル位置の列番号（1-indexed） | 正の整数 |

### 入力データソース

- LSPクライアントからのtextDocument/codeActionリクエスト
- LSPクライアントからのworkspace/executeCommandリクエスト（clean-nsコマンド）
- CLIからの直接実行

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| range | Range | 編集対象の範囲（ns宣言全体） |
| newText | string | 整形後のns宣言テキスト |

### 出力先

- LSPクライアントへWorkspaceEditとして返却
- CLIの場合は標準出力または直接ファイル編集

## 処理フロー

### 処理シーケンス

```
1. ns宣言の位置特定
   └─ zloc（rewrite-cljのジッパー）を使用してns形式を探索

2. 未使用要素の検出（並列実行）
   ├─ 未使用エイリアスの検出（q/find-unused-aliases）
   ├─ 未使用referの検出（q/find-unused-refers）
   ├─ 未使用importの検出（q/find-unused-imports）
   └─ 重複requireの検出（q/find-duplicate-requires）

3. :require節のクリーンアップ
   └─ 未使用エントリの削除とソート

4. :import節のクリーンアップ
   └─ 未使用エントリの削除とソート

5. ns子要素のソート
   └─ :requireと:importの順序を正規化

6. 編集結果の生成
   └─ 範囲とloc（編集後のジッパー）を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[ns宣言を探索]
    B --> C{ns宣言が存在?}
    C -->|No| D[no-op返却]
    C -->|Yes| E[未使用要素を並列検出]
    E --> F[clean-ctx作成]
    F --> G[:require節のクリーンアップ]
    G --> H[:import節のクリーンアップ]
    H --> I[ns子要素のソート]
    I --> J[編集結果生成]
    J --> K[終了]
    D --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 未使用エイリアス削除 | :asで定義されたエイリアスがコード内で使用されていない場合、そのrequire全体を削除 | エイリアスがvar-usagesに存在しない |
| BR-02 | 未使用refer削除 | :referで指定されたシンボルが未使用の場合、そのシンボルのみを削除 | referシンボルがvar-usagesに存在しない |
| BR-03 | 空require削除 | referを全て削除した結果、requireが空になった場合はrequire全体を削除 | referリストが空 |
| BR-04 | 重複require削除 | 同じ名前空間に対する複数のrequireがある場合、未使用のものを削除 | 同一名前空間で複数エイリアス定義 |
| BR-05 | ソート順序 | アルファベット順（大文字小文字無視）でソート | :clean :sort設定がtrue |
| BR-06 | インデント保持 | :ns-inner-blocks-indentation設定に従ってインデント | 設定による |

### 計算ロジック

- ソート時は`string/lower-case`を使用して大文字小文字を無視
- Reader conditionalは通常のrequireより前に配置

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

本機能はデータベース（db）を読み取り専用で使用する。

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 未使用検出 | :analysis | SELECT | ファイル内のvar-usages等を参照 |

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

#### :analysis

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | :var-usages | uri別にフィルタ | エイリアス使用状況確認 |
| SELECT | :namespace-usages | uri別にフィルタ | 名前空間使用状況確認 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | no-op | ns宣言が見つからない | 何もせず{:no-op? true}を返却 |
| N/A | 解析エラー | ファイルの解析に失敗 | nilまたは空リストを返却 |

### リトライ仕様

特になし。同期的に1回のみ実行。

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

- クライアントに編集結果を返却するのみで、サーバー側でのトランザクション管理は不要
- クライアントがWorkspaceEditを適用

## パフォーマンス要件

- 未使用要素の検出は`future`を使用して並列実行
- 通常のファイルサイズ（~1000行）で100ms以内に完了することを目標

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

- ファイルシステムへの直接書き込みは行わない（LSP経由でクライアントに委譲）
- 入力URIの検証はLSPプロトコルレベルで実施

## 備考

- 設定により動作をカスタマイズ可能
  - `:clean :ns-inner-blocks-indentation` - インデントスタイル（:same-line, :next-line, :keep）
  - `:clean :sort :require` - requireのソート有無
  - `:clean :sort :import` - importのソート有無
  - `:clean :sort :refer :max-line-length` - referの最大行長

---

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

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

### 推奨読解順序

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

クリーンアップ処理で使用されるコンテキストマップ（clean-ctx）の構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | clean_ns.clj | `lib/src/clojure_lsp/feature/clean_ns.clj` | clean-ctxの構造（444-452行目）を確認 |

**読解のコツ**: clean-ctxは以下のキーを持つマップである:
- `:db` - データベース参照
- `:uri` - 対象ファイルURI
- `:unused-aliases` - 未使用エイリアスのセット
- `:unused-refers` - 未使用referのセット
- `:unused-imports` - 未使用importのセット
- `:duplicate-requires` - 重複requireの名前空間セット
- `:ns-inner-blocks-indentation` - インデント設定

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

処理の起点となる関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | command.clj | `lib/src/clojure_lsp/feature/command.clj` | run-command :clean-ns（41-42行目）がエントリーポイント |
| 2-2 | clean_ns.clj | `lib/src/clojure_lsp/feature/clean_ns.clj` | clean-ns-edits関数（433-459行目）がメイン処理 |

**主要処理フロー**:
1. **433行目**: `clean-ns-edits`関数の定義開始
2. **436-437行目**: zloc（ジッパー）の取得とns宣言の探索
3. **440-443行目**: 未使用要素の並列検出（future使用）
4. **453-456行目**: clean-requires、clean-imports、sort-ns-childrenの順に処理

#### Step 3: requireクリーンアップ処理を理解する

:require節の処理ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | clean_ns.clj | `lib/src/clojure_lsp/feature/clean_ns.clj` | clean-requires関数（299-308行目） |
| 3-2 | clean_ns.clj | `lib/src/clojure_lsp/feature/clean_ns.clj` | remove-unused-requires関数（253-280行目） |
| 3-3 | clean_ns.clj | `lib/src/clojure_lsp/feature/clean_ns.clj` | process-clean-ns関数（50-141行目）- ソートと再構築 |

**主要処理フロー**:
- **299-301行目**: :require節を探索
- **304-306行目**: 未使用requireを削除
- **307行目**: process-clean-nsでソートと再フォーマット

#### Step 4: importクリーンアップ処理を理解する

:import節の処理ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | clean_ns.clj | `lib/src/clojure_lsp/feature/clean_ns.clj` | clean-imports関数（398-407行目） |
| 4-2 | clean_ns.clj | `lib/src/clojure_lsp/feature/clean_ns.clj` | remove-unused-import関数（369-396行目） |

**主要処理フロー**:
- **400行目**: :import節を探索
- **403-405行目**: 未使用importを削除し、パッケージimportをソート

#### Step 5: クエリ層を理解する

未使用要素の検出ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | queries.clj | `lib/src/clojure_lsp/queries.clj` | find-unused-aliases, find-unused-refers, find-unused-imports関数 |

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

```
handlers/execute-command
    │
    └─ f.command/call-command
           │
           └─ run-command :clean-ns
                  │
                  └─ f.clean-ns/clean-ns-edits
                         │
                         ├─ edit/find-namespace
                         │
                         ├─ [並列] q/find-unused-aliases
                         ├─ [並列] q/find-unused-refers
                         ├─ [並列] q/find-unused-imports
                         └─ [並列] q/find-duplicate-requires
                         │
                         ├─ clean-requires
                         │      └─ remove-unused-requires
                         │             └─ remove-unused-require
                         │                    └─ remove-unused-refers
                         │      └─ process-clean-ns
                         │
                         ├─ clean-imports
                         │      └─ remove-unused-import
                         │      └─ process-clean-ns
                         │
                         └─ sort-ns-children
```

### データフロー図

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

uri ─────────────────┬─> zloc取得 ─────────────> ns-loc
                     │
db[:analysis] ───────┼─> 未使用要素検出 ────────> clean-ctx
                     │       │
                     │       ├─> unused-aliases
                     │       ├─> unused-refers
                     │       ├─> unused-imports
                     │       └─> duplicate-requires
                     │
ns-loc + clean-ctx ──┴─> クリーンアップ処理 ───> result-loc
                              │
                              ├─> clean-requires
                              ├─> clean-imports
                              └─> sort-ns-children
                                         │
                                         └─────────────> [{:range :loc}]
                                                              │
                                                              └─> WorkspaceEdit
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| clean_ns.clj | `lib/src/clojure_lsp/feature/clean_ns.clj` | ソース | メインのクリーンアップロジック |
| command.clj | `lib/src/clojure_lsp/feature/command.clj` | ソース | コマンドディスパッチャー |
| code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | ソース | コードアクション提供 |
| queries.clj | `lib/src/clojure_lsp/queries.clj` | ソース | 未使用要素検出クエリ |
| edit.clj | `lib/src/clojure_lsp/refactor/edit.clj` | ソース | ジッパー操作ユーティリティ |
| settings.clj | `lib/src/clojure_lsp/settings.clj` | ソース | 設定値取得 |
| clean_ns_test.clj | `lib/test/clojure_lsp/feature/clean_ns_test.clj` | テスト | 単体テスト |
