# 機能設計書 91-共通LSPフレームワーク

## 概要

本ドキュメントは、Roslyn の共通 LSP (Language Server Protocol) フレームワークの機能設計を定義する。このフレームワークは、言語に依存しない LSP サーバーの基盤を提供し、C#、Visual Basic、その他の言語向けの LSP 実装で共有される。

### 本機能の処理概要

共通 LSP フレームワークは、Language Server Protocol に準拠した言語サーバーを構築するための抽象化レイヤーを提供する。JSON-RPC を介したクライアント-サーバー通信、リクエストのキューイングと実行、ハンドラーの登録と管理を統一的に行う。

**業務上の目的・背景**：IDE やエディタ（Visual Studio Code、Visual Studio 等）と言語サービスを統合するために、標準化された LSP を実装する必要がある。言語ごとに LSP サーバーを個別に実装するのではなく、共通基盤を設けることで、開発効率の向上と一貫した動作を実現する。

**機能の利用シーン**：開発者が Visual Studio Code やその他の LSP 対応エディタで C# や Visual Basic のコードを編集する際、この共通フレームワーク上に構築された言語サーバーがコード補完、定義へ移動、診断情報などの機能を提供する。

**主要な処理内容**：
1. LSP リクエスト/通知のルーティングとハンドラーへのディスパッチ
2. リクエスト実行キューによる順序制御と並行実行管理
3. サーバーライフサイクル管理（初期化、シャットダウン、終了）
4. ハンドラーのメタデータ管理と動的登録

**関連システム・外部連携**：StreamJsonRpc を使用した JSON-RPC 通信、各種 LSP クライアント（VS Code、Visual Studio 等）との連携。

**権限による制御**：LSP 仕様に基づくサーバー機能のネゴシエーション（ServerCapabilities）により、クライアントが利用可能な機能を制御。

## 関連画面

本機能は LSP プロトコルを提供するバックエンド処理であり、直接的な UI 画面は持たない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | LSP クライアントからのリクエストを処理 |

## 機能種別

プロトコル処理 / サーバーフレームワーク / リクエストハンドリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| jsonRpc | JsonRpc | Yes | JSON-RPC 通信オブジェクト | null チェック |
| logger | ILspLogger | Yes | ログ記録用インスタンス | null チェック |
| typeRefResolver | AbstractTypeRefResolver | No | 型参照リゾルバ | デフォルトで TypeRef.DefaultResolver を使用 |
| request | TRequest | Yes | LSP リクエストオブジェクト | リクエストごとのバリデーション |

### 入力データソース

- LSP クライアントからの JSON-RPC リクエスト（標準入出力またはソケット経由）
- LSP プロトコル仕様に準拠したリクエストパラメータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| response | TResponse | LSP レスポンスオブジェクト |
| error | ResponseError | エラー発生時のエラー情報 |
| notification | object | サーバーからクライアントへの通知 |

### 出力先

- JSON-RPC を通じた LSP クライアントへのレスポンス

## 処理フロー

### 処理シーケンス

```
1. サーバー初期化
   └─ AbstractLanguageServer コンストラクタで JsonRpc 設定、ハンドラープロバイダー初期化
2. リクエスト受信
   └─ SetupRequestDispatcher でメソッドごとにエントリーポイントを登録
3. キュー登録
   └─ RequestExecutionQueue.ExecuteAsync でリクエストをキューに追加
4. ハンドラー実行
   └─ ProcessQueueCoreAsync で適切なハンドラーを呼び出し
5. レスポンス返却
   └─ JSON-RPC 経由でクライアントにレスポンスを送信
6. シャットダウン
   └─ ShutdownAsync → ExitAsync でサーバー終了
```

### フローチャート

