# 通知設計書 9-OnAfterGlobalSymbolRenamed

## 概要

本ドキュメントは、Roslynプロジェクトにおける`OnAfterGlobalSymbolRenamed`通知メソッドの設計仕様を記載するものである。このメソッドは、シンボル名変更（リネーム）操作がワークスペースに適用された後に発火する通知であり、関連サービスへの事後通知とエラー報告を行う機能を提供する。

### 本通知の処理概要

`OnAfterGlobalSymbolRenamed`は、`IRefactorNotifyService`インターフェースの`TryOnAfterGlobalSymbolRenamed`メソッドとして定義されており、シンボル名変更がワークスペースに適用された後に関連するサービスへ通知を送信する。この通知により、XAMLファイルなどの関連ファイルの更新を完了させ、変更の成功/失敗を報告できる。

**業務上の目的・背景**：シンボル名変更がワークスペースに適用された後、XAMLファイルやその他の関連ファイルも同様に更新する必要がある。`OnBeforeGlobalSymbolRenamed`で事前確認を行った後、実際の変更適用後にこの通知が送信され、関連サービスは自身の管理するファイルを更新する。更新に失敗した場合は、ログ記録やユーザーへの通知を行うことで、部分的な更新状態をユーザーに認識させる。

**通知の送信タイミング**：シンボル名変更がワークスペースに適用され、Roslynが管理するドキュメントの更新が完了した直後に送信される。具体的には、InlineRename完了時、RenameTracking確定時、およびシンボル名変更コードアクション実行完了後に呼び出される。

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

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

**期待されるアクション**：通知を受け取ったサービスは、自身が管理する関連ファイル（XAMLなど）を更新する。更新が成功すればtrueを返し、失敗した場合はthrowOnFailureフラグに応じてfalseを返すか例外をスローして、エラーを報告する。

## 通知種別

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

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（リネーム操作の事後処理） |
| リトライ | 無し（成功/失敗の即時判定） |

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

MEFでエクスポートされたすべての`IRefactorNotifyService`実装に対して順次通知が送信される。1つでもfalseを返すか例外をスローした場合、エラーが報告されるが、ワークスペースの変更はすでに適用済みであり、ロールバックは行われない。

## 通知テンプレート

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

