# 機能設計書 27-クラス抽出

## 概要

本ドキュメントは、Roslynにおける「クラス抽出」機能の設計を記述するものである。クラス抽出機能は、既存のクラスから選択されたメンバーを新しい基底クラスに移動し、元のクラスがそれを継承するようにするリファクタリング機能である。

### 本機能の処理概要

クラス抽出機能は、ユーザーが選択したメンバーを新しい基底クラスとして抽出し、元のクラスがその基底クラスを継承するように変更する。これにより、クラス階層を導入し、コードの再利用性を向上させることができる。

**業務上の目的・背景**：大きなクラスは保守が困難であり、単一責任の原則に違反しがちである。クラス抽出は、共通の機能を基底クラスに移動することで、コードの再利用と保守性を向上させる。また、将来の派生クラスの追加を容易にする。

**機能の利用シーン**：
1. 共通の機能を持つ複数のクラスから基底クラスを抽出する
2. 大きなクラスを分割してリファクタリングする
3. テンプレートメソッドパターンを導入する
4. クラス階層を整理する

**主要な処理内容**：
1. メンバーの選択(UI経由)
2. 新しい基底クラスの生成
3. 選択されたメンバーの基底クラスへの移動
4. 元のクラスの継承関係の更新
5. 参照の更新

**関連システム・外部連携**：
- CodeRefactoringProvider経由でエディタに統合
- IExtractClassOptionsServiceでUI連携
- PullMemberUpとの連携

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | クラス抽出ダイアログ | 主画面 | 基底クラス名とメンバーの選択 |
| 20 | プレビューペイン | 補助画面 | 変更箇所のプレビュー |

## 機能種別

コード変換処理 / リファクタリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 対象のドキュメント | 有効なドキュメントであること |
| span | TextSpan | Yes | 選択範囲 | 型宣言またはメンバー内であること |
| containingType | INamedTypeSymbol | Yes | 抽出元の型 | 基底クラスがSystem.Objectであること |
| selectedMembers | ImmutableArray<ISymbol> | Yes | 抽出するメンバー | - |
| newClassName | string | Yes | 新しい基底クラス名 | 有効な識別子であること |

### 入力データソース

- ドキュメントの構文ツリー(SyntaxTree)
- セマンティックモデル(SemanticModel)
- IExtractClassOptionsServiceからのユーザー入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| CodeAction | CodeAction | 抽出アクション |
| updatedSolution | Solution | 更新後のソリューション |

### 出力先

- 新規ファイルに基底クラスを作成
- 元のドキュメントの型宣言を更新

## 処理フロー

### 処理シーケンス

```
1. メンバーの選択検証
   └─ 選択されたメンバーが有効かどうか確認
2. 基底クラスの有無確認
   └─ 既存の基底クラスがSystem.Objectでない場合は不可
3. オプション取得
   └─ IExtractClassOptionsServiceから設定を取得
4. 基底クラス生成
   └─ 新しいクラスを新規ファイルに作成
5. メンバー移動
   └─ PullMembersUpを使用してメンバーを基底クラスに移動
6. 継承関係更新
   └─ 元のクラスの基底クラスを新しいクラスに設定
```

### フローチャート

