# 通知設計書 16-INotificationHandler<TRequest>

## 概要

本ドキュメントは、Roslyn Language Server Protocol（LSP）フレームワークにおける `INotificationHandler<TRequest, TRequestContext>` インターフェースの設計仕様を記述する。このインターフェースは、パラメータ付きのLSP通知を処理するためのハンドラの契約を定義する。

### 本通知の処理概要

INotificationHandler<TRequest, TRequestContext>は、Language Server Protocol（LSP）においてパラメータを持つ通知メッセージを処理するためのジェネリックインターフェースである。クライアントからサーバーへの一方向通知（レスポンスを返さないメッセージ）で、追加のパラメータ情報を含むものを受信・処理するために使用される。

**業務上の目的・背景**：LSPの多くの通知はパラメータを伴う。例えば、textDocument/didOpen通知はテキストドキュメントの内容を含み、textDocument/didChange通知は変更内容を含む。このインターフェースを実装することで、言語サーバーがこれらのパラメータ付き通知を型安全に処理できる。TRequest型パラメータにより、通知パラメータの型を厳密に定義できる。

**通知の送信タイミング**：クライアント（IDE等）がLSPプロトコルに従ってパラメータ付き通知メッセージを送信した時点で、対応するハンドラのHandleNotificationAsyncメソッドが呼び出される。通知はJSON-RPC形式でシリアライズされ、パラメータはTRequest型にデシリアライズされる。

**通知の受信者**：LSPサーバー内の登録されたINotificationHandler<TRequest, TRequestContext>実装クラス。ハンドラはLanguageServerEndpoint属性でメソッド名と対応付けられる。

**通知内容の概要**：TRequest型で定義されたパラメータオブジェクト。例えば、DidOpenTextDocumentParams、DidChangeTextDocumentParams、DidChangeConfigurationParamsなど。RequestContextを通じて現在のサーバー状態やワークスペース情報にアクセスできる。

**期待されるアクション**：ハンドラ実装クラスは、受信した通知パラメータに基づいて適切な処理（ドキュメント同期、設定更新、状態変更など）を非同期で実行する。処理完了後もクライアントへのレスポンスは送信されない。

## 通知種別

LSP通知（Language Server Protocol - パラメータ付き）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（一方向） |
| 優先度 | 通知内容による |
| リトライ | なし（通知のため） |

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

LSPフレームワークがLanguageServerEndpoint属性に基づいてハンドラを自動的にルーティングする。メソッド名と言語タイプに基づいて適切なハンドラが選択される。TRequest型パラメータはJSON-RPCのparamsフィールドからデシリアライズされる。

## 通知テンプレート

### LSP通知の場合

| 項目 | 内容 |
|-----|------|
| プロトコル | JSON-RPC 2.0 |
| メッセージタイプ | notification |
| パラメータ | TRequest型オブジェクト |

### 本文テンプレート

```json
{
  "jsonrpc": "2.0",
  "method": "{メソッド名}",
  "params": {
    // TRequest型のプロパティ
  }
}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| method | LSPメソッド名 | LanguageServerEndpoint属性 | Yes |
| params | 通知パラメータ | TRequest型オブジェクト | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ドキュメント操作 | ファイルオープン/変更/保存/クローズ | LSPサーバーが起動している | textDocument/* 通知 |
| 設定変更 | クライアント設定変更 | LSPサーバーが起動している | workspace/didChangeConfiguration |
| ファイル監視 | ファイルシステム変更 | ファイル監視が有効 | workspace/didChangeWatchedFiles |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| サーバー未起動 | LSPサーバーが起動していない場合 |
| ハンドラ未登録 | 対応するハンドラが登録されていない場合 |
| デシリアライズ失敗 | TRequest型へのデシリアライズが失敗した場合 |

## 処理フロー

### 受信フロー

```mermaid
flowchart TD
    A[クライアントから通知受信] --> B[JSON-RPCデシリアライズ]
    B --> C[メソッド名からハンドラ検索]
    C --> D{ハンドラ存在?}
    D -->|Yes| E[paramsをTRequest型にデシリアライズ]
    D -->|No| F[通知を無視]
    E --> G{デシリアライズ成功?}
    G -->|Yes| H[RequestContext生成]
    G -->|No| I[エラーログ記録]
    H --> J[HandleNotificationAsync呼び出し]
    J --> K[通知処理実行]
    K --> L[処理完了]
    L --> M[終了（レスポンスなし）]
    F --> M
    I --> M
