# 機能設計書 53-文字列補間に変換

## 概要

本ドキュメントは、Roslyn機能「文字列補間に変換」の機能設計書である。文字列連結やstring.Format呼び出しを補間文字列（$"..."形式）に変換するコードリファクタリング機能について記述する。

### 本機能の処理概要

**業務上の目的・背景**：文字列の構築方法として、C#では複数の選択肢（文字列連結、string.Format、StringBuilder、補間文字列）がある。補間文字列は可読性が高く、コンパイル時の最適化も効くため、現代のC#開発では推奨される形式である。本機能は、レガシーな文字列構築コードを補間文字列に変換することで、コードの可読性と保守性を向上させる。

**機能の利用シーン**：
- 古いコードベースの文字列連結を補間文字列に移行したい場合
- string.Formatのプレースホルダを直感的な形式に変換したい場合
- コードレビューでチームの推奨形式に統一したい場合
- 波括弧を含む通常文字列を補間文字列に変換したい場合

**主要な処理内容**：
1. 文字列連結（`a + " " + b`）を補間文字列（`$"{a} {b}"`）に変換
2. string.Format呼び出しを補間文字列に変換
3. 波括弧を含む通常文字列を補間文字列に変換（`{` → `{{`）
4. verbatim文字列（`@"..."`）を補間verbatim文字列（`$@"..."`）に変換
5. .ToString()呼び出しの適切な処理（不要な場合は削除）

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

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

## 関連画面

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

## 機能種別

コードリファクタリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Expression | SyntaxNode | Yes | 対象式のAST | 文字列連結または対象メソッド呼び出し |
| InvocationExpression | SyntaxNode | Conditional | string.Format呼び出し | 有効なFormat呼び出しであること |
| Document | Document | Yes | 対象ドキュメント | null不可 |
| SemanticModel | SemanticModel | Yes | セマンティック情報 | null不可 |

### 入力データソース

エディタ内の選択位置またはカーソル位置にある文字列連結式またはstring.Format呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| InterpolatedString | SyntaxNode | 変換後の補間文字列 |
| UpdatedDocument | Document | 更新後のドキュメント |

### 出力先

エディタ（ソースコードの置換）

## 処理フロー

### 処理シーケンス

