# 画面設計書 19-コードアクション（textDocument/codeAction）

## 概要

ソースコードに対する修正提案やリファクタリングアクションを提供するLSPメソッドの設計書である。未定義識別子のインポート追加、インターフェース実装、インポートソート、DScannerクイックフィックス等を含む。

### 本画面の処理概要

本画面は、LSP標準の `textDocument/codeAction` リクエストを処理し、選択範囲またはカーソル位置に応じたコードアクション（修正提案、リファクタリング操作）のリストを返却する処理を担当する。

**業務上の目的・背景**：コードアクションはIDEの「クイックフィックス」や「リファクタリング」機能に対応し、開発者がコード上の問題を素早く修正したり、定型的なコード変更を自動化できるようにする。特にD言語の開発において、未定義識別子に対するインポート追加やインターフェースの自動実装は頻繁に使用される機能である。

**画面へのアクセス方法**：エディタ上でコードを選択するか、診断情報（エラー・警告）が表示されている箇所にカーソルを置き、クイックフィックスメニュー（通常 Ctrl+. またはライトバルブアイコン）を開くことで、textDocument/codeActionリクエストが送信される。

**主要な操作・処理内容**：
1. クライアントからtextDocument/codeActionリクエストを受信
2. D言語ファイルのみ処理（それ以外は空リスト返却）
3. DCDExtComponentでインターフェース実装の可否を判定
4. ImporterComponentでインポートソートの可否を判定
5. DUB診断に基づくインポート追加アクションを生成
6. DScanner診断に基づくクイックフィックスアクションを生成
7. 構文ヒント診断に基づくクイックフィックスアクションを生成
8. CodeAction[]を返却

**画面遷移**：コードアクション選択後、served/sortImports（No.37）、served/implementMethods（No.38）、served/addImport（No.53）等のカスタムメソッドが呼び出される。codeAction/resolveで遅延解決される場合もある。

**権限による表示制御**：権限による表示制御は存在しない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | コードアクション (textDocument/codeAction) | 主機能 | インターフェース実装・インポート追加・未定義識別子修正等のコードアクションを提供する |
| 35 | DScanner静的解析 | 補助機能 | DScannerの診断結果に基づくクイックフィックスアクションを提供する |
| 36 | DUBビルド診断 | 補助機能 | DUBビルドのエラー診断に基づくインポート追加アクションを提供する |

## 画面種別

LSPレスポンス（コードアクションリスト）

## URL/ルーティング

LSP標準メソッド: `textDocument/codeAction`

- リクエスト: `CodeActionParams`
- レスポンス: `CodeAction[]`

解決メソッド: `codeAction/resolve`
- リクエスト: `CodeAction`
- レスポンス: `CodeAction`（解決済み）

## 入出力項目

| 項目名 | 型 | 入力/出力 | 説明 |
|--------|-----|----------|------|
| textDocument.uri | DocumentUri | 入力 | 対象ドキュメントのURI |
| range | TextRange | 入力 | 選択範囲またはカーソル位置 |
| context.diagnostics | Diagnostic[] | 入力 | 該当範囲の診断情報 |
| context.only | CodeActionKind[] | 入力 | 要求されるアクション種別のフィルタ |
| actions | CodeAction[] | 出力 | 利用可能なコードアクションの配列 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| title | テキスト | アクション名（例: "Implement base classes/interfaces", "Import std.stdio", "Sort imports"） |
| kind | カテゴリ | アクション種別（quickfix, refactor, source.organizeImports等） |
| edit | WorkspaceEdit | 適用されるテキスト編集（resolveで解決される場合もある） |
| command | Command | 実行されるコマンド |
| isPreferred | bool | 推奨アクションフラグ |
| diagnostics | Diagnostic[] | 関連する診断情報 |

## イベント仕様

### 1-インターフェース実装判定

DCDExtComponentが利用可能な場合:

1. カーソル位置から後方にコロン（:）を探索
2. DCDExtComponent.implementAllでインターフェース実装可能かチェック
3. 可能な場合、"Implement base classes/interfaces" アクションを追加
4. implementInterfaceSnippetsフラグに応じてCommand形式またはresolve形式で返却

### 2-インポートソート判定

ImporterComponentが利用可能な場合:

1. findImportCodeSlicesでインポートブロックを検索
2. カーソル位置がインポートブロック内の場合、またはsource.organizeImportsが要求されている場合
3. "Organize All Imports" アクションを追加

### 3-DUB診断に基づくアクション

IndexComponentが利用可能な場合:

1. 診断メッセージから未定義識別子を正規表現で検出
2. provideAutoImportsで一致するシンボルを検索
3. insertTextがある場合は「Change to {replacement}」アクション追加
4. モジュールインポートが候補の場合は「Import {module}」コマンドアクション追加

IndexComponentが無い場合:
1. 診断メッセージからimport文を正規表現で検出し「Import {module}」コマンドアクション追加

### 4-DScanner診断に基づくアクション

1. ImportSortednessCheckの場合、"Sort imports" コマンドアクション追加
2. diagnostic.dataにautofixesが含まれる場合、各autofixをCodeActionに変換
3. resolveContextが必要なautofixはDscannerComponent.resolveAutoFixesで解決
4. DScannerキーに基づく「Ignore {key} warnings」アクション追加（行単位/ファイル単位）

