# 機能設計書 59-条件反転

## 概要

本ドキュメントは、Roslyn機能「条件反転」の機能設計書である。if文の条件を反転させ、true/false分岐の本体を入れ替えるコードリファクタリング機能について記述する。

### 本機能の処理概要

**業務上の目的・背景**：ガード節パターンや早期リターンは、ネストを減らしてコードの可読性を向上させる一般的なテクニックである。本機能は、if文の条件を反転させてtrue/false分岐を入れ替えることで、ガード節パターンへの変換やコード構造の最適化を支援する。

**機能の利用シーン**：
- ネストしたif-else文をガード節パターンに変換したい場合
- 肯定条件と否定条件を入れ替えてより読みやすくしたい場合
- 早期リターンパターンを適用したい場合
- プリプロセッサディレクティブ（#if/#else）の条件を反転したい場合

**主要な処理内容**：
1. if文の条件を論理的に反転（`condition` → `!condition`）
2. true分岐とelse分岐の本体を入れ替え
3. elseなしif文の場合: 後続ステートメントをif本体に移動
4. 制御フロー解析に基づく適切なジャンプステートメントの挿入
5. プリプロセッサディレクティブ（#if/#else/#endif）の反転

**関連システム・外部連携**：該当なし（IDE内機能）

**権限による制御**：該当なし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | エディタ | 主画面 | リファクタリング候補の表示とクイックアクション実行 |

## 機能種別

コードリファクタリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| IfStatement | SyntaxNode | Yes | if文のAST | 反転可能な構造であること |
| IfDirective | SyntaxNode | Conditional | #ifディレクティブ | ディレクティブ反転時 |
| Document | Document | Yes | 対象ドキュメント | null不可 |
| SemanticModel | SemanticModel | Yes | セマンティック情報 | null不可 |

### 入力データソース

エディタ内の選択位置またはカーソル位置にあるif文または#ifディレクティブ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| InvertedIfStatement | SyntaxNode | 反転後のif文 |
| UpdatedDocument | Document | 更新後のドキュメント |

### 出力先

エディタ（ソースコードの置換）

## 処理フロー

### 処理シーケンス

