# 機能設計書 21-コード修正 (CodeFix)

## 概要

本ドキュメントは、Roslynにおける「コード修正 (CodeFix)」機能の設計を記述するものである。CodeFix機能は、コンパイラエラーや警告に対する自動修正候補を提供し、開発者の生産性向上を支援する。

### 本機能の処理概要

コード修正機能は、コンパイラが検出したエラーや警告、およびアナライザーが報告した診断に対して、自動的に修正候補を提供する機能である。Visual StudioやVS Codeなどのエディタ上でライトバルブアイコンとして表示され、開発者はワンクリックで問題を修正できる。

**業務上の目的・背景**：開発者がコードを書く際、コンパイルエラーや警告が発生することは日常的である。これらの問題を手動で修正するには時間がかかり、特に初心者開発者にとっては正しい修正方法が分からないことも多い。CodeFix機能は、これらの問題に対する解決策を自動的に提案することで、開発効率を大幅に向上させ、コード品質の維持に貢献する。

**機能の利用シーン**：
1. コンパイルエラーが発生した際に、エディタ上でエラー箇所にカーソルを合わせると表示されるライトバルブをクリックして修正を適用する
2. Ctrl+. (クイックアクション)ショートカットで修正候補を表示する
3. 警告を修正してコード品質を向上させる場合
4. アナライザーが検出した問題を一括修正する場合

**主要な処理内容**：
1. 診断(Diagnostic)の収集と分類
2. 該当する診断に対応するCodeFixProviderの特定
3. CodeFixProviderからの修正候補(CodeAction)の取得
4. Fix All機能による一括修正の実行
5. 修正適用後のコード整形

**関連システム・外部連携**：
- 診断エンジン(DiagnosticAnalyzerService)との連携
- Copilot連携による追加診断の取得
- エディタ(Visual Studio, VS Code)のLightBulb機能との統合

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | ライトバルブメニュー | 主画面 | CodeFix候補の一覧表示と選択 |
| 20 | プレビューペイン | 補助画面 | コード変更のプレビュー表示 |

## 機能種別

コード変換処理 / 自動修正

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | TextDocument | Yes | 対象のドキュメント | 有効なドキュメントであること |
| range | TextSpan | Yes | 修正対象の範囲 | 有効なテキスト範囲であること |
| priority | CodeActionRequestPriority | No | 優先度(High/Default/Low/Lowest) | 列挙値であること |
| cancellationToken | CancellationToken | Yes | キャンセルトークン | - |

### 入力データソース

- 診断サービス(IDiagnosticAnalyzerService)から取得した診断情報
- Copilot診断(キャッシュされたCopilot診断)
- ワークスペースに登録されたCodeFixProvider

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| CodeFixCollection | CodeFixCollection | 修正候補のコレクション |
| fixes | ImmutableArray<CodeFix> | 個々の修正アクション |
| fixAllState | FixAllState | 一括修正の状態情報 |
| supportedScopes | ImmutableArray<FixAllScope> | サポートされる修正範囲 |

### 出力先

- エディタのライトバルブメニューに表示
- 適用された修正はドキュメントに反映

## 処理フロー

### 処理シーケンス

