# 機能設計書 72-括弧マッチング

## 概要

本ドキュメントは、Roslynの括弧マッチング（BraceMatching）機能の設計を記載する。この機能は、エディタ上でカーソルが括弧に位置したとき、対応するペアの括弧をハイライト表示することで、コードの構造を視覚的に把握しやすくする。

### 本機能の処理概要

**業務上の目的・背景**：複雑なネストを持つコードでは、どの開き括弧がどの閉じ括弧に対応するのかを把握することが困難になる。括弧マッチング機能は、この問題を解決し、コードの可読性と保守性を向上させる。特に、深くネストされた条件文、ループ、メソッド呼び出しなどで、開発者がコードの構造を素早く理解できるよう支援する。

**機能の利用シーン**：コードエディタでカーソルを括弧（`{`、`}`、`(`、`)`、`[`、`]`、`<`、`>`など）の位置に移動したとき、対応する括弧がハイライト表示される。これにより、コードブロックの範囲やメソッド呼び出しの引数範囲などが視覚的に明確になる。

**主要な処理内容**：
1. カーソル位置の括弧トークンを検出
2. 対応するペア括弧を構文木から検索
3. 両括弧のテキストスパンを返却
4. エディタでのハイライト表示に利用

**関連システム・外部連携**：Visual Studioエディタ、Language Server Protocol (LSP)、エディタのカーソル位置変更通知システムと連携する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コードエディタ | 主画面 | カーソル位置の括弧ペアをハイライト表示 |

## 機能種別

エディタ支援機能（視覚的フィードバック）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 対象ドキュメント | null不可 |
| position | int | Yes | カーソル位置 | 0以上、ドキュメント長以下 |
| options | BraceMatchingOptions | Yes | マッチングオプション | - |
| cancellationToken | CancellationToken | No | キャンセルトークン | - |

### 入力データソース

- エディタからのカーソル位置変更イベント
- ドキュメントの構文木

## 出力仕様

### 出力データ

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

### 出力先

- エディタのハイライト表示システム
- BraceMatchingResult構造体として返却

## 処理フロー

### 処理シーケンス

```
1. カーソル位置の取得
   └─ エディタからのイベントでposition取得
2. 位置の妥当性検証
   └─ 0以上、ドキュメント長以下かチェック
3. 言語に応じたマッチャー選択
   └─ MEFで登録されたIBraceMatcherから選択
4. 括弧トークンの検出
   └─ FindToken(position)で現在位置のトークン取得
5. マッチング実行
   └─ 開き括弧の場合：対応する閉じ括弧を検索
   └─ 閉じ括弧の場合：対応する開き括弧を検索
6. 結果返却
   └─ BraceMatchingResult(LeftSpan, RightSpan)を返却
```

### フローチャート