```
1. リファクタリングコンテキストの取得
   └─ カーソル位置のノードを特定

2. 対象の判定
   └─ if文の場合: CanInvertで反転可能性をチェック
   └─ #ifディレクティブの場合: #else/#endifの存在を確認

3. 反転スタイルの決定
   └─ else付きif文: true/false本体を入れ替え
   └─ elseなしif文: 制御フロー解析で最適なスタイルを選択

4. 条件の反転
   └─ SyntaxGenerator.Negateで条件を否定
   └─ 二重否定の最適化

5. 本体の入れ替え
   └─ true分岐 ↔ false分岐
   └─ 後続ステートメントの処理

6. ドキュメントの更新
   └─ 元のif文を反転後の構造で置換
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{対象種別}
    B -->|if文| C{else有?}
    B -->|#if| D[ディレクティブ反転]
    C -->|Yes| E[true/false本体入替]
    C -->|No| F[InvertIfStyleを決定]
    F --> G{スタイル}
    G -->|WithElse| H[else節を追加]
    G -->|SwapStatements| I[後続ステートメントと入替]
    G -->|WithJump| J[ジャンプ文挿入]
    E --> K[条件を反転]
    H --> K
    I --> K
    J --> K
    D --> L[#if/#elseセクション入替]
    K --> M[ドキュメント更新]
    L --> M
    M --> N[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-59-01 | else付き反転 | true/false本体を単純に入れ替え | if-else構造 |
| BR-59-02 | else無し・後続なし | 最近傍のジャンプステートメントを挿入 | 後続ステートメントがない場合 |
| BR-59-03 | else無し・後続あり | 後続ステートメントをif本体に移動 | 後続ステートメントがある場合 |
| BR-59-04 | 条件反転最適化 | `!!x` → `x`、`!(a == b)` → `a != b`等 | 常時 |
| BR-59-05 | ディレクティブ反転 | #if/#else/#endifパターンのみ対応 | 3要素構成の場合 |
| BR-59-06 | エラー診断除外 | 診断エラーがある場合は反転不可 | 常時 |

### 計算ロジック

- 制御フロー解析: SemanticModel.AnalyzeControlFlowで終点到達可能性を判定
- 最近傍ジャンプ: 親のreturn/break/continue/throw等を検索

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 反転不可 | CanInvertがfalse | リファクタリングを提示しない |
| - | 診断エラー | 構文エラーがある場合 | リファクタリングを提示しない |
| - | 不正なディレクティブ | #if/#else/#endif以外のパターン | リファクタリングを提示しない |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 制御フロー解析を使用するため、メソッドの複雑さに比例した処理時間

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

該当なし（コード変換のみでセキュリティ上のリスクなし）

## 備考

- 8種類のInvertIfStyleで様々なシナリオに対応
- プリプロセッサディレクティブの反転は独立した処理パス

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AbstractInvertIfCodeRefactoringProvider.cs | `src/Features/Core/Portable/InvertIf/` | InvertIfStyle列挙型 |

**InvertIfStyle（38-48行目）**:
- IfWithElse_SwapIfBodyWithElseBody: else付きの場合
- IfWithoutElse_SwapIfBodyWithSubsequentStatements: 後続ステートメントと入替
- IfWithoutElse_MoveSubsequentStatementsToIfBody: 後続をif本体に移動
- IfWithoutElse_WithElseClause: else節を追加
- IfWithoutElse_MoveIfBodyToElseClause: 本体をelseに移動
- IfWithoutElse_WithSubsequentExitPointStatement: 出口点ステートメント使用
- IfWithoutElse_WithNearmostJumpStatement: 最近傍ジャンプ使用
- IfWithoutElse_WithNegatedCondition: 条件のみ反転

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AbstractInvertIfCodeRefactoringProvider.cs | `src/Features/Core/Portable/InvertIf/` | メイン処理クラス |

**主要処理フロー**:
1. **93-99行目**: ComputeRefactoringsAsyncでリファクタリング候補を計算
2. **101-150行目**: TryComputeRefactoringForIfDirectiveAsyncでディレクティブ反転
3. **152-189行目**: InvertIfDirectiveAsyncでディレクティブを反転
4. **194-210行目**: TryComputeRefactorForIfStatementAsyncでif文反転
5. **212-392行目**: GetInvertIfStyleで反転スタイルを決定
6. **397-421行目**: InvertIfAsyncで反転を実行
7. **533-756行目**: GetRootWithInvertIfStatementで各スタイルに応じた変換

**読解のコツ**: GetInvertIfStyleメソッドの条件分岐が複雑なので、各InvertIfStyleのコメントを参照しながら理解する。

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

```
ComputeRefactoringsAsync
    │
    ├─ TryComputeRefactoringForIfDirectiveAsync
    │      ├─ GetMatchingConditionalDirectives
    │      └─ InvertIfDirectiveAsync
    │             ├─ Generator.Negate
    │             └─ TextChange (swap sections)
    │
    └─ TryComputeRefactorForIfStatementAsync
           ├─ TryGetRelevantNodeAsync<TIfStatementSyntax>
           ├─ CanInvert
           └─ InvertIfAsync
                  ├─ GetInvertIfStyle
                  │      ├─ IsElseless
                  │      ├─ GetIfBodyStatementRange
                  │      ├─ GetSubsequentStatementRanges
                  │      └─ AnalyzeControlFlow
                  ├─ Generator.Negate
                  └─ GetRootWithInvertIfStatement
```

### データフロー図

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

if (cond) { A } else { B } ───▶ SwapIfBodyWithElseBody ───▶ if (!cond) { B } else { A }

if (cond) { jump; } C ───▶ MoveSubsequentStatementsToIfBody ───▶ if (!cond) { C }

#if COND
 A
#else
 B
#endif                     ───▶ InvertIfDirective ───▶ #if !COND
                                                        B
                                                       #else
                                                        A
                                                       #endif
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AbstractInvertIfCodeRefactoringProvider.cs | `src/Features/Core/Portable/InvertIf/` | ソース | 条件反転の抽象プロバイダ |
| StatementRange.cs | `src/Features/Core/Portable/InvertIf/` | ソース | ステートメント範囲構造体 |
