# 機能設計書 31-静的メンバーの移動

## 概要

本ドキュメントは、Roslynの「静的メンバーの移動（Move Static Members）」機能の設計仕様を記述する。この機能は、選択された静的メンバー（メソッド、プロパティ、フィールド等）を別の型に移動するリファクタリング機能である。

### 本機能の処理概要

**業務上の目的・背景**：大規模なコードベースでは、クラスが肥大化し、関連性の低い静的メンバーが1つのクラスに集約されることがある。この機能は、静的メンバーを適切な型に再配置することで、コードの凝集性を高め、保守性を向上させる。Single Responsibility Principleに従った設計を促進し、コードの理解容易性を向上させる。

**機能の利用シーン**：開発者がユーティリティクラスやヘルパークラスをリファクタリングする際、特定の静的メンバーを新しい専用クラスに移動したい場合に使用する。例えば、`StringHelper`クラスから日付関連のヘルパーメソッドを`DateHelper`クラスに移動するような場面で活用される。

**主要な処理内容**：
1. ユーザーが選択した静的メンバーの検証（有効な移動対象かどうかの判定）
2. 移動先の型の選択または新規作成（ダイアログによるユーザー操作）
3. 全ソリューション内での参照箇所の検索と更新
4. 移動元での静的メンバー参照の完全修飾化
5. 選択されたメンバーの移動先への配置

**関連システム・外部連携**：PullMemberUp機能と連携して実際のメンバー移動処理を行う。Visual Studioのダイアログサービスと連携してユーザーインターフェースを提供する。

**権限による制御**：特になし。ソースコードがあるファイルに対してのみ操作可能であり、生成コードファイルは対象外となる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | 静的メンバー移動ダイアログ | 主機能 | 静的メンバーの移動先型選択とメンバー選択 |
| 11 | 静的メンバー選択コントロール | 補助機能 | 静的メンバー移動ダイアログのメンバー選択部品 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 操作対象のドキュメント | null不可 |
| selectedMembers | ImmutableArray<ISymbol> | Yes | 選択された静的メンバーシンボル | 空配列不可、すべてが同一型に属すること |
| selectedType | INamedTypeSymbol | Yes | 選択されたメンバーを含む型 | null不可 |
| destination | INamedTypeSymbol または string | Yes | 移動先の型（既存）または新規型名 | 有効な型名であること |

### 入力データソース

- エディタで選択された静的メンバー宣言
- IMoveStaticMembersOptionsServiceによるダイアログ入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| modifiedSolution | Solution | 変更が適用されたソリューション |

### 出力先

- 移動元ドキュメント（メンバー削除、参照の完全修飾化）
- 移動先ドキュメント（メンバー追加）
- 参照元ドキュメント（参照の更新）

## 処理フロー

### 処理シーケンス