```
1. 診断情報の取得
   └─ IDiagnosticAnalyzerService.GetDiagnosticsForSpanAsyncで指定範囲の診断を取得
2. Copilot診断の追加
   └─ document.GetCachedCopilotDiagnosticsAsyncでCopilot診断を取得
3. 診断のグループ化
   └─ 診断をTextSpanでグループ化してソート
4. CodeFixProviderの特定
   └─ 各診断IDに対応するワークスペース・プロジェクトのCodeFixProviderを取得
5. 修正候補の収集
   └─ 各CodeFixProviderのRegisterCodeFixesAsyncを呼び出し
6. 重複排除
   └─ 同じequivalenceKeyを持つ修正を重複排除
7. Fix All情報の付与
   └─ FixAllProviderInfoを取得してFixAllStateを構築
8. CodeFixCollectionの返却
   └─ 収集した修正をCodeFixCollectionとして返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: StreamFixesAsync] --> B[診断情報の取得]
    B --> C{診断あり?}
    C -->|No| D[yield break]
    C -->|Yes| E[診断をSpanでグループ化]
    E --> F[各Spanの診断を処理]
    F --> G[対応するCodeFixProviderを取得]
    G --> H{Provider存在?}
    H -->|No| I[次の診断へ]
    H -->|Yes| J[RegisterCodeFixesAsync呼び出し]
    J --> K[修正候補を収集]
    K --> L[重複排除処理]
    L --> M[FixAllState構築]
    M --> N[CodeFixCollection生成]
    N --> O[yield return collection]
    O --> I
    I --> P{全診断処理完了?}
    P -->|No| F
    P -->|Yes| Q[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 抑制診断の除外 | IsSuppressed=trueの診断は修正対象から除外 | 常時 |
| BR-02 | 優先度フィルタ | 指定された優先度に一致するProviderのみ実行 | priorityが指定された場合 |
| BR-03 | 重複排除 | 同一診断に対する同じequivalenceKeyの修正は最初のProviderのみ採用 | 複数Providerが同じ修正を提供する場合 |
| BR-04 | Interactive制限 | Interactive Workspaceでは一部のCodeFixのみ利用可能 | WorkspaceKind.Interactive時 |

### 計算ロジック

優先度によるProvider選択ロジック:
- priority == null: すべてのProviderを実行
- priority == High: コンパイラ診断のみ
- priority == Default/Low: ほとんどのアナライザー診断
- priority == Lowest: 抑制・設定系のみ

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

該当なし（インメモリ操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | CodeFixProvider例外 | Providerの初期化・実行時に例外発生 | エラーログ出力、InfoBar表示、該当Providerをスキップ |
| - | キャンセル | OperationCancelledException | 処理を中断して空の結果を返却 |

### リトライ仕様

なし（ユーザーが再度ライトバルブをクリックすることで再実行）

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

該当なし（ドキュメント変更はCodeActionの適用時に行われる）

## パフォーマンス要件

- テレメトリ: 500ms以上かかる修正計算は個別にログ記録
- 優先度による段階的読み込みでレスポンス時間を最適化
- 診断IDでフィルタリングしてから必要なProviderのみ実行

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

- 信頼できないCodeFixProviderからの例外は適切にキャッチしてログ出力
- 秘密情報を含むファイル(.env等)の変更提案には注意が必要

## 備考

- CodeFixServiceはMEFでエクスポートされ、シングルトンとして動作
- ワークスペースFixerとプロジェクトFixer(NuGet経由)の両方をサポート
- プロジェクトFixerはワークスペースFixerより優先される

---

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

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

### 推奨読解順序

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

まず、CodeFix機能で使用される主要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CodeFixCollection.cs | `src/Features/Core/Portable/CodeFixes/CodeFixCollection.cs` | 修正候補のコレクションを表すクラス |
| 1-2 | ICodeFixService.cs | `src/Features/Core/Portable/CodeFixes/Service/ICodeFixService.cs` | サービスのインターフェース定義 |

**読解のコツ**: CodeFixCollectionは、特定のTextSpanに対する複数のCodeFixをまとめて保持する。FixAllStateも含まれる点に注目。

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

処理の起点となるCodeFixServiceを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CodeFixService.cs | `src/Features/Core/Portable/CodeFixes/Service/CodeFixService.cs` | メインのサービス実装 |

**主要処理フロー**:
1. **93-166行目**: GetMostSevereFixAsync - 最も重要な修正を取得
2. **168-244行目**: StreamFixesAsync - 修正をストリーミングで取得
3. **436-633行目**: StreamFixesAsync(private) - 内部実装、Provider呼び出しとフィルタリング
4. **656-734行目**: GetCodeFixesAsync - 各Providerから修正を取得

#### Step 3: 診断情報の取得を理解する

診断サービスとの連携を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CodeFixService.cs | `src/Features/Core/Portable/CodeFixes/Service/CodeFixService.cs` | 73-91行目: GetShouldIncludeDiagnosticPredicate |

**主要処理フロー**:
- **73-91行目**: 優先度に基づいて含めるべき診断IDを決定
- **104-106行目**: IDiagnosticAnalyzerService.GetDiagnosticsForSpanAsyncで診断取得

#### Step 4: CodeFixProviderの管理を理解する

ワークスペース・プロジェクトレベルのProvider管理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CodeFixService.cs | `src/Features/Core/Portable/CodeFixes/Service/CodeFixService.cs` | 903-939行目: GetFixerPerLanguageMap |
| 4-2 | CodeFixService.ProjectCodeFixProvider.cs | `src/Features/Core/Portable/CodeFixes/Service/CodeFixService.ProjectCodeFixProvider.cs` | プロジェクトレベルのProvider管理 |

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

```
CodeFixService.StreamFixesAsync (public)
    │
    ├─ IDiagnosticAnalyzerService.GetDiagnosticsForSpanAsync
    │      └─ 指定範囲の診断情報を取得
    │
    ├─ document.GetCachedCopilotDiagnosticsAsync
    │      └─ Copilot診断の取得
    │
    ├─ ConvertToMap
    │      └─ 診断をSpanでグループ化
    │
    └─ StreamFixesAsync (private)
           │
           ├─ TryGetWorkspaceFixersMap
           │      └─ ワークスペースレベルのFixerを取得
           │
           ├─ GetProjectFixers
           │      └─ プロジェクトレベルのFixerを取得
           │
           └─ GetCodeFixesAsync
                  │
                  ├─ CodeFixProvider.RegisterCodeFixesAsync
                  │      └─ 各Providerから修正を登録
                  │
                  └─ TryGetFixesOrConfigurationsAsync
                         └─ FixAllProviderInfoの取得とコレクション構築
