# 通知設計書 1-window/showMessage

## 概要

本ドキュメントは、serve-d LSPサーバーからクライアントへ送信される `window/showMessage` 通知の設計を記述する。この通知はLSP標準仕様に準拠し、サーバーがクライアントのUI上にメッセージを表示するために使用される。

### 本通知の処理概要

`window/showMessage` 通知は、serve-dサーバーがクライアント（エディタ）に対してエラー・警告・情報・ログの4種類のメッセージを表示させるための通知である。WindowFunctions構造体のshowMessage()メソッド経由で送信され、MessageTypeに応じた便利なラッパー関数（showErrorMessage、showWarningMessage、showInformationMessage、showLogMessage）が提供されている。

**業務上の目的・背景**：LSPサーバーは言語解析やプロジェクト管理中に様々な状態をユーザーに伝える必要がある。設定エラー、コンポーネントの初期化失敗、DCD（D Completion Daemon）のバージョン不整合など、ユーザーの注意や操作が必要な状況が頻繁に発生するため、この通知によりエディタ上で直接ユーザーにフィードバックを提供する。

**通知の送信タイミング**：サーバー起動時のコンポーネント初期化失敗時、設定値の不正検出時（dubConfiguration、dubArchType、dubBuildType、dubCompiler等）、DCDサーバーの起動失敗時、ワークスペースのスタートアップエラー表示時、致命的な内部エラー発生時など、多岐にわたるタイミングで送信される。

**通知の受信者**：LSPクライアント（VSCode等のエディタ）が受信し、エディタのUI上に通知ダイアログやメッセージバーとして表示する。

**通知内容の概要**：MessageType（error=1、warning=2、info=3、log=4）と人間が読めるテキストメッセージで構成される。メッセージは国際化対応（translate!関数）されている場合がある。

**期待されるアクション**：エラーメッセージの場合はユーザーが設定を修正する、警告メッセージの場合は問題を確認して対処する、情報メッセージの場合は内容を確認する、ログメッセージの場合は必要に応じてデバッグに活用する。

## 通知種別

LSP標準通知（サーバー -> クライアント）/ エディタ内通知（通知ダイアログ、メッセージバー）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（JSON-RPC通知） |
| 優先度 | MessageTypeに依存（error: 高、warning: 中、info: 低、log: 低） |
| リトライ | 無し |

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

LSP接続中のクライアント（エディタ）に対して直接送信される。送信先の選択ロジックは存在せず、RPC接続を通じて常に接続中のクライアントに送信される。

## 通知テンプレート

### LSP通知の場合

| 項目 | 内容 |
|-----|------|
| メソッド名 | `window/showMessage` |
| パラメータ型 | `ShowMessageParams` |
| 形式 | JSON-RPC 2.0 通知 |

### 本文テンプレート

```json
{
  "jsonrpc": "2.0",
  "method": "window/showMessage",
  "params": {
    "type": 1,
    "message": "メッセージ文字列"
  }
}
```

### 添付ファイル

