# 機能設計書 21-コレクション変換

## 概要

本ドキュメントは、clojure-lspの「コレクション変換」機能（change-collコマンド）の設計仕様を定義する。この機能は、Clojureのコレクション型（vector、list、map、set）を相互に変換するリファクタリング機能を提供する。

### 本機能の処理概要

コレクション変換機能は、カーソル位置にあるClojureコレクション（ベクター、リスト、マップ、セット）を別のコレクション型に変換する。この機能により、コードの意図に応じたデータ構造の変更を、手動での書き換えなしに安全かつ迅速に行うことができる。

**業務上の目的・背景**：Clojure開発において、データ構造の選択は重要であり、開発の進行に伴い適切なコレクション型が変わることがある。例えば、順序付きデータをベクターで始めたが、重複排除のためセットに変更したい場合や、キーバリュー構造が必要になりマップに変換したい場合がある。この機能は、そのような変更を効率的に行うことで、開発者の生産性を向上させる。

**機能の利用シーン**：
- ベクターをセットに変換して重複を許さないコレクションにしたい場合
- リストをベクターに変換してランダムアクセスを効率化したい場合
- ベクターやリストをマップに変換してキーバリューペアを明示したい場合
- マップのキーバリューをリストに展開してシーケンス操作を行いたい場合

**主要な処理内容**：
1. カーソル位置のzlocからコレクションノードを特定
2. 現在のコレクション型（:vector、:list、:map、:set）を判定
3. 指定された変換先コレクション型を取得
4. rewrite-cljのノード関数を使用して、子要素を保持したまま新しいコレクションノードを生成
5. 元のノードを新しいノードで置換

**関連システム・外部連携**：LSPプロトコルを通じてエディタと連携し、コードアクションまたはコマンドとして実行される。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本プロジェクトはLSPサーバーであり、UI画面は存在しない。エディタのコードアクションメニューから呼び出される。 |

## 機能種別

リファクタリング（コード変換処理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| zloc | zipper location | Yes | カーソル位置のzipperロケーション | コレクションノード上にあること |
| coll | keyword/string | Yes | 変換先コレクション型（:map, :vector, :set, :list） | 4種類のいずれか |

### 入力データソース

- エディタから送信されるLSPリクエスト（textDocument/codeAction または workspace/executeCommand）
- ドキュメントのパース結果（rewrite-clj zipper）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| range | map | 変更対象範囲（:row, :col, :end-row, :end-col） |
| loc | zipper location | 変換後の新しいコレクションノード |

### 出力先

LSPプロトコルを通じてエディタに返却され、テキスト編集として適用される。

## 処理フロー

### 処理シーケンス

```
1. コレクション型の判定
   └─ coll-tag関数でzlocのタグが:vector, :set, :list, :mapのいずれかを確認
2. 変換可能性チェック
   └─ コレクション型でない場合はnilを返却
3. 子ノードの取得
   └─ n/children関数で現在のノードの子要素を取得
4. 新コレクションノードの生成
   └─ 変換先に応じてn/map-node, n/vector-node, n/set-node, n/list-nodeを使用
5. ノードの置換
   └─ z/replace関数で元のノードを新ノードに置換
6. 結果の返却
   └─ rangeとlocを含むマップのベクターを返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{zlocはコレクション?}
    B -->|No| C[nil返却]
    B -->|Yes| D[子ノードを取得]
    D --> E{変換先コレクション型}
    E -->|:map| F[n/map-node生成]
    E -->|:vector| G[n/vector-node生成]
    E -->|:set| H[n/set-node生成]
    E -->|:list| I[n/list-node生成]
    F --> J[z/replaceで置換]
    G --> J
    H --> J
    I --> J
    J --> K[range,locを返却]
    K --> L[終了]
    C --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | コレクション型制限 | 変換元・変換先は:vector, :set, :list, :mapの4種類のみ | 常時 |
| BR-002 | 子要素保持 | 変換時に子要素の順序と内容を保持する | 常時 |
| BR-003 | 非コレクション拒否 | コレクション以外のノードでは変換不可 | 非コレクションノード選択時 |

### 計算ロジック

特になし。

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

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 暗黙的エラー | zlocがコレクションでない場合 | nil返却（操作不可として扱われる） |
| - | 暗黙的エラー | 変換先が無効な型の場合 | case文のデフォルトでエラー |

### リトライ仕様

リトライは不要。

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

該当なし（メモリ上の操作のみ）。

## パフォーマンス要件

コレクションサイズに比例した処理時間。通常のコード編集では即座に完了すること（100ms以内）。

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

特になし。ローカルファイルの操作のみ。

## 備考

- cycle-coll関数はコレクション型を順番に循環させる派生機能として提供される（map -> vector -> set -> list -> map）
- find-other-colls関数は現在のコレクション以外の変換先候補を返す

---

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

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

### 推奨読解順序

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

rewrite-cljライブラリのノード構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | coll-tag関数（39-40行目）でコレクション型の判定方法を理解 |

**読解のコツ**: rewrite-cljのz/tag関数は、zlocのノードタイプを:vector, :list, :map, :setなどのキーワードで返す。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | command.clj | `lib/src/clojure_lsp/feature/command.clj` | change-collコマンドの定義（47-48行目） |
| 2-2 | code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | change-colls-actionsでUIアクション生成（135-142行目） |

**主要処理フロー**:
1. **47-48行目**: run-commandのchange-collメソッドがr.transform/change-collを呼び出し
2. **135-142行目**: コードアクションとしてUIに表示するアクション生成

#### Step 3: 変換処理の実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | change-coll関数（46-57行目）で変換処理の実装 |

**主要処理フロー**:
- **39-40行目**: coll-tag関数でコレクション型を判定
- **42-44行目**: find-other-colls関数で他の変換先候補を取得
- **46-57行目**: change-coll関数で実際の変換処理
- **50行目**: coll-tagでコレクション判定
- **51行目**: n/childrenで子ノード取得
- **52-57行目**: case文で変換先に応じたノード生成とz/replaceによる置換

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

```
call-command (command.clj)
    │
    └─ run-command :change-coll (command.clj:47-48)
           │
           └─ r.transform/change-coll (transform.clj:46-57)
                  │
                  ├─ coll-tag (transform.clj:39-40)
                  │      └─ z/tag
                  │
                  ├─ z/node → n/children
                  │
                  └─ z/replace
                         └─ n/map-node | n/vector-node | n/set-node | n/list-node
```

### データフロー図

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

LSPリクエスト ───▶ zloc取得 ───▶ coll-tag判定 ───▶ 子ノード取得 ───▶ 新ノード生成 ───▶ TextEdit
(uri, pos, coll)                                                    │
                                                                     └─▶ エディタ反映
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | ソース | 変換処理の実装（coll-tag, change-coll, cycle-coll, find-other-colls） |
| command.clj | `lib/src/clojure_lsp/feature/command.clj` | ソース | コマンドディスパッチ（change-coll, cycle-collの呼び出し） |
| code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | ソース | コードアクションUI生成（change-colls-actions） |
| transform_test.clj | `lib/test/clojure_lsp/refactor/transform_test.clj` | テスト | find-other-colls関数のテスト |
