# 通知設計書 8-OnBeforeGlobalSymbolRenamed

## 概要

本ドキュメントは、Roslynプロジェクトにおける`OnBeforeGlobalSymbolRenamed`通知メソッドの設計仕様を記載するものである。このメソッドは、シンボル名変更（リネーム）操作が実行される前に発火する通知であり、リスナーがリネーム操作のキャンセルを要求できる機能を提供する。

### 本通知の処理概要

`OnBeforeGlobalSymbolRenamed`は、`IRefactorNotifyService`インターフェースの`TryOnBeforeGlobalSymbolRenamed`メソッドとして定義されており、シンボル名変更が実行される前に関連するサービスへ通知を送信する。この通知により、XAMLファイルなどの関連ファイルを更新する必要があるサービスが事前に通知を受け取り、必要に応じてリネーム操作をキャンセルすることができる。

**業務上の目的・背景**：Visual Studioなどの開発環境では、C#コードのシンボルがXAMLファイル、リソースファイル、その他の関連ファイルから参照されていることがある。シンボル名変更時にこれらのファイルも適切に更新する必要があるが、一部のファイルは更新が困難または不可能な場合がある。事前通知により、関連サービスは変更可能性を確認し、問題がある場合はリネーム操作をキャンセルして、ユーザーに適切なフィードバックを提供できる。

**通知の送信タイミング**：ユーザーがシンボル名変更操作を開始し、変更がワークスペースに適用される直前に送信される。具体的には、InlineRename完了時、RenameTracking確定時、およびシンボル名変更コードアクション実行時に呼び出される。

**通知の受信者**：`IRefactorNotifyService`を実装するサービス。具体的には、`VsRefactorNotifyService`（Visual Studio環境）、`ContainedLanguageRefactorNotifyService`（含まれる言語）、Razorなどの外部アクセスサービスなど。

**通知内容の概要**：ワークスペース、変更対象のドキュメントID一覧、リネーム対象のシンボル、新しいシンボル名、および失敗時の例外スロー有無フラグが渡される。

**期待されるアクション**：通知を受け取ったサービスは、関連ファイルの更新可能性を確認し、問題がなければtrueを返す。問題がある場合は、throwOnFailureフラグに応じてfalseを返すか例外をスローして、リネーム操作をキャンセルさせる。

## 通知種別

アプリ内サービス通知（IRefactorNotifyService）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（リネーム操作のブロッキング確認） |
| リトライ | 無し（成功/失敗の即時判定） |

### 送信先決定ロジック

MEFでエクスポートされたすべての`IRefactorNotifyService`実装に対して順次通知が送信される。1つでもfalseを返すか例外をスローした場合、リネーム操作はキャンセルされる。

## 通知テンプレート

### メソッドシグネチャ

```csharp
bool TryOnBeforeGlobalSymbolRenamed(
    Workspace workspace,
    IEnumerable<DocumentId> changedDocumentIDs,
    ISymbol symbol,
    string newName,
    bool throwOnFailure);
```

### パラメータ