```

### データフロー図

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

TextSpan ───▶ GetDiagnosticsForSpanAsync ───▶ ImmutableArray<DiagnosticData>
                      │
                      ▼
DiagnosticData ───▶ ConvertToMap ───▶ SortedDictionary<TextSpan, List<DiagnosticData>>
                      │
                      ▼
DiagnosticId ───▶ TryGetWorkspaceFixersMap ───▶ ImmutableDictionary<DiagnosticId, ImmutableArray<CodeFixProvider>>
                      │
                      ▼
CodeFixProvider ───▶ RegisterCodeFixesAsync ───▶ ImmutableArray<CodeFix>
                      │
                      ▼
CodeFix[] ───▶ TryGetFixesOrConfigurationsAsync ───▶ CodeFixCollection
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CodeFixService.cs | `src/Features/Core/Portable/CodeFixes/Service/CodeFixService.cs` | ソース | メインサービス実装 |
| ICodeFixService.cs | `src/Features/Core/Portable/CodeFixes/Service/ICodeFixService.cs` | ソース | サービスインターフェース |
| CodeFixCollection.cs | `src/Features/Core/Portable/CodeFixes/CodeFixCollection.cs` | ソース | 修正コレクションデータ構造 |
| DiagnosticExtensions.cs | `src/Features/Core/Portable/CodeFixes/DiagnosticExtensions.cs` | ソース | 診断拡張メソッド |
| AbstractSuppressionCodeFixProvider.cs | `src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.cs` | ソース | 抑制系CodeFix基底クラス |
| ConfigurationUpdater.cs | `src/Features/Core/Portable/CodeFixes/Configuration/ConfigurationUpdater.cs` | ソース | 設定更新処理 |
| IFixMultipleOccurrencesService.cs | `src/Features/Core/Portable/CodeFixes/FixAllOccurrences/IFixMultipleOccurrencesService.cs` | ソース | 一括修正サービス |