```mermaid
flowchart TD
    A[カーソル位置変更] --> B{位置は有効?}
    B -->|No| C[null返却]
    B -->|Yes| D[トークン取得]
    D --> E{括弧文字?}
    E -->|No| C
    E -->|Yes| F{開き括弧?}
    F -->|Yes| G[閉じ括弧を検索]
    F -->|No| H[開き括弧を検索]
    G --> I{マッチ発見?}
    H --> I
    I -->|No| C
    I -->|Yes| J[BraceMatchingResult返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-72-1 | 親ノード内検索 | 括弧ペアは同一の親ノード内で検索する | 常時 |
| BR-72-2 | 2トークンペア | 親ノード内に開き括弧と閉じ括弧が正確に2つある場合のみマッチ | 常時 |
| BR-72-3 | 長さゼロ除外 | 長さ0のスパンを持つトークンは除外 | 常時 |
| BR-72-4 | 埋め込み言語対応 | 文字列内のRegexやJSON等の埋め込み言語もマッチング対象 | 埋め込み言語サポート有効時 |

### 計算ロジック

マッチング検索ロジック:
- 親ノードの子ノード/トークンから、開き括弧と閉じ括弧のKindを持つトークンを抽出
- 正確に2つ見つかり、それぞれが開き/閉じ括弧である場合にマッチとして返却

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentException | 無効な位置指定 | 例外スロー |
| - | CancellationException | ユーザーがキャンセル | 処理中断 |

### リトライ仕様

リトライなし。失敗時はnullを返却し、ハイライトなしとなる。

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

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

## パフォーマンス要件

- カーソル移動からの応答時間: リアルタイム（数ミリ秒以内）
- 構文木のキャッシュを活用し、毎回パースしない

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

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

## 備考

- C#とVisual Basicの両言語で利用可能
- ディレクティブトリビア（#region/#endregionなど）のマッチングもサポート
- 埋め込み言語（Regex、JSONなど）のブレースマッチングも拡張可能

---

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

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

### 推奨読解順序

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

まず、括弧マッチングで使用されるデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IBraceMatchingService.cs | `src/Features/Core/Portable/BraceMatching/IBraceMatchingService.cs` | BraceMatchingResult構造体の定義を確認 |

**読解のコツ**:
- **17-20行目**: `BraceMatchingResult`はLeftSpanとRightSpanの2つのTextSpanを保持するrecord struct
- DataContract属性により、シリアライズ可能

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | IBraceMatchingService.cs | `src/Features/Core/Portable/BraceMatching/IBraceMatchingService.cs` | サービスインターフェースの役割を把握 |
| 2-2 | IBraceMatcher.cs | `src/Features/Core/Portable/BraceMatching/IBraceMatcher.cs` | 個別マッチャーのインターフェース |

**主要処理フロー**:
- **14行目**: `GetMatchingBracesAsync` - 非同期でマッチング括弧を取得

#### Step 3: サービス実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | BraceMatchingService.cs | `src/Features/Core/Portable/BraceMatching/BraceMatchingService.cs` | MEFによるサービス実装 |

**主要処理フロー**:
- **19-20行目**: コンストラクタでIBraceMatcherのコレクションを受け取る
- **24-44行目**: `GetMatchingBracesAsync` - 言語に応じたマッチャーを順に試行し、最初にマッチしたものを返却
- **32行目**: 言語フィルタリング（document.Project.Language）

#### Step 4: 抽象マッチャーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AbstractBraceMatcher.cs | `src/Features/Core/Portable/BraceMatching/AbstractBraceMatcher.cs` | 共通マッチングロジック |
| 4-2 | BraceCharacterAndKind.cs | `src/Features/Core/Portable/BraceMatching/BraceCharacterAndKind.cs` | 括弧文字とトークン種別のペア |

**主要処理フロー**:
- **16-17行目**: 開き括弧と閉じ括弧のBraceCharacterAndKindを保持
- **27-56行目**: `TryFindMatchingToken` - 親ノード内から対応する括弧を検索
- **58-89行目**: `FindBracesAsync` - メインのマッチング処理
- **94-95行目**: `IsBrace` - 文字が開き/閉じ括弧かを判定

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

```
エディタ（カーソル位置変更イベント）
    │
    └─ IBraceMatchingService.GetMatchingBracesAsync
           │
           ├─ Document.GetValueTextAsync
           │
           └─ IBraceMatcher.FindBracesAsync（各言語のマッチャー）
                  │
                  ├─ Document.GetSyntaxRootAsync
                  │
                  ├─ SyntaxNode.FindToken(position)
                  │
                  └─ TryFindMatchingToken
                         └─ 親ノードの子トークンをスキャン
```

### データフロー図

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

カーソル位置    ───▶ BraceMatchingService         ───▶ BraceMatchingResult?
Document        ───▶ GetMatchingBracesAsync             ├─ LeftSpan
                      │                                  └─ RightSpan
                      ├─ 言語に応じたマッチャー選択
                      │
                      ├─ FindBracesAsync
                      │   ├─ トークン取得
                      │   └─ ペア検索
                      │
                      └─ 結果返却
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IBraceMatchingService.cs | `src/Features/Core/Portable/BraceMatching/` | インターフェース | サービスインターフェースと結果型定義 |
| BraceMatchingService.cs | `src/Features/Core/Portable/BraceMatching/` | 実装 | MEFエクスポートされたサービス実装 |
| IBraceMatcher.cs | `src/Features/Core/Portable/BraceMatching/` | インターフェース | 個別マッチャーのインターフェース |
| AbstractBraceMatcher.cs | `src/Features/Core/Portable/BraceMatching/` | 抽象クラス | 共通マッチングロジック |
| BraceCharacterAndKind.cs | `src/Features/Core/Portable/BraceMatching/` | データ型 | 括弧文字とトークン種別のペア |
| BraceMatchingOptions.cs | `src/Features/Core/Portable/BraceMatching/` | オプション | マッチングオプション設定 |
| ExportBraceMatcherAttribute.cs | `src/Features/Core/Portable/BraceMatching/` | 属性 | MEFエクスポート用属性 |
| AbstractDirectiveTriviaBraceMatcher.cs | `src/Features/Core/Portable/BraceMatching/` | 抽象クラス | ディレクティブトリビアのマッチング |
| IEmbeddedLanguageBraceMatcher.cs | `src/Features/Core/Portable/BraceMatching/` | インターフェース | 埋め込み言語マッチング |
| AbstractEmbeddedLanguageBraceMatcher.cs | `src/Features/Core/Portable/BraceMatching/` | 抽象クラス | 埋め込み言語マッチング共通ロジック |
| IBraceMatchingServiceExtensions.cs | `src/Features/Core/Portable/BraceMatching/` | 拡張 | サービス拡張メソッド |
