# 機能設計書 30-句の並べ替え

## 概要

本ドキュメントは、clojure-lspの「句の並べ替え」機能（sort-clausesコマンド）の設計仕様を定義する。この機能は、マップ、ベクター、セット、リストの要素をアルファベット順にソートするリファクタリング機能を提供する。

### 本機能の処理概要

句の並べ替え機能は、Clojureのコレクション（マップ、ベクター、セット、リスト）内の要素をアルファベット順にソートする。マップの場合はキーでソートされ、他のコレクションの場合は各要素の文字列表現でソートされる。バインディングを確立するコンテキスト（letのバインディングベクターなど）ではソート対象外となる。

**業務上の目的・背景**：コード内のコレクション要素が整理されていないと、特定の要素を見つけるのが難しくなる。この機能により、マップのキーやベクターの要素をアルファベット順に並べ替えることで、コードの可読性と保守性を向上させることができる。

**機能の利用シーン**：
- マップのキーをアルファベット順に並べ替えたい場合
- ベクターやセットの要素を整理したい場合
- 設定マップや定数定義を見やすくしたい場合
- コードレビューで整理された形式が求められた場合

**主要な処理内容**：
1. カーソル位置のコレクションを特定
2. コレクションの種類（マップ、ベクター、セット、リスト）を判定
3. ソート対象外のコンテキスト（バインディング等）をチェック
4. 要素を「句」として識別（マップはキー-値ペア、他は単一要素）
5. 句の文字列表現でソート
6. パディング（空白、コメント）を適切に配置
7. ソート結果を返却

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

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

## 関連画面

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

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| zloc | zipper location | Yes | カーソル位置のzipperロケーション | コレクション内にあること |
| uri | string | Yes | 対象ファイルのURI | 有効なURI形式 |
| db | database | Yes | LSPデータベース | - |

### 入力データソース

- エディタから送信されるLSPリクエスト
- ドキュメントのパース結果（rewrite-clj zipper）
- clj-kondo解析データ（バインディングコンテキストの判定）

## 出力仕様

### 出力データ

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

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. コレクションの特定
   └─ clause-spec関数でコレクションと句の仕様を取得
2. ソート可能性チェック
   └─ :bindingや:formsコンテキストでないことを確認
3. 句の識別
   └─ identify関数で要素とパディングを分離
4. 句のソート
   └─ 各句の最初のsexpr-ableノードの文字列でソート
5. パディングの再配置
   └─ 元のパディングをソート後の句に割り当て
6. 結果の構築
   └─ ソート後のノード列を構築
7. 結果の返却
   └─ rangeとlocを含むマップのベクターを返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[clause-spec取得]
    B --> C{コレクション?}
    C -->|No| D[nil返却]
    C -->|Yes| E{バインディング?}
    E -->|Yes| D
    E -->|No| F[句とパディングを識別]
    F --> G[句を文字列でソート]
    G --> H[パディングを再配置]
    H --> I[ノード列を構築]
    I --> J[結果返却]
    J --> K[終了]
    D --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | マップソート | マップはキー-値ペアを句としてキーでソート | :mapコンテキスト |
| BR-002 | ベクターソート | ベクターは各要素を句としてソート | :vectorコンテキスト |
| BR-003 | セットソート | セットは各要素を句としてソート | :setコンテキスト |
| BR-004 | リストソート | リストは各要素を句としてソート | :listコンテキスト |
| BR-005 | バインディング除外 | letなどのバインディングベクターはソート対象外 | :bindingコンテキスト |
| BR-006 | :forms除外 | トップレベルのforms（ファイル全体）はソート対象外 | :formsコンテキスト |
| BR-007 | パディング保持 | 句間の空白とコメントを保持して再配置 | 常時 |
| BR-008 | 末尾コメント処理 | 末尾コメントの場合は改行を追加 | 末尾がコメントの場合 |

### 計算ロジック

特になし。

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

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