```csharp
bool TryOnAfterGlobalSymbolRenamed(
    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完了後 | ワークスペース変更適用完了 | インライン名前変更の適用後 |
| 画面操作 | RenameTrackingコードアクション実行後 | ワークスペース変更適用完了 | 名前追跡からのリネーム適用後 |
| コードアクション | Renameコードアクション実行後 | ワークスペース変更適用完了 | リファクタリングメニューからのリネーム適用後 |
| API | SymbolRenamedCodeActionOperation実行後 | ワークスペース変更適用完了 | シンボルリネームコードアクション操作適用後 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| TryOnBeforeGlobalSymbolRenamedがfalseを返した場合 | 事前通知で拒否された場合、ワークスペース変更が適用されないため事後通知も送信されない |
| changedDocumentIDsが空の場合 | 変更対象ドキュメントがない場合はサービスへの通知をスキップ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ワークスペースにリネーム変更を適用] --> B[TryOnAfterGlobalSymbolRenamedを呼び出し]
    B --> C{changedDocumentIDsが空?}
    C -->|Yes| D[通知スキップ、trueを返す]
    C -->|No| E[すべてのIRefactorNotifyServiceを取得]
    E --> F[各サービスにTryOnAfterGlobalSymbolRenamedを呼び出し]
    F --> G{すべてのサービスがtrueを返した?}
    G -->|Yes| H[リネーム操作成功として完了]
    G -->|No| I{throwOnFailure?}
    I -->|Yes| J[例外をスロー]
    I -->|No| K[falseを返す エラーをログ]
    D --> H
    J --> L[エラー報告]
    K --> L
    H --> M[終了]
    L --> M
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| N/A | - | データベースへの更新なし（関連ファイルの更新は各サービスの責務） |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 関連ファイル更新失敗 | XAMLファイル等の更新に失敗した場合 | エラーをログ記録し、ユーザーに通知。ワークスペース変更はロールバックされない |
| 例外スロー | throwOnFailure=trueでサービスが失敗した場合 | 例外を伝播させてエラーを報告 |
| HRESULTエラー | Visual StudioのIVsHierarchyRefactorNotifyが負の値を返した場合 | Marshal.ThrowExceptionForHRまたはfalseを返す |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

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

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

- シンボル名は開発者が入力した内容であり、信頼される
- ワークスペースとドキュメントIDはシステム内部で管理される安全な識別子
- 外部サービス（XAML言語サービスなど）への通知は信頼されたコンポーネント間の通信
- ワークスペース変更はすでに適用済みのため、事後通知の失敗は部分的な更新状態を引き起こす可能性がある

## 備考

- `TryOnBeforeGlobalSymbolRenamed`とペアで使用される
- `OnBefore`がtrueを返した場合のみ呼び出されるべき（インターフェースドキュメントで明記）
- Visual Studio環境では`IVsHierarchyRefactorNotify.OnGlobalSymbolRenamed`を呼び出す（メソッド名が異なる点に注意）
- 拡張メソッド`IRefactorNotifyServiceExtensions.TryOnAfterGlobalSymbolRenamed`でサービス一覧への一括通知を簡略化
- 事後通知の失敗はワークスペースの状態に影響しないが、関連ファイルとの不整合を引き起こす可能性がある

---

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

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

### 推奨読解順序

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

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

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

**読解のコツ**: ドキュメントコメントに「This should only be called if TryOnBeforeGlobalSymbolRenamed was called and returned true」と記載されていることに注目。

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

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

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

**主要処理フロー**:
1. **行72-74**: UIスレッドでの実行を確認
2. **行75-76**: TryGetRenameAPIRequiredArgumentsで必要な引数を準備
3. **行81-104**: 各IVsHierarchyRefactorNotifyに対してOnGlobalSymbolRenamedを呼び出し
4. **行89-99**: HRESULTをチェックし、失敗時はthrowOnFailureに応じて処理

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

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

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

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | VisualStudioSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs | `src/VisualStudio/Core/Def/Workspace/VisualStudioSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs` | コードアクション操作での呼び出しを理解する |
| 4-2 | RenameTrackingTaggerProvider.RenameTrackingCommitter.cs | `src/EditorFeatures/Core/RenameTracking/RenameTrackingTaggerProvider.RenameTrackingCommitter.cs` | RenameTrackingでの呼び出しを理解する |

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

```
ワークスペースにリネーム変更適用完了
    │
    └─ IRefactorNotifyServiceExtensions.TryOnAfterGlobalSymbolRenamed()
           │
           ├─ foreach (IRefactorNotifyService service)
           │      │
           │      └─ service.TryOnAfterGlobalSymbolRenamed()
           │             │
           │             ├─ VsRefactorNotifyService (Visual Studio)
           │             │      │
           │             │      └─ IVsHierarchyRefactorNotify.OnGlobalSymbolRenamed()
           │             │             │
           │             │             └─ 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` | ソース | 一括通知の拡張メソッド |
| VisualStudioSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs | `src/VisualStudio/Core/Def/Workspace/VisualStudioSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs` | ソース | コードアクション操作での呼び出し元 |
| RenameTrackingTaggerProvider.RenameTrackingCommitter.cs | `src/EditorFeatures/Core/RenameTracking/RenameTrackingTaggerProvider.RenameTrackingCommitter.cs` | ソース | RenameTrackingでの呼び出し元 |
| RazorRefactorNotifyWrapper.cs | `src/Tools/ExternalAccess/Razor/Features/RazorRefactorNotifyWrapper.cs` | ソース | Razor向けラッパー |
