# 画面設計書 24-範囲フォーマット（textDocument/rangeFormatting）

## 概要

本ドキュメントは、serve-d LSPサーバーにおける `textDocument/rangeFormatting` リクエストの処理仕様を定義する画面設計書である。ユーザーが選択した範囲のみに対してdfmtによるフォーマットを実行する機能を記述する。

### 本画面の処理概要

**業務上の目的・背景**：ドキュメント全体ではなく、ユーザーが選択した特定の範囲のみをフォーマットしたい場合に使用する機能である。既存のコードスタイルを維持しながら、新たに記述した部分のみをフォーマットするなど、部分的なスタイル適用が可能となる。実装上は、ドキュメント全体をフォーマットした結果から選択範囲に交差するTextEditのみをフィルタリングして返却する方式を採用している。

**画面へのアクセス方法**：エディタ上でフォーマット対象のテキスト範囲を選択し、「選択範囲のフォーマット」コマンドを実行する。エディタが `textDocument/rangeFormatting` リクエストをLSPサーバーに送信する。

**主要な操作・処理内容**：
1. 内部で `provideFormatting`（ドキュメント全体フォーマット）を呼び出す
2. 返却されたTextEdit配列から、指定範囲と交差するものだけをフィルタリングして返却する

**画面遷移**：本機能は単独の操作であり、他の画面への遷移は発生しない。

**権限による表示制御**：権限による表示制御は存在しない。ドキュメントフォーマット（No.23）と同様の設定制御が適用される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 30 | 範囲フォーマット (textDocument/rangeFormatting) | 主機能 | 選択範囲のみに対してdfmtによるコードフォーマットを実行する |

## 画面種別

編集操作（LSPプロトコルレスポンス）

## URL/ルーティング

- LSPメソッド: `textDocument/rangeFormatting`

## 入出力項目

| 項目名 | 型 | 入力/出力 | 必須 | 説明 |
|--------|-----|----------|------|------|
| params.textDocument | TextDocumentIdentifier | 入力 | Yes | 対象ドキュメントの識別子 |
| params.range | TextRange | 入力 | Yes | フォーマット対象の範囲 |
| params.options | FormattingOptions | 入力 | Yes | フォーマットオプション（tabSize, insertSpaces等） |
| TextEdit[] | TextEdit[] | 出力 | - | 指定範囲に交差するフォーマット差分テキスト編集の配列 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|---------|------|
| フォーマット結果 | テキスト変更 | 選択範囲のみがフォーマットされた結果としてテキスト編集が適用される |

## イベント仕様

### 1-範囲フォーマット実行

ユーザーが「選択範囲のフォーマット」を実行した際の処理フロー。

1. `DocumentRangeFormattingParams` から `DocumentFormattingParams` を構築する（textDocumentとoptionsを引き継ぎ）
2. `provideFormatting` を呼び出してドキュメント全体のフォーマットを実行する（No.23のドキュメントフォーマットと同一処理）
3. 返却された `TextEdit[]` に対し、`filter` で `params.range` と交差するTextEditのみを抽出する
4. フィルタリング結果を配列化して返却する

交差判定は `edit.range.intersects(params.range)` で行われ、TextEditの変更範囲が指定された選択範囲と重なっているかどうかを確認する。

## データベース更新仕様

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

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

## メッセージ仕様

本機能固有のメッセージはない。内部で呼び出される `provideFormatting` のメッセージ仕様に準ずる。

## 例外処理

| 条件 | 挙動 |
|------|------|
| フォーマット無効設定 | `provideFormatting` が空配列を返却し、フィルタ結果も空配列 |
| サポートされていない言語 | `provideFormatting` が空配列を返却 |
| 指定範囲に交差するTextEditがない | 空の `TextEdit[]` を返却 |

## 備考

- 実装はドキュメント全体をフォーマットした後にフィルタリングする方式であるため、ドキュメント全体のフォーマット処理が必ず実行される
- dfmtは範囲指定フォーマットをネイティブにサポートしていないため、この方式が採用されている
- フィルタリングは交差判定（intersects）で行われるため、選択範囲の境界を跨ぐTextEditも含まれる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protocol.d | `source/served/lsp/protocol.d` | `DocumentRangeFormattingParams`, `TextRange`, `TextEdit` の定義を確認 |

**読解のコツ**: `DocumentRangeFormattingParams` は `DocumentFormattingParams` に `range` フィールドを追加した構造体である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | format.d | `source/served/commands/format.d` | `provideRangeFormatting` 関数（行183-194）がLSPリクエストハンドラ |

**主要処理フロー**:
1. **行183**: `@protocolMethod("textDocument/rangeFormatting")` でバインド
2. **行189-190**: `provideFormatting` をパラメータ変換して呼び出し
3. **行191-193**: `filter` で交差するTextEditのみを抽出

#### Step 3: ドキュメント全体フォーマットを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | format.d | `source/served/commands/format.d` | `provideFormatting` 関数（行130-171）- No.23で詳述 |

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

```
textDocument/rangeFormatting リクエスト
    |
    +-- provideRangeFormatting (format.d:183)
           |
           +-- provideFormatting (format.d:130)
           |      |
           |      +-- [D言語] DfmtComponent.format
           |      +-- [SDL] sdlfmt.format
           |      +-- diff (format.d:196)
           |
           +-- filter (TextRange.intersects)
```

### データフロー図

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

DocumentRangeFormattingParams ----> provideRangeFormatting -------> TextEdit[]
  textDocument                        |                               (フィルタ済)
  range (選択範囲)                     +-- provideFormatting
  options                             |      --> TextEdit[] (全体)
                                      +-- filter(intersects)
                                             --> TextEdit[] (範囲内のみ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| format.d | `source/served/commands/format.d` | ソース | フォーマット主処理（全体・範囲共通） |
| types.d | `source/served/types.d` | ソース | 共通型定義 |
| protocol.d | `source/served/lsp/protocol.d` | ソース | LSPプロトコル型定義（TextRange.intersects含む） |
