# 機能設計書 73-括弧ペア

## 概要

本ドキュメントは、Roslynの括弧ペア（BracePairs）機能の設計を記載する。この機能は、ドキュメント内の指定されたテキスト範囲にある全ての括弧ペアを収集し、エディタやIDEの視覚化機能（例：レインボー括弧、インデントガイドなど）に提供する。

### 本機能の処理概要

**業務上の目的・背景**：複雑なコードでは、括弧のネストが深くなり、コードの構造を把握することが困難になる。括弧ペア機能は、ドキュメント内の全ての括弧ペアを効率的に収集し、エディタが視覚的なフィードバック（レインボー括弧、括弧ペアガイドラインなど）を提供するための基盤となる。この機能により、開発者はコードの階層構造を直感的に理解できる。

**機能の利用シーン**：エディタがドキュメントをスクロールしたり、表示範囲が変更されたときに呼び出される。LSP（Language Server Protocol）の`textDocument/colorPresentation`やVS Codeのブラケットペアカラーリング機能などで使用される。

**主要な処理内容**：
1. 指定されたテキスト範囲内のノードを探索
2. 各ノードから開き括弧トークンを検出
3. 対応する閉じ括弧トークンを兄弟ノード/トークンから検索
4. BracePairDataとしてペア情報を収集
5. 結果をArrayBuilderに追加

**関連システム・外部連携**：Language Server Protocol (LSP)、Visual Studioエディタ、VS Code拡張機能と連携する。

**権限による制御**：特になし。全ユーザーが利用可能な標準機能である。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コードエディタ | 主画面 | 括弧ペアのレインボー表示、インデントガイド |

## 機能種別

エディタ支援機能（視覚化データ提供）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 対象ドキュメント | null不可 |
| textSpan | TextSpan | Yes | 検索対象のテキスト範囲 | 有効な範囲 |
| bracePairs | ArrayBuilder<BracePairData> | Yes | 結果を格納するビルダー | null不可 |
| cancellationToken | CancellationToken | No | キャンセルトークン | - |

### 入力データソース

- エディタからの表示範囲情報
- ドキュメントの構文木

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Start | TextSpan | 開き括弧のテキストスパン |
| End | TextSpan | 閉じ括弧のテキストスパン |

### 出力先

- ArrayBuilder<BracePairData>に追加
- エディタの視覚化システム

## 処理フロー

### 処理シーケンス

```
1. 構文木の取得
   └─ Document.GetSyntaxRootAsyncで構文木を取得
2. スタックベースの探索開始
   └─ ルートノードをスタックにプッシュ
3. ノード/トークンの処理
   ├─ ノードの場合：指定範囲と交差するかチェックし、子をスタックに追加
   └─ トークンの場合：開き括弧かチェック
4. 開き括弧の検出
   └─ _bracePairKindsで定義された開き括弧トークン種別と照合
5. 閉じ括弧の検索
   └─ 親ノードの兄弟トークンから対応する閉じ括弧を検索
6. ペアの追加
   └─ BracePairData(Start, End)をbuilderに追加
```

### フローチャート