```

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

### 参照テーブル一覧

該当なし（インメモリ処理）

### 更新テーブル一覧

該当なし（ハンドラ実装による）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ハンドラ未登録 | 対応するハンドラがない | 通知を無視（ログ記録） |
| デシリアライズ失敗 | TRequest型への変換失敗 | エラーログ記録、処理中断 |
| 処理例外 | ハンドラ内で例外発生 | 例外をログ記録、クライアントには通知しない |
| キャンセル | CancellationTokenがキャンセル | 処理を中断 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0回（通知のためリトライなし） |
| リトライ間隔 | なし |
| リトライ対象エラー | なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（クライアント依存） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（リアルタイム処理）

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

- LSP通信はローカルプロセス間通信が一般的
- ネットワーク経由の場合はTLSの使用を推奨
- パラメータのバリデーションはハンドラ実装で行う
- 大きなドキュメント内容の処理はメモリ使用量に注意

## 備考

- INotificationHandler<TRequest, TRequestContext>はIMethodHandlerを継承
- HandleNotificationAsyncメソッドはTRequest request, TRequestContext requestContext, CancellationToken cancellationTokenを受け取る
- パラメータなし通知にはINotificationHandler<TRequestContext>を使用
- Roslyn LSP拡張としてILspServiceNotificationHandler<TRequest>が定義されている

---

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

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

### 推奨読解順序

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

INotificationHandler<TRequest, TRequestContext>インターフェースの定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | INotificationHandler.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/INotificationHandler.cs` | インターフェース定義（22-30行目）、TRequestジェネリックパラメータ |

**読解のコツ**: TRequestがリクエストパラメータの型、TRequestContextがリクエストコンテキストの型を表すことに注目。HandleNotificationAsyncがTRequest requestを第一引数に取ることを確認。

#### Step 2: 実装例を理解する

実際のハンドラ実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | InitializedHandler.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/Handlers/InitializedHandler.cs` | INotificationHandler<TRequest, TRequestContext>の実装（15行目） |

**主要処理フロー**:
1. **15行目**: `INotificationHandler<TRequest, TRequestContext>`の実装
2. **21行目**: `HandleNotificationAsync(TRequest request, TRequestContext requestContext, CancellationToken cancellationToken)`

#### Step 3: ハンドラディスパッチを理解する

通知がどのようにハンドラに振り分けられるかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MethodHandlerDetails.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/MethodHandlerDetails.cs` | ハンドラ情報の抽出（80-84行目）、INotificationHandler<,>の検出 |

**主要処理フロー**:
- **80-84行目**: `typeof(INotificationHandler<,>)`の検出とRequestType/RequestContextTypeの抽出
- **82-83行目**: `genericArguments[0]`がRequestType、`genericArguments[1]`がRequestContextType

#### Step 4: キュー処理を理解する

通知の非同期処理フローを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | QueueItem.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/QueueItem.cs` | StartRequestAsyncでの通知処理（202-208行目） |

**主要処理フロー**:
- **202-204行目**: `INotificationHandler<TRequest, TRequestContext>`の判定と呼び出し
- **207行目**: NoValue.Instanceの返却（通知は値を返さない）

#### Step 5: Roslyn LSP拡張を理解する

Roslyn固有の拡張インターフェースを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ILspServiceNotificationHandler.cs | `src/LanguageServer/Protocol/Handler/ILspServiceNotificationHandler.cs` | ILspServiceNotificationHandler<TRequest>の定義（16-21行目） |

**主要処理フロー**:
- **16-21行目**: `ILspService`, `INotificationHandler<TRequest, RequestContext>`, `ISolutionRequiredHandler`を継承

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

```
LSPクライアント（IDE）
    │
    ▼
JSON-RPC受信（params付き）
    │
    ▼
MethodHandlerDetails.From
    │
    └─ INotificationHandler<TRequest, TRequestContext>検出
           │
           ▼
QueueItem.TryDeserializeRequest<TRequest>
    │
    └─ paramsをTRequest型にデシリアライズ
           │
           ▼
QueueItem.StartRequestAsync
    │
    └─ HandleNotificationAsync(request, context, ct)呼び出し
           │
           ▼
具体的なハンドラ実装
```

### データフロー図

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

JSON-RPC通知  ───▶  AbstractLanguageServer  ───▶  RequestContext生成
     │                      │
     │                      ▼
     │               TryDeserializeRequest
     │                      │
     ▼                      ▼
params(JSON)       TRequest型オブジェクト
                          │
                          ▼
                  HandleNotificationAsync
                          │
                          ▼
                  （レスポンスなし）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| INotificationHandler.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/INotificationHandler.cs` | ソース | インターフェース定義 |
| InitializedHandler.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/Handlers/InitializedHandler.cs` | ソース | 実装例 |
| MethodHandlerDetails.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/MethodHandlerDetails.cs` | ソース | ハンドラメタデータ抽出 |
| QueueItem.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/QueueItem.cs` | ソース | 通知処理キュー |
| ILspServiceNotificationHandler.cs | `src/LanguageServer/Protocol/Handler/ILspServiceNotificationHandler.cs` | ソース | Roslyn LSP拡張 |