```
1. 選択されたノードの取得とシンボル解決
   └─ GetSelectedNodesAsync()で選択範囲のノードを取得
   └─ セマンティックモデルからシンボル情報を取得

2. メンバーの検証
   └─ MemberAndDestinationValidator.IsMemberValidで有効性チェック
   └─ 静的メンバーかどうかの確認
   └─ すべてのメンバーが同一型に属するかの確認
   └─ Enum型のメンバーは対象外

3. ダイアログ表示とオプション取得
   └─ IMoveStaticMembersOptionsService.GetMoveMembersToTypeOptions()
   └─ 移動先の選択（既存型 or 新規型）
   └─ 移動するメンバーの最終選択

4. 参照の検索と更新（既存型への移動の場合）
   └─ FindMemberReferencesAsync()で全参照を検索
   └─ RefactorReferencesAsync()で参照を新しい型名に更新

5. 新規型の作成（新規型への移動の場合）
   └─ ExtractTypeHelpers.AddTypeToNewFileAsync()
   └─ 必要な型パラメータの抽出と適用

6. 静的メンバー参照の完全修飾化
   └─ QualifyStaticMemberReferencesAsync()
   └─ 移動するメンバー内で元の型の他のメンバーを参照している場合に修飾

7. メンバーの移動実行
   └─ PullMembersUpOptionsBuilderでオプション構築
   └─ MembersPuller.PullMembersUpAsync()でメンバー移動

8. ソリューションの更新
   └─ ApplyChangesOperationで変更を適用
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[選択ノードの取得]
    B --> C{メンバーは有効か?}
    C -->|No| Z[終了]
    C -->|Yes| D{すべて静的か?}
    D -->|No| Z
    D -->|Yes| E{同一型に属するか?}
    E -->|No| Z
    E -->|Yes| F[ダイアログ表示]
    F --> G{キャンセル?}
    G -->|Yes| Z
    G -->|No| H{新規型を作成?}
    H -->|Yes| I[新規型を作成]
    H -->|No| J[既存型を取得]
    I --> K[参照の検索と更新]
    J --> K
    K --> L[静的参照の完全修飾化]
    L --> M[メンバーの移動]
    M --> N[ソリューション更新]
    N --> Z[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-31-01 | 静的メンバー限定 | 移動対象は静的メンバーのみ | 常に適用 |
| BR-31-02 | 同一型メンバー | 選択されたすべてのメンバーは同一の型に属する必要がある | 常に適用 |
| BR-31-03 | Enum除外 | Enum型のメンバーは移動対象外 | 型がEnumの場合 |
| BR-31-04 | ソース内型限定 | 移動先はソースコード内の型のみ | 常に適用 |
| BR-31-05 | 生成コード除外 | 生成コードファイルは対象外 | ファイルが生成コードの場合 |

### 計算ロジック

型パラメータの抽出ロジック：
```
必要な型パラメータ = 選択メンバーが参照する型パラメータの集合
新しい型の型引数インデックス = 元の型の型パラメータから必要なもののインデックスリスト
```

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

該当なし（メモリ上のシンボルとソースコードの操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | 検証エラー | 非静的メンバーの選択 | リファクタリングを提供しない |
| N/A | 検証エラー | 異なる型のメンバー混在 | リファクタリングを提供しない |
| N/A | 検証エラー | Enum型メンバーの選択 | リファクタリングを提供しない |
| N/A | ユーザーキャンセル | ダイアログでキャンセル | 操作を中止、変更なし |

### リトライ仕様

該当なし（インタラクティブな操作のため）

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

ソリューション全体の変更は単一のApplyChangesOperationとして適用される。中間状態は存在せず、すべての変更が成功するか、すべて適用されないかのいずれかとなる。

## パフォーマンス要件

- 大規模ソリューションでも参照検索は非同期で実行
- UIのレスポンシブ性を維持するため、キャンセル可能な操作として実装

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

- ソースコードへの書き込み権限が必要
- 生成コードファイルは保護のため対象外

## 備考

- 拡張メソッドの移動時は、呼び出し側でstaticメソッド呼び出しに展開される
- VBのModuleは静的クラスとして扱われる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MoveStaticMembersOptions.cs | `src/Features/Core/Portable/MoveStaticMembers/MoveStaticMembersOptions.cs` | 移動オプションの構造体。IsCancelled、FilePath、IsNewType、Destination、TypeName、NamespaceDisplay、SelectedMembersフィールドを理解する |
| 1-2 | IMoveStaticMembersOptionsService.cs | `src/Features/Core/Portable/MoveStaticMembers/IMoveStaticMembersOptionsService.cs` | ダイアログサービスのインターフェース定義 |

**読解のコツ**: MoveStaticMembersOptionsは2つのコンストラクタを持つ。既存型への移動と新規型への移動で異なるコンストラクタが使用される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AbstractMoveStaticMembersRefactoringProvider.cs | `src/Features/Core/Portable/MoveStaticMembers/AbstractMoveStaticMembersRefactoringProvider.cs` | CodeRefactoringProviderの実装。ComputeRefactoringsAsyncがエントリーポイント |

**主要処理フロー**:
1. **20-71行目**: ComputeRefactoringsAsyncメソッド - 選択されたノードの取得とメンバー検証
2. **30-34行目**: GetSelectedNodesAsync - 抽象メソッド、言語固有の実装
3. **36-48行目**: メンバーの検証 - 有効性チェックと静的メンバーフィルタリング
4. **50-60行目**: 型の検証 - 同一型所属チェック、Enum除外
5. **68-70行目**: MoveStaticMembersWithDialogCodeActionの登録

#### Step 3: メイン処理ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MoveStaticMembersWithDialogCodeAction.cs | `src/Features/Core/Portable/MoveStaticMembers/MoveStaticMembersWithDialogCodeAction.cs` | 実際の移動処理を行うCodeAction |

**主要処理フロー**:
- **38-41行目**: GetOptions - ダイアログサービスからオプション取得
- **43-144行目**: ComputeOperationsAsync - メイン処理ロジック
- **61-78行目**: 既存型への移動処理（RefactorAndMoveAsync呼び出し）
- **81-143行目**: 新規型作成と移動処理
- **167-231行目**: RefactorAndMoveAsync - 参照更新とメンバー移動の実行
- **361-390行目**: FindMemberReferencesAsync - 全ソリューションでの参照検索
- **396-449行目**: QualifyStaticMemberReferencesAsync - 静的参照の完全修飾化

#### Step 4: メンバー移動の実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | MembersPuller.cs | `src/Features/Core/Portable/PullMemberUp/MembersPuller.cs` | 実際のメンバー移動処理（PullMemberUp機能と共通） |

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

```
AbstractMoveStaticMembersRefactoringProvider.ComputeRefactoringsAsync
    │
    ├─ GetSelectedNodesAsync (abstract)
    │      └─ 言語固有の実装（C#/VB）
    │
    ├─ MemberAndDestinationValidator.IsMemberValid
    │
    └─ MoveStaticMembersWithDialogCodeAction
           │
           ├─ GetOptions
           │      └─ IMoveStaticMembersOptionsService.GetMoveMembersToTypeOptions
           │
           └─ ComputeOperationsAsync
                  │
                  ├─ [既存型の場合] RefactorAndMoveAsync
                  │      ├─ FindMemberReferencesAsync
                  │      │      └─ SymbolFinder.FindReferencesAsync
                  │      ├─ RefactorReferencesAsync
                  │      │      └─ FixReferencesSingleDocumentAsync
                  │      ├─ QualifyStaticMemberReferencesAsync
                  │      └─ MembersPuller.PullMembersUpAsync
                  │
                  └─ [新規型の場合]
                         ├─ ExtractTypeHelpers.AddTypeToNewFileAsync
                         ├─ FindMemberReferencesAsync
                         ├─ RefactorReferencesAsync
                         ├─ QualifyStaticMemberReferencesAsync
                         └─ MembersPuller.PullMembersUpAsync