```mermaid
flowchart TD
    A[クライアントからリクエスト受信] --> B[JSON-RPC デシリアライズ]
    B --> C[DelegatingEntryPoint.InvokeAsync]
    C --> D[RequestExecutionQueue.ExecuteAsync]
    D --> E{ミューテーティングリクエスト?}
    E -->|Yes| F[直列実行・他リクエストブロック]
    E -->|No| G[並列実行可能]
    F --> H[ハンドラー実行]
    G --> H
    H --> I[レスポンス生成]
    I --> J[JSON-RPC でレスポンス送信]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-91-01 | ミューテーティングリクエストの直列化 | ソリューション状態を変更するリクエストは後続リクエストをブロックして実行 | handler.MutatesSolutionState == true |
| BR-91-02 | キャンセル伝播 | クライアントからのキャンセルまたはキュー停止時にリクエストをキャンセル | CancellationToken がキャンセルされた場合 |
| BR-91-03 | シャットダウン順序 | shutdown リクエスト後にのみ exit 通知を処理可能 | _shutdownRequestTask が完了している場合 |
| BR-91-04 | 言語ルーティング | リクエストごとに適切な言語ハンドラーにルーティング | TryGetLanguageForRequest で言語判定 |

### 計算ロジック

リクエスト実行の優先度は受信順に処理される（FIFO）。ただし、ミューテーティングリクエストは他のリクエストの完了を待たずにキューの先頭で処理される。

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

本機能はデータベースを直接操作しない。ワークスペースの状態管理はインメモリで行われる。

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| -32700 | ParseError | JSON パースエラー | リクエスト形式を確認 |
| -32600 | InvalidRequest | 不正なリクエスト | リクエスト構造を確認 |
| -32601 | MethodNotFound | ハンドラーが存在しない | サーバー機能を確認 |
| -32602 | InvalidParams | パラメータ不正 | パラメータ形式を確認 |
| -32603 | InternalError | 内部エラー | サーバーログを確認 |
| -32802 | RequestCancelled | リクエストがキャンセルされた | 正常なキャンセル |
| -32800 | ContentModified | ドキュメントが変更された | 再リクエストが必要 |

### リトライ仕様

LSP 仕様により、クライアント側でリトライを制御する。サーバー側ではエラーレスポンスを返却するのみ。

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

LSP リクエストは個別のアトミック操作として処理される。ワークスペースの状態変更（didOpen, didChange 等）は即座にスナップショットに反映される。

## パフォーマンス要件

- リクエストレスポンスタイム: 100ms 以内（通常のリクエスト）
- コード補完: 200ms 以内
- 定義へ移動: 100ms 以内
- 非ミューテーティングリクエストの並列実行をサポート

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

- 標準入出力またはローカルソケット経由の通信（ネットワーク公開なし）
- ファイルシステムアクセスはワークスペース設定に制限
- 外部プロセス起動の制限

## 備考

本フレームワークは NuGet パッケージ `Microsoft.CommonLanguageServerProtocol.Framework` として公開され、外部の言語サーバー実装でも使用可能。

---

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

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

### 推奨読解順序

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

まず、LSP リクエストのメタデータとハンドラーのインターフェースを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IRequestHandler.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/IRequestHandler.cs` | リクエストハンドラーの基本インターフェース、HandleRequestAsync メソッドの定義 |
| 1-2 | INotificationHandler.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/INotificationHandler.cs` | 通知ハンドラーのインターフェース |
| 1-3 | RequestHandlerMetadata.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/RequestHandlerMetadata.cs` | ハンドラーのメタデータ構造（メソッド名、言語、型情報） |
| 1-4 | IQueueItem.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/IQueueItem.cs` | キュー項目のインターフェース |

**読解のコツ**: `IRequestHandler<TRequest, TResponse, TRequestContext>` は 3 つの型パラメータを持つ。TRequest は入力、TResponse は出力、TRequestContext はリクエストコンテキスト（ドキュメント情報等）。

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

処理の起点となる AbstractLanguageServer クラスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AbstractLanguageServer.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/AbstractLanguageServer.cs` | サーバーの基底クラス、初期化とシャットダウンの流れ |

**主要処理フロー**:
1. **59-82行目**: コンストラクタで JsonRpc 設定、Lazy 初期化
2. **88-91行目**: Initialize() でリクエスト実行キューを開始
3. **110-157行目**: SetupRequestDispatcher でメソッドごとにエントリーポイント登録
4. **159-163行目**: shutdown/exit ハンドラーの定義
5. **246-271行目**: ShutdownAsync でキュー停止とクリーンアップ
6. **277-325行目**: ExitAsync でリソース解放

#### Step 3: リクエスト実行キューを理解する

LSP リクエストの順序制御と並行実行を管理する RequestExecutionQueue を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RequestExecutionQueue.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/RequestExecutionQueue.cs` | キューの実装、ミューテーティングと非ミューテーティングの区別 |

**主要処理フロー**:
- **156-188行目**: ExecuteAsync でリクエストをキューに追加
- **190-303行目**: ProcessQueueAsync でキューからリクエストを取り出して実行
- **332-406行目**: ProcessQueueCoreAsync でハンドラー実行とレスポンス処理

#### Step 4: ハンドラープロバイダーを理解する

ハンドラーの登録と取得を管理する HandlerProvider を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | HandlerProvider.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/HandlerProvider.cs` | ハンドラーの登録と検索ロジック |
| 4-2 | AbstractHandlerProvider.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/AbstractHandlerProvider.cs` | ハンドラープロバイダーの抽象基底クラス |

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

```
AbstractLanguageServer<TRequestContext>
    │
    ├─ Initialize()
    │      └─ GetRequestExecutionQueue()
    │             └─ ConstructRequestExecutionQueue()
    │
    ├─ SetupRequestDispatcher(handlerProvider)
    │      └─ CreateDelegatingEntryPoint(method)
    │
    └─ DelegatingEntryPoint.InvokeAsync()
           └─ RequestExecutionQueue.ExecuteAsync()
                  └─ QueueItem.Create()
                         └─ ProcessQueueAsync()
                                └─ ProcessQueueCoreAsync<TRequest, TResponse>()
                                       ├─ CreateRequestContextAsync()
                                       └─ StartRequestAsync()
                                              └─ IRequestHandler.HandleRequestAsync()
```

### データフロー図

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

LSP クライアント ─────▶ JsonRpc ─────▶ DelegatingEntryPoint ─────▶ レスポンス
                         │
                         ▼
                  DeserializeRequest()
                         │
                         ▼
              RequestExecutionQueue.ExecuteAsync()
                         │
                         ▼
                    QueueItem
                         │
                         ▼
               ProcessQueueCoreAsync()
                         │
                         ▼
            IRequestHandler.HandleRequestAsync()
                         │
                         ▼
                    TResponse
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AbstractLanguageServer.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | LSP サーバーの抽象基底クラス |
| RequestExecutionQueue.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | リクエスト実行キュー |
| IRequestHandler.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | リクエストハンドラーインターフェース |
| INotificationHandler.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | 通知ハンドラーインターフェース |
| HandlerProvider.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | ハンドラー管理 |
| RequestHandlerMetadata.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | ハンドラーメタデータ |
| QueueItem.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | キュー項目の実装 |
| ILspServices.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | LSP サービスコンテナインターフェース |
| LanguageServerEndpointAttribute.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | エンドポイント定義属性 |
| ILifeCycleManager.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | ライフサイクル管理インターフェース |
| NewtonsoftLanguageServer.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | Newtonsoft.Json 対応サーバー実装 |
| SystemTextJsonLanguageServer.cs | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ソース | System.Text.Json 対応サーバー実装 |
| README.md | `src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/` | ドキュメント | フレームワークの概要説明 |
