# 機能設計書 32-要素の後方移動

## 概要

本ドキュメントは、Clojure LSPの「要素の後方移動（drag-forward）」機能の設計仕様を記載する。この機能は、コレクション内の要素やキー/値ペアを後方（下方向）に移動させるリファクタリング操作を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Clojureコードを編集する際、マップのキー/値ペア、ベクタの要素、関数呼び出しの引数など、コレクション内の項目の順序を変更したい場面が頻繁に発生する。前方移動（drag-backward）と対をなす本機能により、要素を下方向に移動させることができ、開発者の生産性を向上させる。

**機能の利用シーン**：この機能は以下の場面で利用される：
- マップリテラル内のキー/値ペアの並べ替え
- letバインディング内の変数定義の順序変更
- 関数呼び出しの引数順序の調整
- case/cond式の条件節の優先度調整

**主要な処理内容**：
1. カーソル位置から移動対象の「句（clause）」を特定
2. 句の「幅（breadth）」に基づき、移動単位を決定
3. 対象句と後方の句を入れ替えるテキスト編集を生成
4. カーソル位置を移動後の句内の同じ相対位置に更新
5. エディタにテキスト編集とカーソル移動を適用

**関連システム・外部連携**：LSPプロトコルを通じてエディタと連携し、`workspace/executeCommand`リクエストで呼び出される。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | エディタ画面 | 主画面 | コードアクションメニューから「Drag forward」を選択、またはキーバインドで実行 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | string | Yes | 対象ファイルのURI | 有効なファイルURIであること |
| line | number | Yes | カーソル行（0-indexed） | 0以上の整数 |
| character | number | Yes | カーソル列（0-indexed） | 0以上の整数 |

### 入力データソース

- エディタからのLSP `workspace/executeCommand` リクエスト
- コマンド名: `drag-forward`

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| changes-by-uri | map | URI別のテキスト編集リスト |
| show-document-after-edit | map | 編集後に表示・フォーカスするドキュメントとカーソル位置 |

### 出力先

- LSPレスポンスとしてエディタに返却
- `workspace/applyEdit` でエディタにテキスト編集を適用

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ コマンドと引数（URI、行、列）を取得

2. zlocの取得
   └─ ファイルをパースしてカーソル位置のzlocを取得

3. 移動可否判定
   └─ clause-specを取得し、後方移動が可能か判定
   └─ 不可の場合はnilを返却

4. 句の特定
   └─ identify-clausesで句とパディングを特定

5. ノード交換の計算
   └─ nodes-to-dragで交換対象ノードを抽出（dir = :forward）
   └─ node-editsで編集操作を生成

6. カーソル位置の再計算
   └─ reposition-cursorで移動後のカーソル位置を算出（後方移動用）

7. 結果の返却
   └─ changes-by-uriとshow-document-after-editを含むマップを返却
```

### フローチャート

```mermaid
flowchart TD
    A[コマンド受信] --> B[zlocを取得]
    B --> C{zloc存在?}
    C -->|No| D[nil返却]
    C -->|Yes| E[clause-spec取得]
    E --> F{後方移動可能?}
    F -->|No| D
    F -->|Yes| G[句の特定]
    G --> H[交換ノードの抽出]
    H --> I[テキスト編集生成]
    I --> J[カーソル位置再計算]
    J --> K[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-32-01 | 句幅の決定 | マップは2要素、ベクタは1要素、letバインディングは2要素を1句として扱う | コレクション種別に応じて自動判定 |
| BR-32-02 | 移動境界 | 句がコレクションの末尾にある場合は後方移動不可 | 末尾要素選択時 |
| BR-32-03 | rind除外 | case/condp等の末尾固定要素は移動対象外 | 特定関数呼び出し内 |
| BR-32-04 | コメント連携 | 句の直前のコメントは句と共に移動 | コメントが句に隣接している場合 |

### 計算ロジック

**カーソル位置再計算（後方移動時）**：
```clojure
;; 後方移動時：前方句の位置 + 後方句のオフセット + 中間パディングのオフセット + カーソルオフセット
new-cursor = nodes-start(earlier-clause)
           + nodes-offset(later-clause)
           + nodes-offset(interstitial)
           + cursor-offset
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 操作不可 | 末尾要素で後方移動を試行 | nil返却（無視） |
| - | 操作不可 | コレクション外で実行 | nil返却（無視） |

### リトライ仕様

リトライは行わない。

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

トランザクション管理は不要。

## パフォーマンス要件

- 応答時間: 100ms以内

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

- ファイルシステムへの書き込みは行わない

## 備考

- 本機能は以前「move-coll-entry-down」という名前で提供されていたが、「drag-forward」に改名された
- コマンドエイリアス `move-coll-entry-down` は後方互換性のため維持されている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | clauses.clj | `lib/src/clojure_lsp/feature/clauses.clj` | clause-spec の構造を理解 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | command.clj | `lib/src/clojure_lsp/feature/command.clj` | コマンドディスパッチ |

**主要処理フロー**:
- **71-72行目**: `:drag-forward` コマンドハンドラ

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | drag.clj | `lib/src/clojure_lsp/feature/drag.clj` | 後方移動のコアロジック |

**主要処理フロー**:
- **170行目**: `can-drag-forward?` - 後方移動可否判定
- **178行目**: `drag-forward` - 公開API
- **67-69行目**: `reposition-cursor` - 後方移動時のカーソル計算（:forwardケース）

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

```
workspace/executeCommand (LSP)
    │
    └─ command/call-command
           │
           └─ run-command :drag-forward
                  │
                  └─ f.drag/drag-forward
                         │
                         ├─ plan (dir = :forward)
                         │
                         ├─ identify-clauses
                         │
                         ├─ nodes-to-drag (dir = :forward)
                         │
                         └─ drag-clause (dir = :forward)
```

### データフロー図

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

URI, row, col      ──▶  drag-forward               ──▶  {:changes-by-uri, :show-document-after-edit}
                         (dir = :forward)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| drag.clj | `lib/src/clojure_lsp/feature/drag.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` | ソース | コードアクション生成 |
| drag_test.clj | `lib/test/clojure_lsp/feature/drag_test.clj` | テスト | 要素移動のテスト |
