# 機能設計書 37-using文の導入

## 概要

本ドキュメントは、Roslynの「using文の導入（Introduce Using Statement）」機能の設計仕様を記述する。この機能は、IDisposableを実装するオブジェクトをusing文（またはusing宣言）でラップするリファクタリング機能である。

### 本機能の処理概要

**業務上の目的・背景**：.NETにおいて、IDisposableを実装するオブジェクトは適切にDisposeを呼び出す必要がある。using文を使用することで、例外発生時も含めて確実にリソースが解放される。この機能は、既存のIDisposableオブジェクトを安全なusing文で囲むことを支援する。

**機能の利用シーン**：開発者がファイルストリーム、データベース接続、HTTPクライアントなどのDisposableリソースを使用する際に、既存のローカル変数宣言や式をusing文に変換したい場合に使用する。

**主要な処理内容**：
1. 選択された変数宣言または式文の検証（IDisposable実装型かどうかの判定）
2. 変数の使用範囲の特定
3. using文またはusing宣言への変換
4. 既存のtry-finally（手動Dispose）パターンの検出と変換

**関連システム・外部連携**：セマンティックモデルを使用してIDisposable実装を判定する。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | N/A | N/A | コードエディタ上のコンテキストメニューから直接実行 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 操作対象のドキュメント | null不可 |
| declarationStatement | TLocalDeclarationSyntax または TExpressionStatementSyntax | Yes | 変換対象のステートメント | IDisposable型であること |

### 入力データソース

- エディタで選択されたローカル変数宣言または式文

## 出力仕様

### 出力データ

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

### 出力先

- 対象ドキュメント（using文への変換）

## 処理フロー

### 処理シーケンス

```
1. ステートメントの取得
   └─ TryGetRelevantNodeAsync<TLocalDeclarationSyntax>または<TExpressionStatementSyntax>

2. コンテキストの検証
   └─ CanRefactorToContainBlockStatements()でブロック変換可能か確認

3. IDisposable判定
   └─ IsLegalUsingStatementType()で暗黙的変換可能か確認
   └─ ローカル変数宣言の場合: 変数の型をチェック
   └─ 式文の場合: 式の結果型をチェック

4. 変数の使用範囲特定
   └─ FindSiblingStatementContainingLastUsage()
   └─ 変数を使用する最後のステートメントまでの範囲を特定
   └─ 宣言後の変数による追加の変数も考慮

5. try-finallyパターンの検出
   └─ ShouldReplaceTryStatementWithUsing()
   └─ finally内のDisposeパターンを検出

6. using文の生成
   └─ try-finally置換の場合: tryブロックの内容をusing文に
   └─ 通常の場合: CreateUsingStatement()で生成
   └─ C# 8.0以降: TryCreateUsingLocalDeclaration()でusing宣言を検討

7. ドキュメントの更新
   └─ ReplaceWithUsingStatementAsync()
   └─ 元のステートメントと囲むステートメントを置換
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[ステートメント取得]
    B --> C{ブロック変換可能?}
    C -->|No| Z[終了]
    C -->|Yes| D{IDisposable型?}
    D -->|No| Z
    D -->|Yes| E{変数宣言?}
    E -->|Yes| F[変数名取得]
    E -->|No| G[式文として処理]
    F --> H[使用範囲特定]
    G --> I{シンプルusing優先?}
    I -->|Yes| J[using宣言生成]
    I -->|No| K[usingブロック生成]
    H --> L{try-finallyパターン?}
    L -->|Yes| M[try-finallyをusing置換]
    L -->|No| N{最後まで使用?}
    N -->|Yes| O{using宣言サポート?}
    N -->|No| P[usingブロック生成]
    O -->|Yes| Q[using宣言生成]
    O -->|No| P
    M --> R[ドキュメント更新]
    J --> R
    K --> R
    P --> R
    Q --> R
    R --> Z[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-37-01 | IDisposable必須 | System.IDisposableへの暗黙的変換が可能な型のみ対象 | 常に適用 |
| BR-37-02 | 単一宣言子 | 複数の変数宣言を含む文は対象外 | 常に適用 |
| BR-37-03 | 初期化式必須 | 初期化式を持つ変数宣言のみ対象 | 変数宣言の場合 |
| BR-37-04 | try-finally優先変換 | 手動Disposeパターン（try-finally）があれば優先的に変換 | try-finallyパターンがある場合 |
| BR-37-05 | using宣言優先 | C# 8.0以降で最後まで使用される場合はusing宣言を優先 | 言語バージョンとオプションによる |

### 計算ロジック

使用範囲特定ロジック：
```
endOfUsingStatementIndex = 0  // 初期は宣言位置

for each (宣言された変数 in 宣言順) {
    if (変数の宣言位置 > endOfUsingStatementIndex) {
        break  // using範囲外の変数なのでスキップ
    }
    // 変数の最後の使用位置でusing範囲を更新
    endOfUsingStatementIndex = max(endOfUsingStatementIndex, 変数の最後の使用位置)
}
return statementsFromDeclarationToEnd[endOfUsingStatementIndex]
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | 検証エラー | 非IDisposable型 | リファクタリングを提供しない |
| N/A | 検証エラー | 複数変数宣言 | リファクタリングを提供しない |
| N/A | 検証エラー | 初期化式なし | リファクタリングを提供しない |
| N/A | 検証エラー | ブロック変換不可 | リファクタリングを提供しない |