該当なし（LSP通知のため添付ファイルは存在しない）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| type | メッセージ種別（1=error, 2=warning, 3=info, 4=log） | MessageType列挙値 | Yes |
| message | 表示するメッセージ文字列 | 呼び出し元から直接指定 / translate!関数による国際化文字列 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 設定変更 | dubConfiguration設定値が無効 | 設定されたconfigurationが存在しない | showErrorMessage経由で送信 |
| 設定変更 | dubArchType設定値が無効 | setArchTypeが失敗 | showErrorMessage経由で送信 |
| 設定変更 | dubBuildType設定値が無効 | setBuildTypeが失敗 | showErrorMessage経由で送信 |
| 設定変更 | dubCompiler設定値が無効 | setCompilerが失敗 | showErrorMessage経由で送信 |
| 設定変更 | プロジェクトにconfigurationが存在しない | configs.length == 0 | showInformationMessage経由で送信 |
| コンポーネント初期化 | DCDサーバー起動失敗 | startServer()で例外発生 | showErrorMessage経由で送信 |
| コンポーネント初期化 | コンポーネントのバインド失敗 | onBindFailコールバック | showErrorMessage経由で送信 |
| 致命的エラー | リクエスト処理中のThrowable | processRequestでThrowableをキャッチ | showMessage(error)経由で送信 |
| 致命的エラー | 通知処理中のThrowable | processNotifyでThrowableをキャッチ | showMessage(error)経由で送信 |
| プロジェクト初期化 | ワークスペースのスタートアップエラー | handleThings()でstartupErrorNotificationsが存在 | showErrorMessage経由で送信 |
| ファイル作成 | 新規Dソースファイルのモジュール名自動更新 | onFullyCreateDSourceで正規化パッチ適用 | showInformationMessage経由で送信 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| RPC接続が停止済み | shutdownRequested=trueの場合、新たな通知は送信されない |
| safeShowMessageフラグ | ラッパー関数（showErrorMessage等）使用時は重複ログ出力を抑止 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[イベント発生] --> B{メッセージ種別判定}
    B -->|error| C1[showErrorMessage]
    B -->|warning| C2[showWarningMessage]
    B -->|info| C3[showInformationMessage]
    B -->|log| C4[showLogMessage]
    C1 --> D[stderrにログ出力]
    C2 --> D
    C3 --> D
    C4 --> D
    D --> E[WindowFunctions.showMessage]
    E --> F[RPCProcessor.notifyMethod]
    F --> G[JSON-RPCパケット構築]
    G --> H[stdout経由で送信]
    H --> I[終了]
