# 機能設計書 38-コンストラクタ生成

## 概要

本ドキュメントは、Roslynの「コンストラクタ生成（Generate Constructors）」機能の設計仕様を記述する。この機能は、選択されたフィールドやプロパティからコンストラクタを自動生成するリファクタリング機能である。

### 本機能の処理概要

**業務上の目的・背景**：クラスやstructのフィールド・プロパティを初期化するコンストラクタは頻繁に必要となる定型的なコードである。この機能は、そのようなボイラープレートコードの自動生成を支援し、開発効率を向上させる。

**機能の利用シーン**：
1. 開発者が複数のフィールド/プロパティを選択してコンストラクタを生成したい場合
2. 型ヘッダーまたはメンバー間でコンストラクタ生成ダイアログを開きたい場合
3. 基底クラスのコンストラクタを委譲するコンストラクタを生成したい場合

**主要な処理内容**：
1. 選択されたメンバー（フィールド/プロパティ）の検証
2. 既存のコンストラクタとの重複チェック
3. 基底クラスへの委譲コンストラクタ検索
4. パラメータ名とnullチェックオプションの決定
5. コンストラクタの生成

**関連システム・外部連携**：メンバー選択ダイアログサービス（IPickMembersService）を使用してユーザーインターフェースを提供する。コード生成サービスを使用してコンストラクタを生成する。

**権限による制御**：静的クラスではコンストラクタ生成不可。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | コンストラクタ生成ダイアログ | 主機能 | フィールド・プロパティからコンストラクタ生成設定 |

## 機能種別

コード生成 / コードリファクタリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 操作対象のドキュメント | null不可 |
| textSpan | TextSpan | Yes | 選択範囲 | 有効な範囲 |
| selectedMembers | ImmutableArray<ISymbol> | No | 選択されたメンバー | フィールドまたはプロパティ |
| addNullChecks | bool | No | nullチェックを追加するか | デフォルトfalse |
| desiredAccessibility | Accessibility? | No | 希望するアクセス修飾子 | null許可 |

### 入力データソース

- エディタでの選択範囲（フィールド/プロパティ選択）
- IPickMembersServiceによるダイアログ入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| modifiedDocument | Document | 変更が適用されたドキュメント |

### 出力先

- 対象ドキュメント（コンストラクタの挿入）

## 処理フロー

### 処理シーケンス

```
1. コンテキスト判定
   a. メンバー選択モード: 選択されたフィールド/プロパティを取得
   b. 非選択モード: 型ヘッダーまたはメンバー間にいるか確認

2. 型の検証
   └─ クラスまたはstructのみ対象
   └─ 静的クラスは除外

3. メンバー選択モードの処理
   └─ GetSelectedMemberInfoAsync()で選択メンバー取得
   └─ State.TryGenerateAsync()で既存コンストラクタとの重複チェック

4. 非選択モードの処理
   └─ HandleNonSelectionAsync()
   └─ 書き込み可能なインスタンスフィールド/プロパティを収集
   └─ nullチェック可能なメンバーがある場合はオプション表示
   └─ GenerateConstructorWithDialogCodeAction生成

5. 基底クラス委譲コンストラクタの提供
   └─ IGenerateDefaultConstructorsService.GenerateDefaultConstructorsAsync()
   └─ 基底クラスのアクセス可能なコンストラクタを列挙

6. コンストラクタの生成
   a. FieldDelegatingCodeAction: フィールド/プロパティを直接初期化
   b. ConstructorDelegatingCodeAction: 既存コンストラクタに委譲
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{メンバー選択?}
    B -->|Yes| C[選択メンバー取得]
    B -->|No| D{型ヘッダー/メンバー間?}
    D -->|No| Z[終了]
    D -->|Yes| E[書き込み可能メンバー収集]
    C --> F[State.TryGenerateAsync]
    F --> G{既存コンストラクタ?}
    G -->|あり| Z
    G -->|なし| H[CodeAction生成]
    E --> I{メンバーあり?}
    I -->|No| Z
    I -->|Yes| J[ダイアログCodeAction生成]
    H --> K[基底クラスコンストラクタ検索]
    J --> K
    K --> L[基底クラス委譲アクション生成]
    L --> M[CodeAction登録]
    M --> Z[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-38-01 | クラス/struct限定 | クラスまたはstructのみ対象 | 常に適用 |
| BR-38-02 | 静的クラス除外 | 静的クラスはコンストラクタ生成不可 | 常に適用 |
| BR-38-03 | 書き込み可能メンバー | 書き込み可能なインスタンスフィールド/プロパティのみ対象 | 常に適用 |
| BR-38-04 | 重複チェック | 既存のコンストラクタと同じシグネチャは生成しない | 常に適用 |
| BR-38-05 | nullチェックオプション | 参照型/null許容型のメンバーにはnullチェック追加可能 | 該当メンバーがある場合 |
| BR-38-06 | ArgumentNullException要件 | nullチェック生成にはArgumentNullException型が必要 | nullチェック使用時 |

### 計算ロジック

コンストラクタシグネチャ決定ロジック：
```
パラメータリスト = 選択メンバー.Select(m => {
    名前 = ToParameterName(m.Name)
    型 = m.GetSymbolType()
    return (名前, 型)
})