### 5-構文ヒント診断に基づくアクション

1. "workspaced.foreach-auto" の場合、"Remove 'auto' to fix syntax" アクション追加
2. 不要な `auto` キーワードを削除するTextEditを生成

### 6-codeAction/resolve

resolveCodeAction関数で遅延解決:

1. id="sortImports" の場合、sortImports関数で全インポートソートのWorkspaceEditを生成
2. id="implementMethods" の場合、implementMethods関数でメソッド実装のWorkspaceEditを生成

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | なし | なし | データベースアクセスなし（読み取り専用操作） |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 条件 |
|-------------|------|---------------|------|
| なし | なし | なし | エラーメッセージの表示は行わない |

## 例外処理

| 例外条件 | 処理内容 |
|----------|----------|
| D言語以外のファイル | 空の配列を返却 |
| インスタンスがnull | 空の配列を返却 |
| DCDExtComponentが未初期化 | インターフェース実装判定をスキップ |
| ImporterComponentが未初期化 | インポートソート判定をスキップ |
| IndexComponentが未初期化 | 自動インポート候補検索をスキップ |

## 備考

- codeActionKindsはinitialize時に全CodeActionKindのEnumMembersとして宣言される
- resolveProviderがtrueに設定されているため、codeAction/resolveで遅延解決が可能
- DCD補完コンポーネントのeager loadがcode action実行時に行われる（53-54行目）
- undefinedIdentifier, undefinedTemplate, noPropertyの3つの正規表現パターンで未定義識別子を検出する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | code_actions.d | `source/served/commands/code_actions.d` | 正規表現パターン定数（30-41行目）: importRegex, undefinedIdentifier, undefinedTemplate, noProperty, moduleRegex |

**読解のコツ**: これらの正規表現パターンは診断メッセージから未定義識別子やインポート文を抽出するために使用される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | code_actions.d | `source/served/commands/code_actions.d` | provideCodeActions関数（43-152行目）がメインエントリーポイント |

**主要処理フロー**:
1. **46-49行目**: ドキュメント取得、D言語チェック、インスタンス取得
2. **69-107行目**: DCDExtComponentによるインターフェース実装判定
3. **110-137行目**: ImporterComponentによるインポートソート判定
4. **139行目**: addDubDiagnostics呼び出し
5. **140-151行目**: 診断情報ごとのDScanner/構文ヒントアクション追加

#### Step 3: DUB診断処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | code_actions.d | `source/served/commands/code_actions.d` | addDubDiagnostics関数（191-341行目）: 未定義識別子検出とインポート追加アクション生成 |

#### Step 4: DScanner診断処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | code_actions.d | `source/served/commands/code_actions.d` | addDScannerDiagnostics関数（389-497行目）: DScanner autofixとインポートソートアクション |

#### Step 5: codeAction/resolveを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | code_actions.d | `source/served/commands/code_actions.d` | resolveCodeAction関数（154-189行目）: sortImportsとimplementMethodsの遅延解決 |

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

```
textDocument/codeAction
    |
    +-- provideCodeActions() [code_actions.d:43]
            |
            +-- DCDExtComponent.implementAll() [code_actions.d:78]
            |
            +-- ImporterComponent.findImportCodeSlices() [code_actions.d:120]
            |
            +-- addDubDiagnostics() [code_actions.d:191]
            |       +-- provideAutoImports() [complete.d:735]
            |       +-- autofixFromError() [code_actions.d:283]
            |
            +-- addDScannerDiagnostics() [code_actions.d:389]
            |       +-- DscannerComponent.resolveAutoFixes() [code_actions.d:472]
            |
            +-- addSyntaxDiagnostics() [code_actions.d:499]

codeAction/resolve
    |
    +-- resolveCodeAction() [code_actions.d:154]
            |
            +-- [sortImports] sortImports() [code_actions.d:538]
            +-- [implementMethods] implementMethods() [code_actions.d:572]
```

### データフロー図

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

CodeActionParams       +-- provideCodeActions()         +-- CodeAction[]
(uri, range,                |                                  |
 diagnostics)               +-- インターフェース実装判定         +-- title
                             +-- インポートソート判定              +-- kind
                             +-- DUB診断アクション生成            +-- edit/command
                             +-- DScanner診断アクション生成       +-- isPreferred
                             +-- 構文ヒント診断アクション生成     +-- diagnostics
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| code_actions.d | `source/served/commands/code_actions.d` | ソース | メイン実装（provideCodeActions, resolveCodeAction, sortImports, implementMethods） |
| complete.d | `source/served/commands/complete.d` | ソース | provideAutoImports関数（未定義識別子の自動インポート候補） |
| format.d | `source/served/commands/format.d` | ソース | generateDfmtArgs関数（DScanner autofix解決時に使用） |
| extension.d | `source/served/extension.d` | ソース | codeActionProviderケイパビリティ設定（296-299行目） |
| dscanner.d | `source/served/linters/dscanner.d` | ソース | DScannerDiagnosticSource定数 |
| dub.d | `source/served/linters/dub.d` | ソース | DubDiagnosticSource定数 |