```

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

該当なし（LSPサーバーはデータベースを使用しない。全てのデータはインメモリで管理される）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | RPC接続が切断されている | 送信処理自体が例外をスローし、上位で処理 |
| シリアライゼーションエラー | パラメータのJSON変換失敗 | 発生しない（固定構造のため） |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（サーバー動作中は常時送信可能）

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

メッセージ文字列には内部パス情報やエラーメッセージが含まれる場合がある。デバッグビルドではファイルパスと行番号が追加される（types.d handleThings内のdebugブロック）。個人情報は含まれない。

## 備考

- WindowFunctions構造体はRPCProcessorのラッパーとして機能し、MessageTypeに応じた便利メソッドを提供する
- showErrorMessage/showWarningMessage/showInformationMessage/showLogMessageの各ラッパーはstderrへの適切なレベルでのログ出力も同時に行う
- safeShowMessageフラグにより、ラッパー関数経由の場合はshowMessage内での重複警告ログ出力が抑止される
- translate!関数により国際化対応されたメッセージが使用される場合がある

---

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

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

### 推奨読解順序

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

LSPプロトコルで定義されるShowMessageParamsとMessageTypeの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protocol.d | `lsp/source/served/lsp/protocol.d` | ShowMessageParams構造体とMessageType列挙値の定義。type(MessageType)とmessage(string)の2フィールドを持つ |

**読解のコツ**: protocol.dは自動生成されたLSPプロトコル型定義ファイルであり、非常に大きい。ShowMessageParamsでgrep検索すると効率的。

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

WindowFunctions構造体がshowMessage通知の主要なエントリーポイントである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | jsonrpc.d | `lsp/source/served/lsp/jsonrpc.d` | WindowFunctions構造体（938行目〜）。showMessage()メソッド（947行目）が基本送信関数。showErrorMessage（994行目）、showWarningMessage（1001行目）、showInformationMessage（1013行目）、showLogMessage（1019行目）が便利ラッパー |

**主要処理フロー**:
1. **947行目**: showMessage() - notifyMethodでwindow/showMessageを送信
2. **951行目**: rpc.notifyMethod("window/showMessage", ShowMessageParams(type, message)) - 実際の送信
3. **994行目**: showErrorMessage() - error()でログ出力後、showMessage(MessageType.error, ...)を呼び出し
4. **1013行目**: showInformationMessage() - info()でログ出力後、showMessage(MessageType.info, ...)を呼び出し

#### Step 3: 送信処理を理解する

RPCProcessorのnotifyMethodがJSON-RPCパケットを構築して送信する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | jsonrpc.d | `lsp/source/served/lsp/jsonrpc.d` | notifyMethod（172行目〜）がメソッド名とパラメータからJSON-RPCパケットを構築。sendRawPacket（145行目）がContent-Lengthヘッダ付きでstdoutに書き出す |

**主要処理フロー**:
- **180行目**: notifyMethod(string method, T value) - パラメータをserializeJsonでJSON化
- **201行目**: notifyMethodRaw - JSON-RPCフォーマットのパケット構築
- **145行目**: sendRawPacket - Content-Lengthヘッダ付きで書き出し

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

extension.dやserverbase.dなど、実際にshowMessageを呼び出す箇所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | extension.d | `source/served/extension.d` | changedConfig内の各設定エラー（121行目〜155行目）、startDCDServer内のエラー（1019行目）、onBindFail内のエラー（1375行目） |
| 4-2 | serverbase.d | `serverbase/source/served/serverbase.d` | gotRequest内の致命的エラー（412行目）、gotNotify内の致命的エラー（436行目） |
| 4-3 | types.d | `source/served/types.d` | handleThings内のスタートアップエラー表示（388行目） |

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

```
[呼び出し元: extension.d / serverbase.d / types.d 等]
    |
    +-- rpc.window.showErrorMessage(message)        [jsonrpc.d:994]
    |       +-- error(message)                       (stderrログ)
    |       +-- showMessage(MessageType.error, msg)  [jsonrpc.d:947]
    |
    +-- rpc.window.showWarningMessage(message)      [jsonrpc.d:1001]
    |       +-- warning(message)                     (stderrログ)
    |       +-- showMessage(MessageType.warning, msg)
    |
    +-- rpc.window.showInformationMessage(message)  [jsonrpc.d:1013]
    |       +-- info(message)                        (stderrログ)
    |       +-- showMessage(MessageType.info, msg)
    |
    +-- rpc.window.showLogMessage(message)          [jsonrpc.d:1019]
    |       +-- trace(message)                       (stderrログ)
    |       +-- showMessage(MessageType.log, msg)
    |
    +-- showMessage(type, message)                  [jsonrpc.d:947]
            +-- rpc.notifyMethod("window/showMessage", params) [jsonrpc.d:180]
                    +-- notifyMethodRaw(method, json)           [jsonrpc.d:201]
                            +-- sendRawPacket(parts)            [jsonrpc.d:145]
                                    +-- writer.put(...)         (stdout書き出し)
```

### データフロー図

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

メッセージ文字列        -->  WindowFunctions.showXxxMessage()  -->  stderr(ログ出力)
MessageType列挙値       -->  WindowFunctions.showMessage()     -->  JSON-RPCパケット
                        -->  RPCProcessor.notifyMethod()       -->  stdout(クライアントへ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| jsonrpc.d | `lsp/source/served/lsp/jsonrpc.d` | ソース | WindowFunctions構造体・RPCProcessor（通知送信の中核） |
| protocol.d | `lsp/source/served/lsp/protocol.d` | ソース | ShowMessageParams・MessageType等のLSPプロトコル型定義 |
| extension.d | `source/served/extension.d` | ソース | 設定変更エラー時の呼び出し元、コンポーネント初期化エラーの呼び出し元 |
| serverbase.d | `serverbase/source/served/serverbase.d` | ソース | 致命的エラー時のshowMessage呼び出し元 |
| types.d | `source/served/types.d` | ソース | handleThings内のスタートアップエラー表示の呼び出し元 |
| rename_listener.d | `source/served/workers/rename_listener.d` | ソース | ファイル作成時のshowInformationMessage呼び出し元 |
| translate.d | `source/served/utils/translate.d` | ソース | 国際化メッセージ文字列の提供 |
