# 画面設計書 28-空白削除

## 概要

本ドキュメントは、Lua Language Serverにおける「空白削除」機能の画面設計書です。LSPコマンド `lua.removeSpace` に対応し、ドキュメント内の末尾空白を一括削除します。

### 本画面の処理概要

空白削除機能は、Luaソースコード内の各行末に存在する不要な空白文字（スペース、タブ）を検出し、一括で削除するコマンドです。

**業務上の目的・背景**：末尾の空白文字は、コードの見た目には影響しませんが、バージョン管理システムで不要な差分を生じさせたり、コーディング規約に違反する場合があります。この機能により、開発者は手動で空白を削除する手間を省き、クリーンなコードを維持できます。特にチーム開発では、空白文字の扱いが統一されていないと、コードレビューやマージ時に問題が発生することがあります。

**画面へのアクセス方法**：この機能は、以下の方法で呼び出されます：
- コードアクション（クイックフィックス）メニューから選択
- コマンドパレットから `lua.removeSpace` を実行
- 診断結果からのクイックフィックスとして実行

**主要な操作・処理内容**：
1. コマンド `lua.removeSpace` がトリガーされる
2. 対象ファイルの各行を走査
3. 行末の空白文字（スペース、タブ）を検出
4. 文字列リテラル内、コメント内の空白は除外
5. 検出された空白を削除するTextEdit配列を構築
6. `workspace/applyEdit` リクエストでエディタに適用

**画面遷移**：独立したコマンドとして動作し、特定の画面遷移はありません。処理結果は現在のエディタに直接反映されます。

**権限による表示制御**：特別な権限制御はありません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | スペース除去 (lua.removeSpace) | 主機能 | 末尾空白を削除するコマンド処理 |

## 画面種別

LSPコマンド

## URL/ルーティング

LSPコマンド: `lua.removeSpace`
LSPメソッド: `workspace/executeCommand`

## 入出力項目

### 入力パラメータ

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| uri | uri | はい | 対象ドキュメントのURI |

### 出力パラメータ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| - | - | 戻り値なし（workspace/applyEditで変更を適用） |

## 表示項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| - | - | エディタ上で空白が削除された結果が表示される |

## イベント仕様

### 1-空白削除コマンド実行

1. ユーザーが `lua.removeSpace` コマンドを実行
2. `workspace/executeCommand` ハンドラが呼び出される
3. `core/command/removeSpace.lua` が実行される
4. ファイルの各行を走査し、末尾空白を検出
5. 文字列リテラル・コメント内の空白は除外
6. TextEdit配列を構築
7. `workspace/applyEdit` リクエストでエディタに適用

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 空白削除コマンド実行 | - | - | データベース操作なし（ファイル編集のみ） |

## メッセージ仕様

| メッセージID | 種別 | 表示内容 | 発生条件 |
|-------------|------|----------|----------|
| COMMAND_REMOVE_SPACE | ラベル | "Remove trailing spaces" | 編集適用時のラベル |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| ファイルが取得できない | 処理を終了（何もしない） |
| ファイル状態が取得できない | 処理を終了（何もしない） |
| 削除対象の空白がない | 処理を終了（何もしない） |

## 備考

- 文字列リテラル内の空白は削除しない（`guide.isInString` でチェック）
- コメント内の空白は削除しない（`guide.isInComment` でチェック）
- 各行の最初の空白以外の文字から末尾までの空白を検出
- `workspace/applyEdit` でエディタに変更を適用

---

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

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

### 推奨読解順序

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

TextEdit型とworkspace/applyEdit構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | removeSpace.lua | `script/core/command/removeSpace.lua` | textEdit構造（40-43行目）を確認 |

**読解のコツ**: textEditはrangeとnewText（空文字列）のペアで、削除する範囲を指定します。

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

コマンドハンドラがどのように呼び出されるかを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | provider.lua | `script/provider/provider.lua` | `workspace/executeCommand` ハンドラ（977-1021行目）を確認 |

**主要処理フロー**:
1. **977行目**: `m.register 'workspace/executeCommand'` でハンドラを登録
2. **992行目**: コマンド名を取得
3. **993-995行目**: `lua.removeSpace` の場合、removeSpace.luaを実行

#### Step 3: コア処理を理解する

実際の空白削除処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | removeSpace.lua | `script/core/command/removeSpace.lua` | 空白削除処理（8-60行目）を確認 |

**主要処理フロー**:
- **8-14行目**: ファイルテキストと状態の取得、エラーチェック
- **16-18行目**: 各行のループ開始
- **19-25行目**: 行末の空白文字を検出
- **26-30行目**: 文字列・コメント内かチェック
- **31-38行目**: 最初の空白位置を特定
- **40-43行目**: TextEditを構築
- **52-59行目**: `workspace/applyEdit` で変更を適用

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

```
workspace/executeCommand (provider.lua:977-1021)
    │
    └─ 'lua.removeSpace' (993-995行目)
           │
           └─ core/command/removeSpace.lua (8-60行目)
                  │
                  ├─ files.getText(uri) - テキスト取得
                  │
                  ├─ files.getState(uri) - ファイル状態取得
                  │
                  ├─ 各行ループ (18-46行目)
                  │      │
                  │      ├─ 行末空白検出
                  │      │
                  │      ├─ guide.isInString() - 文字列内チェック
                  │      │
                  │      ├─ guide.isInComment() - コメント内チェック
                  │      │
                  │      └─ textEdit構築
                  │
                  └─ proto.awaitRequest('workspace/applyEdit', ...)
```

### データフロー図

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

{                              1. ファイル取得                  workspace/applyEdit {
  uri: 'file:///path/to/file'  2. 各行走査                        label: 'Remove trailing spaces',
}                              3. 行末空白検出                    edit: {
                                  ├─ 末尾から空白を探索              changes: {
                                  └─ 非空白文字で停止                  [uri]: [
                               4. 除外チェック                          { range: ..., newText: '' },
                                  ├─ 文字列内？                         { range: ..., newText: '' }
                                  └─ コメント内？                      ]
                               5. TextEdit構築                       }
                               6. applyEdit送信                   }
                                                                }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| provider.lua | `script/provider/provider.lua` | ソース | LSPコマンドハンドラの登録・処理 |
| removeSpace.lua | `script/core/command/removeSpace.lua` | ソース | 空白削除処理のコアロジック |
| files.lua | `script/files.lua` | ソース | ファイル状態・テキストの管理 |
| guide.lua | `script/parser/guide.lua` | ソース | AST操作ユーティリティ（isInString, isInComment） |
| proto.lua | `script/proto/proto.lua` | ソース | LSPプロトコル通信 |
| converter.lua | `script/proto/converter.lua` | ソース | LSPプロトコル型変換 |
| language.lua | `script/language.lua` | ソース | メッセージ定義（COMMAND_REMOVE_SPACE） |