本機能はデータベース操作を行わない。clj-kondo解析データの読み取りのみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 暗黙的エラー | コレクションでない場合 | nil返却 |
| - | 暗黙的エラー | バインディングコンテキストの場合 | nil返却 |

### リトライ仕様

リトライは不要。

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

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

## パフォーマンス要件

即座に完了すること（100ms以内）。

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

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

## 備考

- clauses.cljモジュールで句の識別と操作のロジックを共通化
- breadthパラメータで句の幅を指定（マップは2、他は1）
- sort-mapは非推奨となり、sort-clausesが推奨される

---

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

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

### 推奨読解順序

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

句（clause）の概念と句仕様（clause-spec）を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | clauses.clj | `lib/src/clojure_lsp/feature/clauses.clj` | clause-spec関数（351-368行目）で句の仕様 |
| 1-2 | clauses.clj | `lib/src/clojure_lsp/feature/clauses.clj` | identify関数（171-198行目）で句の識別 |

**読解のコツ**: clause-specは:context、:breadth、:rind、:pulpを含むマップを返す。breadthは句の幅（マップは2、他は1）。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | command.clj | `lib/src/clojure_lsp/feature/command.clj` | sort-clausesコマンドの定義（128-129行目） |
| 2-2 | code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | sort-clauses-actionでUIアクション生成（276-287行目） |

**主要処理フロー**:
1. **128-129行目**: run-commandのsort-clausesメソッドがf.sort-clauses/sort-clausesを呼び出し

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sort_clauses.clj | `lib/src/clojure_lsp/feature/sort_clauses.clj` | clause-spec関数（8-16行目）で句仕様取得 |
| 3-2 | sort_clauses.clj | `lib/src/clojure_lsp/feature/sort_clauses.clj` | can-sort?（18-19行目）でソート可能性判定 |
| 3-3 | sort_clauses.clj | `lib/src/clojure_lsp/feature/sort_clauses.clj` | sort-clauses（21-42行目）でメイン処理 |

**主要処理フロー**:
- **8-16行目**: clause-spec関数でバインディングコンテキストを除外
- **23行目**: f.clauses/identifyで句とパディングを識別
- **29-33行目**: sort-byで句を文字列でソート
- **35行目**: medley/interleave-allでパディングを再配置
- **37-40行目**: 末尾コメントの処理
- **41-42行目**: 結果の返却

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

```
call-command (command.clj)
    │
    └─ run-command :sort-clauses (command.clj:128-129)
           │
           └─ f.sort-clauses/sort-clauses (sort_clauses.clj:21-42)
                  │
                  ├─ clause-spec (sort_clauses.clj:8-16)
                  │      └─ f.clauses/clause-spec (clauses.clj:351-368)
                  │
                  ├─ f.clauses/identify (clauses.clj:171-198)
                  │
                  ├─ sort-by (句のソート)
                  │
                  ├─ medley/interleave-all (パディング配置)
                  │
                  └─ f.clauses/loc-of-nodes (clauses.clj:200-201)
```

### データフロー図

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

LSPリクエスト ───▶ zloc取得 ───▶ clause-spec ───▶ identify ───▶ sort-by ───▶ 再構築 ───▶ TextEdit
(uri, pos)                              │            │
                                        └─ 句仕様    └─ 句+パディング
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sort_clauses.clj | `lib/src/clojure_lsp/feature/sort_clauses.clj` | ソース | 句の並べ替え処理の実装 |
| clauses.clj | `lib/src/clojure_lsp/feature/clauses.clj` | ソース | 句の識別と操作の共通ロジック |
| command.clj | `lib/src/clojure_lsp/feature/command.clj` | ソース | コマンドディスパッチ |
| code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | ソース | コードアクションUI生成 |
| sort_clauses_test.clj | `lib/test/clojure_lsp/feature/sort_clauses_test.clj` | テスト | 句の並べ替えのテスト |