| パラメータ名 | 型 | 説明 |
|------------|---|------|
| workspace | Workspace | 現在のワークスペース |
| changedDocumentIDs | IEnumerable<DocumentId> | 変更される予定のドキュメントID一覧 |
| symbol | ISymbol | リネーム対象のシンボル |
| newName | string | 新しいシンボル名 |
| throwOnFailure | bool | 失敗時に例外をスローするかどうか |

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | - | - | メソッド通知のため添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| workspace | 対象ワークスペース | リネーム操作コンテキスト | Yes |
| changedDocumentIDs | 変更ドキュメントID | リネーム影響範囲分析結果 | Yes |
| symbol | 対象シンボル | セマンティックモデル | Yes |
| newName | 新しい名前 | ユーザー入力 | Yes |
| throwOnFailure | 例外スローフラグ | 呼び出し元設定 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | InlineRename完了 | Enterキー押下またはフォーカス移動 | インライン名前変更の確定 |
| 画面操作 | RenameTrackingコードアクション実行 | コードアクション選択 | 名前追跡からのリネーム実行 |
| コードアクション | Renameコードアクション実行 | コードアクション選択 | リファクタリングメニューからのリネーム |
| API | SymbolRenamedCodeActionOperation実行 | プログラム的なリネーム | シンボルリネームコードアクション操作 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| changedDocumentIDsが空の場合 | 変更対象ドキュメントがない場合はサービスへの通知をスキップ |
| RQName生成不可の場合 | シンボルのRQNameが生成できない場合はVisual Studioへの通知をスキップ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[リネーム操作開始] --> B[影響範囲分析]
    B --> C[changedDocumentIDsを収集]
    C --> D{changedDocumentIDsが空?}
    D -->|Yes| E[通知スキップ、trueを返す]
    D -->|No| F[すべてのIRefactorNotifyServiceを取得]
    F --> G[各サービスにTryOnBeforeGlobalSymbolRenamedを呼び出し]
    G --> H{すべてのサービスがtrueを返した?}
    H -->|Yes| I[リネーム操作を続行]
    H -->|No| J{throwOnFailure?}
    J -->|Yes| K[例外をスロー]
    J -->|No| L[falseを返す]
    I --> M[ワークスペースに変更を適用]
    K --> N[リネーム操作キャンセル]
    L --> N
    E --> M
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | - | データベースアクセスなし |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| N/A | - | データベースへの更新なし（この通知自体は事前確認のみ） |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| リネームキャンセル | サービスがfalseを返した場合 | リネーム操作を中止し、ユーザーに通知 |
| 例外スロー | throwOnFailure=trueでサービスが失敗した場合 | 例外を伝播させてリネームを中止 |
| HRESULTエラー | Visual StudioのIVsHierarchyRefactorNotifyが負の値を返した場合 | Marshal.ThrowExceptionForHRまたはfalseを返す |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（ユーザー操作起点のため） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

ユーザー操作に応じて即座に送信されるため、時間帯制限なし。

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

- シンボル名は開発者が入力した内容であり、信頼される
- ワークスペースとドキュメントIDはシステム内部で管理される安全な識別子
- 外部サービス（XAML言語サービスなど）への通知は信頼されたコンポーネント間の通信

## 備考

- `TryOnAfterGlobalSymbolRenamed`とペアで使用される
- Visual Studio環境では`IVsHierarchyRefactorNotify.OnBeforeGlobalSymbolRenamed`を呼び出す
- コンストラクタやデストラクタの場合、シンボルを含む型に変換される（RQName生成のため）
- 拡張メソッド`IRefactorNotifyServiceExtensions.TryOnBeforeGlobalSymbolRenamed`でサービス一覧への一括通知を簡略化

---

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

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

### 推奨読解順序

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

まず、インターフェース定義とメソッドシグネチャを理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IRefactorNotifyService.cs | `src/Features/Core/Portable/Rename/IRefactorNotifyService.cs` | インターフェース定義、TryOnBeforeGlobalSymbolRenamedメソッド（行22-23）を理解する |

**読解のコツ**: `TryOnBeforeGlobalSymbolRenamed`と`TryOnAfterGlobalSymbolRenamed`がペアであること、戻り値がboolでキャンセル可能なことに注目。

#### Step 2: Visual Studio実装を理解する

Visual Studio環境での具体的な実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | VsRefactorNotifyService.cs | `src/VisualStudio/Core/Def/Implementation/VsRefactorNotifyService.cs` | TryOnBeforeGlobalSymbolRenamedの実装（行35-70）、IVsHierarchyRefactorNotifyへの委譲を理解する |

**主要処理フロー**:
1. **行35-37**: UIスレッドでの実行を確認
2. **行38-39**: TryGetRenameAPIRequiredArgumentsで必要な引数を準備
3. **行46-64**: 各IVsHierarchyRefactorNotifyに対してOnBeforeGlobalSymbolRenamedを呼び出し
4. **行54-64**: HRESULTをチェックし、失敗時はthrowOnFailureに応じて処理