```mermaid
flowchart TD
    A[AddBracePairsAsync開始] --> B[構文木取得]
    B --> C[ルートをスタックにプッシュ]
    C --> D{スタックに要素あり?}
    D -->|No| E[終了]
    D -->|Yes| F[要素をポップ]
    F --> G{ノード?}
    G -->|Yes| H{範囲と交差?}
    H -->|No| D
    H -->|Yes| I[子をスタックに追加]
    I --> D
    G -->|No| J{開き括弧トークン?}
    J -->|No| D
    J -->|Yes| K[閉じ括弧を検索]
    K --> L{発見?}
    L -->|No| D
    L -->|Yes| M[BracePairDataを追加]
    M --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-73-1 | 範囲フィルタリング | 指定されたtextSpanと交差するノードのみ処理 | 常時 |
| BR-73-2 | 標準括弧対応 | 波括弧、角括弧、丸括弧、山括弧の4種類に対応 | 常時 |
| BR-73-3 | 深さ優先探索 | スタックを使用した深さ優先探索で効率的に処理 | 常時 |
| BR-73-4 | 言語抽象化 | ISyntaxKindsを使用して言語に依存しない実装 | 常時 |

### 計算ロジック

括弧ペアマッピング:
- OpenBraceToken → CloseBraceToken
- OpenBracketToken → CloseBracketToken
- OpenParenToken → CloseParenToken
- LessThanToken → GreaterThanToken

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

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

データベース操作なし。メモリ上のドキュメントモデルに対する操作のみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | CancellationException | ユーザーがキャンセル | 処理中断 |

### リトライ仕様

リトライなし。失敗時は空の結果となる。

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

トランザクションなし。読み取り専用操作。

## パフォーマンス要件

- 大規模ドキュメントでも効率的に動作
- 範囲フィルタリングにより不要なノード探索をスキップ
- SharedPools.Defaultを使用してメモリ割り当てを最小化

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

特になし。ローカルの読み取り専用操作のみ。

## 備考

- C#とVisual Basicの両言語で利用可能
- 括弧マッチング（No.72）とは異なり、指定範囲内の全ペアを収集
- LSPのセマンティックトークン機能で活用可能

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、括弧ペアで使用されるデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IBracePairsService.cs | `src/Features/Core/Portable/BracePairs/IBracePairsService.cs` | BracePairData record structの定義を確認 |

**読解のコツ**:
- **16-18行目**: `BracePairData`はStartとEndの2つのTextSpanを保持するrecord struct

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | IBracePairsService.cs | `src/Features/Core/Portable/BracePairs/IBracePairsService.cs` | ILanguageServiceを継承したサービスインターフェース |

**主要処理フロー**:
- **20-23行目**: `IBracePairsService`インターフェース定義
- **22行目**: `AddBracePairsAsync` - 括弧ペアを収集するメインメソッド

#### Step 3: 抽象実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | IBracePairsService.cs | `src/Features/Core/Portable/BracePairs/IBracePairsService.cs` | AbstractBracePairsServiceの実装 |

**主要処理フロー**:
- **27行目**: `_bracePairKinds`ディクショナリで開き括弧→閉じ括弧のマッピングを保持
- **29-44行目**: コンストラクタでISyntaxKindsから括弧ペアを登録
- **46-86行目**: `AddBracePairsAsync` - スタックベースの深さ優先探索
- **56-57行目**: スタックにプッシュして探索開始
- **58-68行目**: ノードの場合は範囲チェックと子の追加
- **70-83行目**: トークンの場合は開き括弧チェックと閉じ括弧検索

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

```
エディタ/LSP
    │
    └─ IBracePairsService.AddBracePairsAsync
           │
           ├─ Document.GetSyntaxRootAsync
           │
           ├─ SharedPools.Default<Stack<SyntaxNodeOrToken>>().GetPooledObject
           │
           └─ スタックベース深さ優先探索
                  │
                  ├─ ノード処理：span.IntersectsWith(textSpan)
                  │      └─ child.ChildNodesAndTokens().Reverse()
                  │
                  └─ トークン処理：_bracePairKinds.TryGetValue
                         └─ parent.ChildNodesAndTokens() で閉じ括弧検索
```

### データフロー図

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

Document        ───▶ GetSyntaxRootAsync          ───▶ SyntaxNode (root)
TextSpan        ───▶
                      │
                      ▼
              スタックベース探索
                      │
                      ├─ ノード：範囲フィルタリング
                      │
                      └─ トークン：括弧ペア検出
                             │
                             ▼
              BracePairData(Start, End)          ───▶ ArrayBuilder<BracePairData>
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IBracePairsService.cs | `src/Features/Core/Portable/BracePairs/` | インターフェース・実装 | サービスインターフェースとAbstract実装 |
