# 通知設計書 3-ShowToastNotification

## 概要

本ドキュメントは、Roslynプロジェクトにおける`ShowToastNotification`カスタムLSP通知の設計仕様を記載するものである。この通知は、Language Server Protocol（LSP）を通じてクライアント（エディタ）にトースト形式の通知を表示するためのカスタム拡張機能である。

### 本通知の処理概要

`ShowToastNotification`は、`window/_roslyn_showToast`というカスタムLSPメソッド名で定義された通知であり、Language Serverからクライアントへトースト形式の通知を非同期で送信する。標準のLSP `window/showMessageRequest`とは異なり、サーバー側でレスポンスを待機する必要がなく、クライアント側のコマンドボタンにマッピングできる点が特徴である。

**業務上の目的・背景**：LSPベースのエディタ統合において、ユーザーに重要な情報を通知しつつ、サーバー側の処理をブロックしない非同期通知が必要となる場面がある。例えば、プロジェクトのロード状況、ビルドエラーの発生、設定変更の推奨などをユーザーに伝えながら、Language Serverは他のリクエスト処理を継続できる。また、トースト通知にはコマンドボタンを含めることができ、ユーザーがクリックするとクライアント側で定義されたアクション（例：出力ウィンドウを開く）が実行される。

**通知の送信タイミング**：プロジェクトロード完了時、テレメトリレポート送信時、エラー発生時など、ユーザーへの情報提供が必要だがサーバー側で応答を待つ必要がない場面で非同期に送信される。

**通知の受信者**：LSPをサポートするエディタ（Visual Studio Code、Visual Studioなど）のクライアント。通知はクライアント側でトースト（ポップアップ通知）として表示される。

**通知内容の概要**：メッセージタイプ（Info、Warning、Error）、メッセージ本文、およびオプションのコマンドボタン配列がJSON-RPC形式で送信される。コマンドボタンにはタイトルとクライアント側コマンド識別子が含まれる。

**期待されるアクション**：ユーザーはトースト通知を確認し、必要に応じてコマンドボタンをクリックする。コマンドボタンがクリックされると、クライアント側で対応するコマンド（例：`csharp.showOutputWindow`）が実行される。

## 通知種別

LSPカスタム通知（window/_roslyn_showToast）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（Fire-and-forget） |
| 優先度 | 中（トースト通知として表示） |
| リトライ | 無し（通知は送信のみ） |

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

通知はLanguage Serverに接続しているすべてのLSPクライアントに対して送信される。クライアントの選択やフィルタリングは行われない。

## 通知テンプレート

### LSP通知パラメータ

| 項目 | 内容 |
|-----|------|
| メソッド名 | `window/_roslyn_showToast` |
| パラメータ形式 | JSON-RPC 2.0 |

### パラメータ構造

```json
{
  "messageType": 1,
  "message": "{メッセージ本文}",
  "commands": [
    {
      "title": "{ボタンラベル}",
      "commandIdentifier": "{クライアント側コマンド}"
    }
  ]
}
```

### 定義済みコマンド

| コマンド | タイトル | コマンド識別子 | 説明 |
|---------|---------|---------------|------|
| ShowCSharpLogsCommand | "Show C# logs" | `csharp.showOutputWindow` | C#出力ウィンドウを表示 |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| messageType | メッセージの種類（1:Error, 2:Warning, 3:Info, 4:Log） | LSP.MessageType列挙型 | Yes |
| message | 表示するメッセージ本文 | 呼び出し元から直接渡される | Yes |
| commands | コマンドボタンの配列 | LSP.Command配列 | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| システム処理 | プロジェクトロード開始/完了 | プロジェクトロード時 | ProjectInitializationHandlerからの通知 |
| システム処理 | テレメトリレポート送信 | テレメトリ収集時 | ProjectLoadTelemetryReporterからの通知 |
| システム処理 | ログメッセージ出力 | ログレベルがInfo以上の場合 | LspLogMessageLoggerからの通知 |
| システム処理 | エラー発生時 | 重大なエラー発生時 | 各種ハンドラからのエラー通知 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| LanguageServerHost.Instanceがnullの場合 | LSPチャンネルが確立されていない場合は送信不可（Contract.ThrowIfNullで例外） |
| クライアントが切断されている場合 | JSON-RPC接続が切断されている場合は送信失敗 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[呼び出し元がShowToastNotificationAsyncを呼び出し] --> B{LanguageServerHost.Instanceが存在するか?}
    B -->|No| C[Contract.ThrowIfNull例外]
    B -->|Yes| D[IClientLanguageServerManagerを取得]
    D --> E[ShowToastNotificationParamsを構築]
    E --> F[SendNotificationAsyncを呼び出し]
    F --> G[JSON-RPCで通知を送信]
    G --> H[終了（応答待機なし）]
    C --> I[例外処理]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | - | データベースアクセスなし（LSP通信のみ） |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| N/A | - | データベースへの更新なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| LSPホスト未初期化 | LanguageServerHost.Instanceがnullの場合 | Contract.ThrowIfNullで例外をスロー |
| JSON-RPC送信失敗 | クライアント接続が切断されている場合 | 例外は呼び出し元で処理 |
| キャンセル | CancellationTokenがキャンセルされた場合 | OperationCanceledExceptionがスロー |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（システム起点のため適切な頻度で送信） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