#### Step 3: 拡張メソッドを理解する

複数サービスへの一括通知を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | IRefactorNotifyServiceExtensions.cs | `src/EditorFeatures/Core/Shared/Extensions/IRefactorNotifyServiceExtensions.cs` | TryOnBeforeGlobalSymbolRenamed拡張メソッド（行12-29）、foreachで全サービスに通知を理解する |

#### Step 4: 呼び出し元を理解する

実際にこのメソッドを呼び出している箇所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AbstractEditorInlineRenameService.SymbolRenameInfo.cs | `src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.SymbolRenameInfo.cs` | InlineRenameでの呼び出しを理解する |
| 4-2 | RenameTrackingTaggerProvider.RenameTrackingCommitter.cs | `src/EditorFeatures/Core/RenameTracking/RenameTrackingTaggerProvider.RenameTrackingCommitter.cs` | RenameTrackingでの呼び出しを理解する |

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

```
リネーム操作開始（InlineRename / RenameTracking / CodeAction）
    │
    └─ IRefactorNotifyServiceExtensions.TryOnBeforeGlobalSymbolRenamed()
           │
           ├─ foreach (IRefactorNotifyService service)
           │      │
           │      └─ service.TryOnBeforeGlobalSymbolRenamed()
           │             │
           │             ├─ VsRefactorNotifyService (Visual Studio)
           │             │      │
           │             │      └─ IVsHierarchyRefactorNotify.OnBeforeGlobalSymbolRenamed()
           │             │             │
           │             │             └─ XAML言語サービス等に通知
           │             │
           │             ├─ ContainedLanguageRefactorNotifyService
           │             │
           │             └─ RazorRefactorNotifyWrapper 等
           │
           └─ 全サービスがtrue → リネーム操作続行
              いずれかがfalse → リネーム操作キャンセル
```

### データフロー図

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

workspace ─────────────────┐
                           │
changedDocumentIDs ────────┼──▶ IRefactorNotifyService
                           │          │
symbol ────────────────────┤          ├──▶ VsRefactorNotifyService
                           │          │         │
newName ───────────────────┤          │         └──▶ IVsHierarchyRefactorNotify
                           │          │                    │
throwOnFailure ────────────┘          │                    ▼
                                      │              XAML更新確認
                                      │                    │
                                      │                    ▼
                                      └──────────────▶ bool (成功/失敗)
                                                           │
                                                           ▼
                                                     リネーム続行/キャンセル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IRefactorNotifyService.cs | `src/Features/Core/Portable/Rename/IRefactorNotifyService.cs` | インターフェース | 通知サービスの契約定義 |
| VsRefactorNotifyService.cs | `src/VisualStudio/Core/Def/Implementation/VsRefactorNotifyService.cs` | ソース | Visual Studio環境の実装 |
| ContainedLanguageRefactorNotifyService.cs | `src/VisualStudio/Core/Def/Implementation/ContainedLanguageRefactorNotifyService.cs` | ソース | 含まれる言語の実装 |
| IRefactorNotifyServiceExtensions.cs | `src/EditorFeatures/Core/Shared/Extensions/IRefactorNotifyServiceExtensions.cs` | ソース | 一括通知の拡張メソッド |
| AbstractEditorInlineRenameService.SymbolRenameInfo.cs | `src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.SymbolRenameInfo.cs` | ソース | InlineRenameでの呼び出し元 |
| RenameTrackingTaggerProvider.RenameTrackingCommitter.cs | `src/EditorFeatures/Core/RenameTracking/RenameTrackingTaggerProvider.RenameTrackingCommitter.cs` | ソース | RenameTrackingでの呼び出し元 |
| RazorRefactorNotifyWrapper.cs | `src/Tools/ExternalAccess/Razor/Features/RazorRefactorNotifyWrapper.cs` | ソース | Razor向けラッパー |
| MockRefactorNotifyService.cs | `src/EditorFeatures/TestUtilities/RenameTracking/MockRefactorNotifyService.cs` | テスト | テスト用モック |
