# 機能設計書 15-スレッド全展開

## 概要

本ドキュメントは、clojure-lspのスレッド全展開（unwind-all）機能の設計を記述する。この機能はスレッドマクロ（`->`, `->>`, `some->`, `some->>`）を完全に展開し、元のネストされた形式に戻すリファクタリング機能である。

### 本機能の処理概要

スレッド全展開機能は、スレッドマクロを使用した式を完全に元のネストされた形式に戻す。

**業務上の目的・背景**：スレッドマクロは可読性を向上させるが、デバッグ時やコード構造の変更時に元の形式に戻したいことがある。本機能はunwind-threadを繰り返し適用することで、スレッドマクロを完全に展開する。

**機能の利用シーン**：
- スレッドマクロを完全に取り消したい場合
- 別のマクロやフォームに書き換える前処理
- デバッグのために中間結果を確認したい場合
- コード構造を根本的に変更するリファクタリング時

**主要な処理内容**：
1. unwind-threadを呼び出して一段階展開
2. 展開結果に対して再度unwind-threadを呼び出し
3. 展開できなくなるまで繰り返し
4. 最終結果を返却

**関連システム・外部連携**：rewrite-cljライブラリを使用してASTを操作する。

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

## 関連画面

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

## 機能種別

リファクタリング / コード変換

## 入力仕様

### 入力パラメータ

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

### 入力データソース

- LSPクライアントからのtextDocument/codeActionリクエスト
- LSPクライアントからのworkspace/executeCommandリクエスト（unwind-allコマンド）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| range | Range | 編集対象の範囲（元のスレッドマクロ全体） |
| newText | string | 完全に展開後のテキスト |

### 出力先

- LSPクライアントへWorkspaceEditとして返却

## 処理フロー

### 処理シーケンス

```
1. 初回のunwind-thread呼び出し
   └─ 一段階展開を試行

2. ループ処理
   └─ 展開結果のlocに対してunwind-threadを再帰呼び出し

3. 終了条件判定
   └─ unwind-threadがnilを返すまで繰り返し

4. 最終結果の返却
   └─ 最後に成功した展開結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[unwind-thread初回呼び出し]
    B --> C{展開成功?}
    C -->|No| D[nil返却]
    C -->|Yes| E[結果を保存]
    E --> F[展開結果のlocでunwind-thread]
    F --> G{展開成功?}
    G -->|Yes| E
    G -->|No| H[保存した結果を返却]
    H --> I[終了]
    D --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 完全展開 | スレッドマクロが完全に消えるまで展開 | unwind-threadがnilを返すまで |
| BR-02 | 最終結果保持 | 展開できなくなる直前の結果を返却 | ループ終了時 |
| BR-03 | 初回失敗時 | 最初のunwind-threadが失敗した場合はnilを返却 | current = nil |

### 計算ロジック

- ループはloop/recurパターンで実装
- 各反復で前回の結果を保持し、新しい結果がnilならば前回の結果を返却

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

本機能はデータベースを使用しない。純粋なAST操作のみ。

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | nil返却 | スレッドマクロが見つからない | nilを返却（何もしない） |

### リトライ仕様

特になし。同期的に実行。

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

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

## パフォーマンス要件

- 繰り返し処理だが、通常のスレッド深度（~10ステップ）では即時完了
- loop/recurパターンで実装されているためスタックオーバーフローなし

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

- ファイルシステムへの直接書き込みは行わない（LSP経由でクライアントに委譲）

## 備考

- 変換例（完全展開）:
  - 入力:
    ```clojure
    (-> a b (c) d)
    ```
  - 出力:
    ```clojure
    (d (c (b a)))
    ```
- unwind-thread（No.14）を内部的に繰り返し呼び出す

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | command.clj | `lib/src/clojure_lsp/feature/command.clj` | run-command :unwind-all（119-120行目） |
| 1-2 | transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | unwind-all関数（201-207行目） |

**主要処理フロー**:
1. **201行目**: `unwind-all`関数定義
2. **203行目**: 初回の`unwind-thread`呼び出し
3. **204-206行目**: loop/recurで繰り返し展開

#### Step 2: ループ処理を理解する

繰り返し展開のロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | unwind-all関数のloop部分（203-207行目） |

**主要処理フロー**:
- **203行目**: `current`に初回結果、`result`にnilを設定
- **205行目**: `current`がnilでなければ再帰
- **206行目**: `unwind-thread`を`:loc`に対して呼び出し

#### Step 3: unwind-thread関数との関係を理解する

unwind-allがunwind-threadを内部的に使用していることを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | unwind-thread関数（173-199行目） |

**読解のコツ**: unwind-allは単にunwind-threadを繰り返し呼び出すラッパー関数。unwind-threadが実際の展開ロジックを担当。

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

```
handlers/execute-command
    │
    └─ f.command/call-command
           │
           └─ run-command :unwind-all
                  │
                  └─ r.transform/unwind-all
                         │
                         └─ loop
                                │
                                ├─ unwind-thread (1回目)
                                │      └─ can-unwind-thread?
                                │      └─ z/subedit-> ...
                                │
                                ├─ unwind-thread (2回目)
                                │      └─ ...
                                │
                                └─ ... (nilになるまで繰り返し)
```

### データフロー図

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

zloc ─────────────────┬─> unwind-thread (1回目) ──> result1
                      │
                      └─> loop
                              │
                              ├─> result1.loc → unwind-thread → result2
                              ├─> result2.loc → unwind-thread → result3
                              └─> ...
                                      │
                                      └─> resultN (最終)
                                              │
                                              └─────────────> [{:range :loc}]
                                                                   │
                                                                   └─> WorkspaceEdit
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | ソース | 展開処理のメインロジック |
| command.clj | `lib/src/clojure_lsp/feature/command.clj` | ソース | コマンドディスパッチャー |
| code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | ソース | コードアクション提供 |
| transform_test.clj | `lib/test/clojure_lsp/refactor/transform_test.clj` | テスト | 単体テスト |
