# 機能設計書 57-プロパティをメソッドに変換

## 概要

本ドキュメントは、Roslyn機能「プロパティをメソッドに変換」の機能設計書である。プロパティをGetXxx()/SetXxx()メソッドに変換するコードリファクタリング機能について記述する。

### 本機能の処理概要

**業務上の目的・背景**：プロパティは値の取得・設定を簡潔に表現できるが、処理が重い操作やパラメータが必要な操作には適さない。.NETガイドラインでは、計算量の多い処理やI/O操作を含む場合はメソッドを使用することを推奨している。本機能は、プロパティをメソッドに変換することで、APIの意図をより明確にし、パフォーマンス期待値を適切に伝える。

**機能の利用シーン**：
- プロパティに重い処理を追加する際にメソッドに変更したい場合
- プロパティにパラメータを追加したい場合
- レガシーなGetXxx()/SetXxx()パターンとの互換性が必要な場合
- 計算が重いことを呼び出し側に明示したい場合

**主要な処理内容**：
1. プロパティのgetterをGetXxx()メソッドに変換
2. プロパティのsetterをSetXxx(value)メソッドに変換
3. 全ての参照箇所をメソッド呼び出しに更新
4. 自動実装プロパティの場合はバッキングフィールドを生成
5. ソリューション全体での一括変換

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

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

## 関連画面

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

## 機能種別

コードリファクタリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| PropertyDeclaration | SyntaxNode | Yes | プロパティ宣言のAST | 有効なプロパティであること |
| Document | Document | Yes | 対象ドキュメント | null不可 |
| SemanticModel | SemanticModel | Yes | セマンティック情報 | null不可 |
| Solution | Solution | Yes | ソリューション | null不可（参照更新用） |

### 入力データソース

エディタ内の選択位置またはカーソル位置にあるプロパティ宣言

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| MethodDeclarations | SyntaxNode[] | 変換後のメソッド宣言（getter/setter） |
| FieldDeclaration | SyntaxNode | バッキングフィールド（自動プロパティの場合） |
| UpdatedSolution | Solution | 参照更新済みのソリューション |

### 出力先

エディタおよびソリューション全体（参照箇所の更新）

## 処理フロー

### 処理シーケンス