システムイベントに応じて即座に送信されるため、時間帯制限なし。

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

- メッセージ内容はJSON形式で送信されるため、特殊文字のエスケープが自動的に行われる
- コマンド識別子はクライアント側で事前定義されたもののみを使用すべき
- 機密情報をメッセージに含めないよう注意が必要
- クライアント側でのコマンド実行は信頼されたコマンドのみに限定すること

## 備考

- このカスタム通知は標準LSPの`window/showMessageRequest`を拡張したもの
- 標準の`window/showMessageRequest`はサーバーがレスポンスを待機する必要があるが、この通知では不要
- `ShowToastNotificationParams`はrecord型として定義され、JSONシリアライズに対応
- コマンドボタンはクライアント側のコマンドパレット機能と連携

---

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

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

### 推奨読解順序

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

まず、通知パラメータの構造とLSPインターフェースを理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ShowToastNotification.cs | `src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ShowToastNotification.cs` | ShowToastNotificationクラスの定義、ShowToastNotificationParamsレコードの構造を理解する（行35-38） |
| 1-2 | IClientLanguageServerManager.cs | `src/LanguageServer/Protocol/IClientLanguageServerManager.cs` | LSP通知送信用インターフェースの契約を理解する（行20-21） |

**読解のコツ**: `ShowToastNotificationParams`がrecord型として定義され、JsonPropertyName属性でJSONシリアライズ時のプロパティ名が指定されていることに注目。

#### Step 2: エントリーポイントを理解する

静的メソッド`ShowToastNotificationAsync`の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ShowToastNotification.cs | `src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ShowToastNotification.cs` | ShowToastNotificationAsyncメソッドの実装（行27-33）。LanguageServerHost.Instanceの取得とnullチェック |

**主要処理フロー**:
1. **行29**: LanguageServerHost.Instanceが存在することを確認（Contract.ThrowIfNull）
2. **行30**: IClientLanguageServerManagerサービスを取得
3. **行31**: ShowToastNotificationParamsを構築
4. **行32**: SendNotificationAsyncでJSON-RPC通知を送信

#### Step 3: LSP通知送信の実装を理解する

JSON-RPC通信の実装詳細を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | LanguageServerNotificationManager.cs | `src/LanguageServer/Protocol/Handler/LanguageServerNotificationManager.cs` | ClientLanguageServerManagerの実装、JsonRpcを使用した通知送信（行35-39） |

**主要処理フロー**:
- **行38-39**: `_jsonRpc.NotifyWithParameterObjectAsync`を使用してJSON-RPC通知を送信

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

実際にShowToastNotificationAsyncを呼び出している箇所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ProjectInitializationHandler.cs | `src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectInitializationHandler.cs` | プロジェクト初期化時の通知使用例 |
| 4-2 | ProjectLoadTelemetryReporter.cs | `src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectTelemetry/ProjectLoadTelemetryReporter.cs` | テレメトリレポート時の通知使用例 |
| 4-3 | LspLogMessageLogger.cs | `src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs` | ログメッセージ出力時の通知使用例 |

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

```
呼び出し元（ProjectInitializationHandler等）
    │
    └─ ShowToastNotification.ShowToastNotificationAsync()
           │
           ├─ LanguageServerHost.Instance の取得・nullチェック
           │
           ├─ IClientLanguageServerManager の取得
           │
           └─ SendNotificationAsync("window/_roslyn_showToast", params)
                  │
                  └─ ClientLanguageServerManager
                         │
                         └─ JsonRpc.NotifyWithParameterObjectAsync()
                                │
                                └─ クライアントへJSON-RPC通知送信
```

### データフロー図

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

messageType: MessageType ───┐
                            │
message: string ────────────┼──▶ ShowToastNotification ──▶ JSON-RPC Notification
                            │         │                        │
commands: Command[] ────────┘         │                        ▼
                                      ▼                   LSPクライアント
                               ShowToastNotificationParams     │
                                      │                        ▼
                                      ▼                   トースト表示
                               IClientLanguageServerManager    │
                                      │                        ▼
                                      ▼                   ユーザーアクション
                               JsonRpc.NotifyWithParameterObjectAsync
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ShowToastNotification.cs | `src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ShowToastNotification.cs` | ソース | トースト通知の静的メソッドとパラメータ定義 |
| IClientLanguageServerManager.cs | `src/LanguageServer/Protocol/IClientLanguageServerManager.cs` | インターフェース | LSP通知送信の契約定義 |
| LanguageServerNotificationManager.cs | `src/LanguageServer/Protocol/Handler/LanguageServerNotificationManager.cs` | ソース | JSON-RPCを使用した通知送信実装 |
| ProjectInitializationHandler.cs | `src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectInitializationHandler.cs` | ソース | 使用例（プロジェクト初期化） |
| ProjectLoadTelemetryReporter.cs | `src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectTelemetry/ProjectLoadTelemetryReporter.cs` | ソース | 使用例（テレメトリ） |
| LspLogMessageLogger.cs | `src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs` | ソース | 使用例（ログ出力） |
| LanguageServerResources.resx | `src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServerResources.resx` | リソース | ローカライズ文字列定義 |