### リトライ仕様

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

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

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

## パフォーマンス要件

- 変数使用範囲の特定は効率的なアルゴリズムで実装
- UIのレスポンシブ性を維持するため、キャンセル可能な操作として実装

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

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

## 備考

- C# 8.0以降ではusing宣言（`using var x = ...;`）を生成可能
- try-finallyパターンはfinally内で変数.Dispose()を呼び出すパターン
- パターンベースのDispose（C# 8.0以降）は現在未サポート

---

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

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

### 推奨読解順序

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

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

**主要処理フロー**:
1. **53-134行目**: ComputeRefactoringsAsyncメソッド - ステートメントの取得と検証
2. **57-59行目**: TryGetRelevantNodeAsyncでステートメント取得
3. **64行目**: CanRefactorToContainBlockStatementsで変換可能性チェック
4. **68行目**: GetSpecialType(System_IDisposable)でIDisposable型取得
5. **74-99行目**: ローカル変数宣言の処理
6. **86-99行目**: 式文の処理
7. **103-133行目**: FindDisposableLocalDeclaration - Disposable変数の検出

#### Step 2: IDisposable判定を理解する

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

**主要処理フロー**:
- **140-144行目**: IsLegalUsingStatementType - IDisposableへの暗黙的変換チェック
- **143行目**: ClassifyCommonConversion().IsImplicitで判定

#### Step 3: using文生成を理解する

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

**主要処理フロー**:
- **146-203行目**: IntroduceUsingStatementAsync（変数宣言版）
- **162-182行目**: try-finallyパターンの検出と変換
- **185-202行目**: 通常のusing文/using宣言生成
- **205-237行目**: IntroduceUsingStatementAsync（式文版）

#### Step 4: 使用範囲特定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AbstractIntroduceUsingStatementCodeRefactoringProvider.cs | `src/Features/Core/Portable/IntroduceUsingStatement/AbstractIntroduceUsingStatementCodeRefactoringProvider.cs` | GetStatementsToSurround、FindSiblingStatementContainingLastUsage |

**主要処理フロー**:
- **314-342行目**: GetStatementsToSurround - 囲むステートメントの決定
- **344-424行目**: FindSiblingStatementContainingLastUsage - 変数の最後の使用位置検索
- **373-397行目**: ループ内での変数宣言と使用の追跡
- **405-420行目**: using範囲の決定ロジック

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

```
AbstractIntroduceUsingStatementCodeRefactoringProvider.ComputeRefactoringsAsync
    │
    ├─ TryGetRelevantNodeAsync
    │
    ├─ CanRefactorToContainBlockStatements (abstract)
    │
    ├─ GetSpecialType(System_IDisposable)
    │
    ├─ [ローカル変数宣言] FindDisposableLocalDeclaration
    │      ├─ IVariableDeclarationGroupOperation解析
    │      └─ IsLegalUsingStatementType
    │
    └─ [式文] IsLegalUsingStatementType
           │
           └─ CodeAction.Create
                  │
                  └─ IntroduceUsingStatementAsync
                         │
                         ├─ GetSurroundingStatements
                         │
                         ├─ [try-finallyパターン] ShouldReplaceTryStatementWithUsing
                         │      └─ CreateUsingStatement
                         │
                         ├─ [using宣言] TryCreateUsingLocalDeclaration (abstract)
                         │
                         └─ [usingブロック]
                                ├─ GetStatementsToSurround
                                │      └─ FindSiblingStatementContainingLastUsage
                                │             └─ AddReferencedLocalVariables
                                ├─ CreateUsingStatement (abstract)
                                └─ ReplaceWithUsingStatementAsync
```

### データフロー図

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

変数宣言/式文 ─────────▶ AbstractIntroduceUsingStatementCodeRefactoringProvider
                                 │
                                 ▼
                        IDisposable判定 ───▶ 型チェック結果
                                 │
                                 ▼
                        try-finally検出
                                 │
                        ┌────────┴────────┐
                        ▼                 ▼
              [パターンあり]        [パターンなし]
                        │                 │
                        ▼                 ▼
              try-finally置換    使用範囲特定
                        │                 │
                        │          ┌──────┴──────┐
                        │          ▼             ▼
                        │     [最後まで使用]  [途中まで使用]
                        │          │             │
                        │          ▼             ▼
                        │     using宣言      usingブロック
                        │          │             │
                        └──────────┴──────┬──────┘
                                          ▼
                                ReplaceWithUsingStatementAsync
                                          │
                                          ▼
                                更新されたドキュメント
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AbstractIntroduceUsingStatementCodeRefactoringProvider.cs | `src/Features/Core/Portable/IntroduceUsingStatement/` | ソース | リファクタリングプロバイダーの基底クラス |
| CSharpIntroduceUsingStatementCodeRefactoringProvider.cs | `src/Features/CSharp/Portable/IntroduceUsingStatement/` | ソース | C#固有の実装 |
| VisualBasicIntroduceUsingStatementCodeRefactoringProvider.vb | `src/Features/VisualBasic/Portable/IntroduceUsingStatement/` | ソース | VB固有の実装 |