```

### データフロー図

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

選択されたメンバー ───────▶ AbstractMoveStaticMembersRefactoringProvider
                                 │
ダイアログ選択 ──────────▶ MoveStaticMembersWithDialogCodeAction ───▶ 変更後Solution
                                 │
                        ┌────────┴────────┐
                        ▼                 ▼
               [既存型への移動]    [新規型への移動]
                        │                 │
                        ▼                 ▼
              RefactorAndMoveAsync  ExtractTypeHelpers
                        │                 │
                        └────────┬────────┘
                                 ▼
                     MembersPuller.PullMembersUpAsync
                                 │
                                 ▼
                    ApplyChangesOperation ───────▶ 更新されたソリューション
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AbstractMoveStaticMembersRefactoringProvider.cs | `src/Features/Core/Portable/MoveStaticMembers/` | ソース | リファクタリングプロバイダーの基底クラス |
| MoveStaticMembersWithDialogCodeAction.cs | `src/Features/Core/Portable/MoveStaticMembers/` | ソース | メイン処理を行うCodeAction |
| MoveStaticMembersOptions.cs | `src/Features/Core/Portable/MoveStaticMembers/` | ソース | 移動オプションのデータ構造 |
| IMoveStaticMembersOptionsService.cs | `src/Features/Core/Portable/MoveStaticMembers/` | ソース | ダイアログサービスインターフェース |
| MembersPuller.cs | `src/Features/Core/Portable/PullMemberUp/` | ソース | メンバー移動の実行処理 |
| MemberAndDestinationValidator.cs | `src/Features/Core/Portable/PullMemberUp/` | ソース | メンバーと移動先の検証 |
| ExtractTypeHelpers.cs | `src/Features/Core/Portable/` | ソース | 型抽出のヘルパー関数 |