if (既存コンストラクタに同じシグネチャあり) {
    生成しない
}
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | 検証エラー | 静的クラスを選択 | リファクタリングを提供しない |
| N/A | 検証エラー | 書き込み可能メンバーなし | リファクタリングを提供しない |
| N/A | 検証エラー | 既存コンストラクタと重複 | リファクタリングを提供しない |
| N/A | 検証エラー | ArgumentNullException型なし（nullチェック使用時） | ダイアログを表示しない |

### リトライ仕様

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

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

ドキュメント単位での変更を適用。すべての変更が成功するか、すべて適用されないかのいずれかとなる。

## パフォーマンス要件

- UIのレスポンシブ性を維持するため、キャンセル可能な操作として実装
- 基底クラスコンストラクタの検索は効率的に実行

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

- ソースコードへの書き込み権限が必要

## 備考

- throw式とthrow文の両方をサポート（nullチェック生成時）
- プロパティのバッキングフィールドへの直接書き込みが可能な場合はそちらを使用
- Intent Providerとしても機能し、プログラム的なコンストラクタ生成をサポート

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AbstractGenerateConstructorsCodeRefactoringProvider.cs | `src/Features/Core/Portable/GenerateConstructors/AbstractGenerateConstructorsCodeRefactoringProvider.cs` | CodeRefactoringProviderとIIntentProviderの実装 |

**主要処理フロー**:
1. **31-49行目**: クラス定義 - IIntentProviderインターフェース実装
2. **66-75行目**: ComputeRefactoringsAsync - エントリーポイント
3. **151-188行目**: ComputeRefactoringsAsync（内部） - メイン処理フロー

#### Step 2: メンバー選択処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AbstractGenerateConstructorsCodeRefactoringProvider.cs | `src/Features/Core/Portable/GenerateConstructors/AbstractGenerateConstructorsCodeRefactoringProvider.cs` | GenerateConstructorFromMembersAsync |

**主要処理フロー**:
- **265-280行目**: GenerateConstructorFromMembersAsync - メンバーからのコンストラクタ生成
- **270行目**: GetSelectedMemberInfoAsync - 選択メンバー取得
- **273行目**: State.TryGenerateAsync - 状態生成と重複チェック

#### Step 3: 非選択モード処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AbstractGenerateConstructorsCodeRefactoringProvider.cs | `src/Features/Core/Portable/GenerateConstructors/AbstractGenerateConstructorsCodeRefactoringProvider.cs` | HandleNonSelectionAsync |

**主要処理フロー**:
- **190-263行目**: HandleNonSelectionAsync - 非選択時の処理
- **200-206行目**: 型ヘッダーまたはメンバー間の判定
- **211-214行目**: 型の検証（クラス/struct、非静的）
- **226行目**: 書き込み可能メンバーの収集
- **241-244行目**: nullチェックオプションの追加
- **260-262行目**: GenerateConstructorWithDialogCodeAction生成