```
1. リファクタリングコンテキストの取得
   └─ カーソル位置のノードを特定

2. 対象の検証
   └─ 文字列連結の場合: IsStringConcatで検証
   └─ メソッド呼び出しの場合: string.Format呼び出しかを検証

3. 連結要素の収集
   └─ CollectPiecesDownで各部分を収集
   └─ 文字列リテラルの種類を確認（通常/verbatim）

4. 補間文字列の構築
   └─ 文字列リテラル部分をテキストノードに変換
   └─ 式部分を補間ノードに変換
   └─ 波括弧をエスケープ

5. ドキュメントの更新
   └─ 元の式を補間文字列で置換
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{入力の種類}
    B -->|文字列連結| C[連結要素を収集]
    B -->|string.Format| D[引数を解析]
    B -->|通常文字列| E[波括弧有無を確認]
    C --> F{全て同種の文字列?}
    D --> G[プレースホルダを解析]
    E --> H{波括弧あり?}
    F -->|Yes| I[補間文字列を構築]
    F -->|No| J[リファクタリング提示なし]
    G --> I
    H -->|Yes| I
    H -->|No| J
    I --> K[ドキュメント更新]
    K --> L[終了]
    J --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-53-01 | 同種文字列のみ | verbatimと通常文字列の混在は変換不可 | 文字列連結時 |
| BR-53-02 | Raw文字列除外 | Raw文字列リテラルは変換対象外 | C# 11以降のRaw文字列 |
| BR-53-03 | const除外 | const宣言内の式は変換対象外 | 定数宣言時（定数補間非対応時） |
| BR-53-04 | 波括弧エスケープ | `{` → `{{`、`}` → `}}`に変換 | 補間文字列への変換時 |
| BR-53-05 | ToString削除 | 補間文字列ハンドラー対応時はToString()を削除 | .NET 6以降 |
| BR-53-06 | CultureInfo除外 | CultureInfoを含む呼び出しは変換対象外 | 書式指定がある場合 |

### 計算ロジック

- プレースホルダインデックス: 引数位置に基づいて補間式を挿入

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 変換不可 | verbatimと通常の混在 | リファクタリングを提示しない |
| - | 変換不可 | CultureInfo引数あり | リファクタリングを提示しない |
| - | パース失敗 | 補間文字列が不正になる | リファクタリングを提示しない |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 文字列連結の収集は再帰的に実行（大きな連結でもスタックオーバーフローしない設計）

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

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

## 備考

- ConstantInterpolatedStringsをサポートする言語バージョンでは、const内でも変換可能
- 補間文字列ハンドラー（C# 10）対応でToString()の自動削除が可能

---

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

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

### 推奨読解順序

#### Step 1: 文字列連結の変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs | `src/Features/Core/Portable/ConvertToInterpolatedString/` | 文字列連結→補間文字列の抽象クラス |

**主要処理フロー**:
1. **32-115行目**: ComputeRefactoringsAsyncでリファクタリング候補を計算
2. **42-48行目**: IsStringConcatで文字列連結の判定
3. **70-71行目**: CollectPiecesDownで連結要素を収集
4. **127-254行目**: CreateInterpolatedStringAsyncで補間文字列を生成

**読解のコツ**: CollectPiecesDownメソッドが二分木構造の連結式を再帰的に展開する仕組みを理解する。

#### Step 2: string.Format変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AbstractConvertPlaceholderToInterpolatedStringRefactoringProvider.cs | `src/Features/Core/Portable/ConvertToInterpolatedString/` | string.Format→補間文字列の抽象クラス |

**主要処理フロー**:
- **52-125行目**: AnalyzeInvocationでstring.Format呼び出しを解析
- **188-265行目**: FindValidPlaceholderArgumentでプレースホルダ引数を検証
- **326-424行目**: ReplaceInvocationでプレースホルダを補間式に置換

#### Step 3: 通常文字列の変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ConvertRegularStringToInterpolatedStringRefactoringProvider.cs | `src/Features/Core/Portable/ConvertToInterpolatedString/` | 通常文字列→補間文字列 |

**主要処理フロー**:
- **30-81行目**: ComputeRefactoringsAsyncでリファクタリング候補を計算
- **52-53行目**: 波括弧の有無チェック
- **90-104行目**: CreateInterpolatedStringで変換

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

```
ComputeRefactoringsAsync
    │
    ├─ IsStringConcat
    │      └─ 文字列連結の判定
    │
    ├─ CollectPiecesDown
    │      └─ 連結要素の収集（再帰）
    │
    ├─ CreateInterpolatedStringAsync
    │      ├─ InterpolatedStringText生成
    │      ├─ Interpolation生成
    │      └─ TryRemoveToString（不要なToString削除）
    │
    └─ Document.WithSyntaxRoot
           └─ ドキュメント更新
```

### データフロー図

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

"a" + b + "c" ───▶ CollectPiecesDown ───▶ ["a", b, "c"]
                          │
                          ▼
["a", b, "c"] ───▶ CreateInterpolatedString ───▶ $"a{b}c"

string.Format("{0}...", a) ───▶ AnalyzeInvocation ───▶ (format, args)
                                      │
                                      ▼
(format, args) ───▶ ReplaceInvocation ───▶ $"{a}..."
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs | `src/Features/Core/Portable/ConvertToInterpolatedString/` | ソース | 文字列連結変換の抽象プロバイダ |
| AbstractConvertPlaceholderToInterpolatedStringRefactoringProvider.cs | `src/Features/Core/Portable/ConvertToInterpolatedString/` | ソース | string.Format変換の抽象プロバイダ |
| ConvertRegularStringToInterpolatedStringRefactoringProvider.cs | `src/Features/Core/Portable/ConvertToInterpolatedString/` | ソース | 通常文字列変換プロバイダ |