```mermaid
flowchart TD
    A[開始: ComputeRefactoringsAsync] --> B[GetSelectedNodesAsync]
    B --> C{メンバー選択あり?}
    C -->|No| D[GetSelectedClassDeclarationAsync]
    C -->|Yes| E[TryGetMemberActionAsync]
    D --> F[TryGetClassActionAsync]
    E --> G{HasBaseType?}
    G -->|Yes| H[処理不可]
    G -->|No| I[ExtractClassWithDialogCodeAction生成]
    F --> J{HasBaseType?}
    J -->|Yes| H
    J -->|No| I
    I --> K[CodeAction登録]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 基底クラス制限 | 既存の基底クラスがSystem.Object以外の場合は抽出不可 | HasBaseType判定 |
| BR-02 | メンバー検証 | MemberAndDestinationValidator.IsMemberValidで有効性を確認 | メンバー選択時 |
| BR-03 | 同一型内制限 | 選択されたメンバーはすべて同じ型内でなければならない | メンバー選択時 |
| BR-04 | マルフォームドコード | 型宣言ノードが見つからない場合は処理不可 | 常時 |

### 計算ロジック

HasBaseType判定ロジック:
```
containingType.BaseType?.SpecialType != SpecialType.System_Object
```
→ 基底クラスがSystem.Object以外の場合はtrue(抽出不可)

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 基底クラス存在 | 既に基底クラスを持つ | リファクタリング不可として表示しない |
| - | 無効なメンバー | 移動できないメンバーを選択 | リファクタリング不可として表示しない |

### リトライ仕様

なし

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

該当なし

## パフォーマンス要件

- 非同期処理でUIスレッドをブロックしない
- Spanの選択範囲に基づいてフィルタリング

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

- 特になし

## 備考

- PullMemberUp機能を内部で使用してメンバー移動を実現
- IExtractClassOptionsServiceがない場合は機能が利用不可
- クラス全体を選択した場合は、すべてのメンバーを対象とするダイアログを表示

---

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

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

### 推奨読解順序

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

まず、クラス抽出で使用される主要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ExtractClassOptions.cs | `src/Features/Core/Portable/ExtractClass/ExtractClassOptions.cs` | オプション構造 |
| 1-2 | IExtractClassOptionsService.cs | `src/Features/Core/Portable/ExtractClass/IExtractClassOptionsService.cs` | サービスインターフェース |

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

処理の起点となるAbstractExtractClassRefactoringProvider.csを確認する。

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

**主要処理フロー**:
1. **27-50行目**: ComputeRefactoringsAsync - エントリーポイント
2. **52-109行目**: TryGetMemberActionAsync - メンバー選択時のアクション取得
3. **111-135行目**: TryGetClassActionAsync - クラス選択時のアクション取得
4. **137行目**: HasBaseType - 基底クラスの有無チェック

#### Step 3: CodeActionを理解する

実際の抽出処理を行うCodeActionを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ExtractClassWithDialogCodeAction.cs | `src/Features/Core/Portable/ExtractClass/ExtractClassWithDialogCodeAction.cs` | CodeAction実装 |

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

```
AbstractExtractClassRefactoringProvider.ComputeRefactoringsAsync
    │
    ├─ GetSelectedNodesAsync
    │      └─ 選択されたメンバーノードを取得
    │
    ├─ TryGetMemberActionAsync
    │      ├─ MemberAndDestinationValidator.IsMemberValid
    │      ├─ HasBaseType判定
    │      └─ ExtractClassWithDialogCodeAction生成
    │
    └─ TryGetClassActionAsync
           ├─ GetSelectedClassDeclarationAsync
           ├─ HasBaseType判定
           └─ ExtractClassWithDialogCodeAction生成

ExtractClassWithDialogCodeAction
    │
    ├─ IExtractClassOptionsService
    │      └─ ユーザーからオプション取得
    │
    └─ (内部処理)
           ├─ 新規クラスファイル作成
           └─ PullMemberUp使用でメンバー移動
```

### データフロー図

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

TextSpan ───▶ GetSelectedNodesAsync ───▶ ImmutableArray<SyntaxNode>
                      │
                      ▼
SyntaxNodes ───▶ GetDeclaredSymbol ───▶ ImmutableArray<ISymbol>
                      │
                      ▼
ISymbol[] ───▶ MemberAndDestinationValidator.IsMemberValid ───▶ Valid Members
                      │
                      ▼
ContainingType ───▶ HasBaseType ───▶ bool
                      │
                      ▼
Valid ───▶ ExtractClassWithDialogCodeAction ───▶ CodeAction
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AbstractExtractClassRefactoringProvider.cs | `src/Features/Core/Portable/ExtractClass/AbstractExtractClassRefactoringProvider.cs` | ソース | メイン処理 |
| ExtractClassWithDialogCodeAction.cs | `src/Features/Core/Portable/ExtractClass/ExtractClassWithDialogCodeAction.cs` | ソース | CodeAction |
| ExtractClassOptions.cs | `src/Features/Core/Portable/ExtractClass/ExtractClassOptions.cs` | ソース | オプション構造 |
| IExtractClassOptionsService.cs | `src/Features/Core/Portable/ExtractClass/IExtractClassOptionsService.cs` | ソース | サービスインターフェース |
| MemberAndDestinationValidator.cs | `src/Features/Core/Portable/PullMemberUp/MemberAndDestinationValidator.cs` | ソース | メンバー検証 |