#### Step 4: CodeAction実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AbstractGenerateConstructorsCodeRefactoringProvider.cs | `src/Features/Core/Portable/GenerateConstructors/AbstractGenerateConstructorsCodeRefactoringProvider.cs` | FieldDelegatingCodeAction、ConstructorDelegatingCodeAction |

**主要処理フロー**:
- **282-291行目**: GetCodeActions - CodeActionの生成
- **286行目**: FieldDelegatingCodeAction - フィールド初期化コンストラクタ
- **288行目**: ConstructorDelegatingCodeAction - 委譲コンストラクタ

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

```
AbstractGenerateConstructorsCodeRefactoringProvider.ComputeRefactoringsAsync
    │
    ├─ [メンバー選択] GenerateConstructorFromMembersAsync
    │      ├─ GetSelectedMemberInfoAsync
    │      └─ State.TryGenerateAsync
    │             └─ GetCodeActions
    │                    ├─ FieldDelegatingCodeAction
    │                    └─ ConstructorDelegatingCodeAction
    │
    ├─ [非選択] HandleNonSelectionAsync
    │      ├─ IRefactoringHelpersService.IsOnTypeHeader
    │      ├─ IRefactoringHelpersService.IsBetweenTypeMembers
    │      ├─ IsWritableInstanceFieldOrProperty
    │      ├─ CanAddNullCheck
    │      └─ GenerateConstructorWithDialogCodeAction
    │             └─ GetOperationsAsync
    │                    ├─ IPickMembersService.PickMembersAsync
    │                    └─ GenerateConstructor
    │
    └─ IGenerateDefaultConstructorsService.GenerateDefaultConstructorsAsync
           └─ 基底クラス委譲コンストラクタ生成
```

### データフロー図

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

メンバー選択 ─────────▶ AbstractGenerateConstructorsCodeRefactoringProvider
                                 │
                        ┌────────┴────────┐
                        ▼                 ▼
              [メンバー選択モード]   [非選択モード]
                        │                 │
                        ▼                 ▼
              GetSelectedMemberInfo  HandleNonSelectionAsync
                        │                 │
                        ▼                 ▼
              State.TryGenerateAsync  GenerateConstructorWithDialogCodeAction
                        │                 │
                        └────────┬────────┘
                                 ▼
                        ┌────────┴────────┐
                        ▼                 ▼
              FieldDelegatingCodeAction  ConstructorDelegatingCodeAction
                        │                 │
                        └────────┬────────┘
                                 ▼
                        コンストラクタ挿入
                                 │
                                 ▼
                        更新されたドキュメント
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AbstractGenerateConstructorsCodeRefactoringProvider.cs | `src/Features/Core/Portable/GenerateConstructors/` | ソース | リファクタリングプロバイダーの基底クラス |
| AbstractGenerateConstructorsCodeRefactoringProvider.State.cs | `src/Features/Core/Portable/GenerateConstructors/` | ソース | 状態管理 |
| AbstractGenerateConstructorsCodeRefactoringProvider.FieldDelegatingCodeAction.cs | `src/Features/Core/Portable/GenerateConstructors/` | ソース | フィールド初期化CodeAction |
| AbstractGenerateConstructorsCodeRefactoringProvider.ConstructorDelegatingCodeAction.cs | `src/Features/Core/Portable/GenerateConstructors/` | ソース | 委譲コンストラクタCodeAction |
| AbstractGenerateConstructorsCodeRefactoringProvider.GenerateConstructorWithDialogCodeAction.cs | `src/Features/Core/Portable/GenerateConstructors/` | ソース | ダイアログ付きCodeAction |
| CSharpGenerateConstructorsCodeRefactoringProvider.cs | `src/Features/CSharp/Portable/GenerateConstructors/` | ソース | C#固有の実装 |
