# 機能設計書 133-生文字列リテラル

## 概要

本ドキュメントは、Roslynの「生文字列リテラル（RawStringLiteral）」機能の設計を記述する。この機能は、C# 11で導入された生文字列リテラル（Raw String Literal）の入力支援とエディタ機能を提供する。

### 本機能の処理概要

この機能は、生文字列リテラル（`"""`で囲まれた文字列）の入力時に、開始・終了デリミタの自動バランス調整やEnterキーでの適切なインデント処理を提供するエディタ機能である。

**業務上の目的・背景**：
C# 11で導入された生文字列リテラルは、エスケープシーケンスなしで複数行文字列やJSON/SQLなどを記述できる強力な機能である。しかし、デリミタ（`"""`）の管理が複雑になりやすい。本機能により、デリミタの自動追加・調整が行われ、開発者の入力負荷を軽減する。

**機能の利用シーン**：
- 空の通常文字列（`""`）の後にクォートを入力して生文字列を開始
- 既存の生文字列デリミタを拡張する際のクォート入力
- 生文字列内でEnterキーを押下した際のインデント処理
- 内容にクォートが含まれる場合のデリミタ自動拡張

**主要な処理内容**：
1. クォート文字入力時の自動補完判定
2. 空の通常文字列から生文字列への変換（`""` → `"""""""`）
3. 既存生文字列デリミタの自動拡張
4. Enterキー押下時の適切なインデント挿入
5. 閉じデリミタの自動追加

**関連システム・外部連携**：
- Visual Studioエディタ：ICommandHandler実装
- ITextUndoHistoryRegistry：Undo操作対応
- IEditorOperationsFactoryService：エディタ操作

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | エディタウィンドウ | 主画面 | 文字入力時の自動補完処理 |

## 機能種別

エディタ入力支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 編集中のドキュメント | null不可 |
| text | SourceText | Yes | 現在のソーステキスト | null不可 |
| caretPosition | int | Yes | キャレット位置 | 0以上 |

### 入力データソース

- エディタからのキー入力イベント
- 現在のドキュメントのSyntaxTree

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| TextChange | TextChange? | 適用すべきテキスト変更（nullの場合は処理なし） |

### 出力先

- エディタバッファへの直接変更

## 処理フロー

### 処理シーケンス

```
1. TypeChar/Return イベント受信
   └─ コマンドハンドラで処理開始
2. GetTextChangeForQuote呼び出し
   └─ 言語サービスで変更内容を計算
3. 変換パターン判定
   └─ 3つの変換パターンを順次チェック
4. TextChange生成
   └─ 適用すべき変更を返却
5. エディタへの変更適用
   └─ Undoトランザクション内で実行
```

### フローチャート

```mermaid
flowchart TD
    A[クォート入力] --> B{TryGenerateInitialEmptyRawString?}
    B -->|Yes| C[開始デリミタ生成: """"""]
    B -->|No| D{TryGrowInitialEmptyRawString?}
    D -->|Yes| E[デリミタ拡張: " 追加]
    D -->|No| F{TryGrowRawStringDelimiters?}
    F -->|Yes| G[終了デリミタにも " 追加]
    F -->|No| H[通常処理]
    C --> I[TextChange返却]
    E --> I
    G --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-133-01 | 初期生成 | `""`の後に`"`入力で`""""""`に変換 | 空の通常文字列の後 |
| BR-133-02 | 偶数クォート必須 | デリミタのクォート数は偶数（開始+終了） | 初期空生文字列 |
| BR-133-03 | 最小3クォート | 生文字列は最低3つのクォートで開始 | すべての生文字列 |
| BR-133-04 | バランス維持 | 開始デリミタ拡張時は終了も拡張 | 内容にクォートがある場合 |

### 計算ロジック

デリミタ拡張判定:
- 現在位置の前後のクォート数をカウント
- クォート数が偶数かつ位置が中央にあるか確認
- トークン種別がRawStringLiteral系であることを確認

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

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

データベース操作なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | パース失敗 | SyntaxTreeが取得できない | nullを返却（通常処理にフォールバック） |
| - | トークン不一致 | 期待するトークン種別でない | nullを返却 |

### リトライ仕様

リトライは行わない。

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

ITextUndoHistoryを使用したUndo対応。単一のUndo操作として記録。

## パフォーマンス要件

- キー入力の応答性を損なわない（同期処理）
- GetRequiredSyntaxRootSynchronouslyで同期的にSyntaxRoot取得

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

特になし。

## 備考

- C# 11以降の機能
- 補間生文字列（$"""）にも対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IRawStringLiteralAutoInsertService.cs | `src/Features/Core/Portable/RawStringLiteral/` | サービスインターフェース定義 |

**読解のコツ**: `GetTextChangeForQuote`メソッドがクォート入力時の変更を計算する唯一のエントリーポイント。

#### Step 2: C#実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CSharpRawStringLiteralOnAutoInsertService.cs | `src/Features/CSharp/Portable/RawStringLiteral/` | C#固有の実装 |

**主要処理フロー**:
1. **21-27行目**: GetTextChangeForQuoteで3パターンを順次試行
2. **33-72行目**: TryGenerateInitialEmptyRawString - 空文字列から生文字列への変換
3. **80-124行目**: TryGrowInitialEmptyRawString - 空の生文字列のデリミタ拡張
4. **131-176行目**: TryGrowRawStringDelimiters - 内容ありの生文字列のデリミタ拡張

#### Step 3: コマンドハンドラを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RawStringLiteralCommandHandler.cs | `src/EditorFeatures/CSharp/RawStringLiteral/` | コマンドハンドラ登録 |
| 3-2 | RawStringLiteralCommandHandler_TypeChar.cs | `src/EditorFeatures/CSharp/RawStringLiteral/` | TypeChar処理 |
| 3-3 | RawStringLiteralCommandHandler_Return.cs | `src/EditorFeatures/CSharp/RawStringLiteral/` | Return処理 |

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

```
RawStringLiteralCommandHandler
    │
    ├─ TypeCharCommandHandler
    │      └─ IRawStringLiteralAutoInsertService.GetTextChangeForQuote
    │             ├─ TryGenerateInitialEmptyRawString
    │             ├─ TryGrowInitialEmptyRawString
    │             └─ TryGrowRawStringDelimiters
    │
    └─ ReturnCommandHandler
           └─ 改行とインデント処理
```

### データフロー図

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

キー入力(") ───▶ GetTextChangeForQuote ───▶ TextChange?
     │                    │
     │                    ├─ TryGenerateInitialEmptyRawString
SourceText               │      └─ TextChange: "\"\"\""
     │                    ├─ TryGrowInitialEmptyRawString
     │                    │      └─ TextChange: "\""
     │                    └─ TryGrowRawStringDelimiters
     │                           └─ TextChange: "\""
     ▼
エディタバッファ更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IRawStringLiteralAutoInsertService.cs | `src/Features/Core/Portable/RawStringLiteral/` | ソース | サービスインターフェース |
| CSharpRawStringLiteralOnAutoInsertService.cs | `src/Features/CSharp/Portable/RawStringLiteral/` | ソース | C#実装 |
| RawStringLiteralCommandHandler.cs | `src/EditorFeatures/CSharp/RawStringLiteral/` | ソース | コマンドハンドラ定義 |
| RawStringLiteralCommandHandler_TypeChar.cs | `src/EditorFeatures/CSharp/RawStringLiteral/` | ソース | 文字入力処理 |
| RawStringLiteralCommandHandler_Return.cs | `src/EditorFeatures/CSharp/RawStringLiteral/` | ソース | Enter処理 |
