# 機能設計書 61-コード折りたたみ

## 概要

本ドキュメントは、Clojure LSPにおけるコード折りたたみ機能（textDocument/foldingRange）の設計を定義する。この機能は、エディタにおいて関数定義などのコードブロックを折りたたみ可能な範囲として提供し、大規模なコードベースの可読性向上を支援する。

### 本機能の処理概要

**業務上の目的・背景**：Clojureコードは、特にマクロや複雑なデータ構造を含む場合、長大になることがある。コード折りたたみ機能は、開発者が現在注目していない部分を一時的に非表示にすることで、コードの全体構造を把握しやすくし、開発効率を向上させる。LSPプロトコルの textDocument/foldingRange リクエストに対応することで、VSCode、Emacs、Vim等の主要エディタでこの機能を利用可能にする。

**機能の利用シーン**：開発者がソースファイルを開いた際、エディタは自動的にこの機能を呼び出し、折りたたみ可能な領域をユーザーに提示する。ユーザーは関数定義、名前空間宣言、大きなマップやベクターなどを折りたたんで、関心のある部分に集中できる。

**主要な処理内容**：
1. URIで指定されたファイルの解析データから要素定義を取得
2. 各要素定義の開始位置と終了位置を抽出
3. LSPプロトコルの FoldingRange 形式に変換して返却

**関連システム・外部連携**：LSPクライアント（エディタ）との通信はJSON-RPC経由で行われる。clj-kondoによる静的解析結果を利用して折りたたみ範囲を決定する。

**権限による制御**：特に権限制御は存在しない。全ユーザーが同等にこの機能を利用できる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 該当なし | 該当なし | 該当なし | 本機能はLSPプロトコルを通じてエディタから呼び出される |

## 機能種別

データ取得処理 / LSPレスポンス生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | string | Yes | 対象ファイルのURI | 有効なファイルURIであること |

### 入力データソース

- LSPクライアントからの textDocument/foldingRange リクエスト
- 内部DB（解析済みの要素定義情報）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| start-line | integer | 折りたたみ範囲の開始行（0-indexed） |
| start-character | integer | 折りたたみ範囲の開始列（0-indexed） |
| end-line | integer | 折りたたみ範囲の終了行（0-indexed） |
| end-character | integer | 折りたたみ範囲の終了列（0-indexed） |
| kind | keyword | 折りたたみの種類（:region） |

### 出力先

LSPクライアント（JSON-RPC レスポンス）

## 処理フロー

### 処理シーケンス

```
1. LSPクライアントから textDocument/foldingRange リクエストを受信
   └─ handlers.clj の folding-range ハンドラが呼び出される
2. 対象ファイルURIから解析データを取得
   └─ queries.clj の find-element-definitions を呼び出し
3. 各要素定義から折りたたみ範囲を生成
   └─ 行番号を0-indexedに変換し、FoldingRange形式に整形
4. レスポンスをLSPクライアントに返却
```

### フローチャート

```mermaid
flowchart TD
    A[textDocument/foldingRange リクエスト受信] --> B[folding-range ハンドラ呼び出し]
    B --> C[find-element-definitions で定義一覧取得]
    C --> D{各要素に位置情報があるか}
    D -->|Yes| E[FoldingRange形式に変換]
    D -->|No| F[スキップ]
    E --> G[結果リストに追加]
    F --> G
    G --> H[全要素処理完了]
    H --> I[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 位置情報必須 | row, col, end-row, end-col が全て存在する場合のみ折りたたみ範囲を生成 | 常時 |
| BR-02 | 0-indexed変換 | clj-kondoの1-indexed行番号をLSPの0-indexedに変換 | 常時 |
| BR-03 | 種類固定 | 折りたたみの種類は常に :region を使用 | 常時 |

### 計算ロジック

- start-line = row - 1
- start-character = col - 1
- end-line = end-row - 1
- end-character = end-col - 1

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 要素定義取得 | db[:analysis][uri] | SELECT | 指定URIの解析データから要素定義を取得 |

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

#### db[:analysis][uri]

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | namespace-definitions, var-definitions, keyword-definitions, var-usages | uri = 指定URI | find-element-definitions関数経由 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 空リスト | 解析データが存在しない場合 | 空の配列を返却 |

### リトライ仕様

リトライは不要。解析データが存在しない場合は空配列を返す。

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

読み取り専用処理のため、トランザクション管理は不要。

## パフォーマンス要件

- 通常のClojureファイル（数百行）に対して数十ミリ秒以内で応答

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

- 特になし（ローカルファイルの読み取り専用）

## 備考

- LSPプロトコル仕様: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_foldingRange

---

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

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

### 推奨読解順序

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

解析データの構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | queries.clj | `lib/src/clojure_lsp/queries.clj` | find-element-definitions関数（736-742行目）で返却されるデータ構造 |

**読解のコツ**: Clojure LSPは clj-kondo の解析結果をベースにしており、各要素は :row, :col, :end-row, :end-col などの位置情報を持つマップとして表現される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | textDocument/foldingRange リクエストハンドラ（429-434行目） |
| 2-2 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | folding-range ハンドラ関数（509-514行目） |

**主要処理フロー**:
1. **429-434行目（server.clj）**: LSPリクエストを受信し、ハンドラに委譲
2. **509-514行目（handlers.clj）**: DBからデータを取得し、f.folding/folding-range を呼び出し

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | folding.clj | `lib/src/clojure_lsp/feature/folding.clj` | 折りたたみ範囲生成のコアロジック（全16行） |

**主要処理フロー**:
- **7-15行目**: folding-range 関数
  - q/find-element-definitions でファイル内の全要素定義を取得
  - keep で位置情報が完全な要素のみをフィルタリング
  - 各要素を FoldingRange 形式のマップに変換

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

```
server.clj (textDocument/foldingRange リクエスト受信)
    │
    └─ handlers.clj::folding-range
           │
           └─ feature/folding.clj::folding-range
                  │
                  └─ queries.clj::find-element-definitions
                         │
                         ├─ find-namespace-definition-by-uri
                         ├─ find-var-definitions
                         ├─ find-keyword-definitions
                         └─ find-defmethods
```

### データフロー図

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

URI (file path)  ───▶  folding.clj::folding-range
                              │
                              ▼
                       queries.clj::find-element-definitions
                              │
                              ▼
                       要素定義リスト
                       [{:row 1 :col 1 :end-row 5 :end-col 2} ...]
                              │
                              ▼
                       位置情報の0-indexed変換
                              │
                              ▼
                       FoldingRange リスト  ───▶  LSPクライアント
                       [{:start-line 0
                         :start-character 0
                         :end-line 4
                         :end-character 1
                         :kind :region} ...]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| folding.clj | `lib/src/clojure_lsp/feature/folding.clj` | ソース | 折りたたみ範囲生成のコアロジック |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | LSPリクエストハンドラ |
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSPサーバーエントリーポイント |
| queries.clj | `lib/src/clojure_lsp/queries.clj` | ソース | 解析データクエリ関数群 |