```
1. リファクタリングコンテキストの取得
   └─ カーソル位置のプロパティ宣言を特定

2. プロパティの解析
   └─ getter/setterの有無を確認
   └─ アクセサの数をカウント

3. メソッド名の決定
   └─ GetXxx（getterの場合）
   └─ SetXxx（setterの場合）
   └─ 既存メンバーとの名前衝突を確認

4. バッキングフィールドの処理
   └─ 自動プロパティの場合: 新規フィールドを生成
   └─ バッキングフィールドがある場合: そのまま使用

5. 参照の検索と更新
   └─ SymbolFinderで全参照を検索
   └─ 読み取りをGetXxx()呼び出しに変換
   └─ 書き込みをSetXxx(value)呼び出しに変換

6. ドキュメントの更新
   └─ プロパティをメソッドに置換
   └─ バッキングフィールドを追加
   └─ 全参照箇所を更新
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[プロパティ宣言を取得]
    B --> C[getter/setterを解析]
    C --> D{自動プロパティ?}
    D -->|Yes| E[バッキングフィールドを生成]
    D -->|No| F[既存フィールドを使用]
    E --> G[メソッド名を決定]
    F --> G
    G --> H[全参照を検索]
    H --> I[参照をメソッド呼び出しに更新]
    I --> J[プロパティをメソッドに置換]
    J --> K[ソリューション更新]
    K --> L[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-57-01 | Get/Setプレフィックス | Xxx → GetXxx/SetXxxの命名変換 | メソッド名生成時 |
| BR-57-02 | アクセサ数でメッセージ変更 | 1つ："method"、2つ："methods" | UI表示時 |
| BR-57-03 | バッキングフィールド生成 | 自動プロパティの場合は新規フィールド生成 | 自動プロパティ時 |
| BR-57-04 | フィールド名生成 | プロパティ名をcamelCaseに変換 | フィールド生成時 |
| BR-57-05 | 暗黙的参照警告 | 暗黙的参照は警告アノテーション追加 | 参照更新時 |
| BR-57-06 | 更新不可参照警告 | メンバー初期化子等は警告追加 | 参照更新時 |

### 計算ロジック

- メソッド名生成: `Xxx` → `GetXxx` / `SetXxx`
- フィールド名生成: `Xxx` → `xxx`（先頭小文字化）

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 警告 | 暗黙的参照あり | ConflictAnnotation追加 |
| - | 警告 | 更新不可位置の参照 | ConflictAnnotation追加 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 全参照の検索が必要なため、大規模ソリューションでは時間がかかる可能性あり
- SymbolFinderによる非同期参照検索

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

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

## 備考

- インターフェースプロパティの場合は抽象メンバーとして生成
- 逆方向の変換（メソッド → プロパティ）は「メソッドをプロパティに変換」機能で提供

---

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

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

### 推奨読解順序

#### Step 1: サービスインターフェースを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IReplacePropertyWithMethodsService.cs | `src/Features/Core/Portable/ReplacePropertyWithMethods/` | 言語サービスインターフェース |

**読解のコツ**: GetPropertyDeclarationAsync, ReplaceReferenceAsync, GetReplacementMembersAsync等の抽象メソッドを理解する。

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

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

**主要処理フロー**:
1. **38-69行目**: ComputeRefactoringsAsyncでプロパティを解析
2. **55-61行目**: アクセサ数に応じたリソース文字列の選択
3. **71-113行目**: ReplacePropertyWithMethodsAsyncでメソッド生成と参照更新
4. **115-126行目**: CreateDefinitionToBackingFieldMapでバッキングフィールドマッピング
5. **153-178行目**: GetBackingFieldでバッキングフィールドの取得・生成
6. **191-290行目**: UpdateReferencesAsyncで参照の更新
7. **293-390行目**: ReplaceDefinitionsWithMethodsAsyncでプロパティをメソッドに置換

**読解のコツ**: ReferencesByDocumentへのグループ化と、ドキュメントごとの更新処理を理解する。

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

```
ComputeRefactoringsAsync
    │
    ├─ GetPropertyDeclarationAsync
    │      └─ プロパティ宣言の取得
    │
    ├─ GetDeclaredSymbol
    │      └─ プロパティシンボルの取得
    │
    └─ ReplacePropertyWithMethodsAsync
           ├─ SymbolFinder.FindReferencesAsync
           │      └─ 全参照の検索
           ├─ CreateDefinitionToBackingFieldMap
           │      └─ バッキングフィールドマッピング
           ├─ UpdateReferencesAsync
           │      └─ ReplaceReferenceAsync
           └─ ReplaceDefinitionsWithMethodsAsync
                  └─ GetReplacementMembersAsync
```

### データフロー図

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

Property ───▶ GetPropertyDeclarationAsync ───▶ IPropertySymbol
                      │
                      ▼
IPropertySymbol ───▶ GetBackingField ───▶ IFieldSymbol (または新規生成)
                      │
                      ▼
(IPropertySymbol, IFieldSymbol) ───▶ GetReplacementMembersAsync ───▶ Methods + Field
                      │
                      ▼
Methods ───▶ UpdateReferencesAsync ───▶ Updated Solution
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ReplacePropertyWithMethodsCodeRefactoringProvider.cs | `src/Features/Core/Portable/ReplacePropertyWithMethods/` | ソース | メイン処理クラス |
| IReplacePropertyWithMethodsService.cs | `src/Features/Core/Portable/ReplacePropertyWithMethods/` | ソース | 言語サービスインターフェース |
