# 通知設計書 5-workspace/didChangeConfiguration

## 概要

本ドキュメントは、LSP(Language Server Protocol)におけるworkspace/didChangeConfiguration通知の設計仕様を記載する。クライアントからサーバーへ送信される通知であり、設定が変更されたことをサーバーに通知する。

### 本通知の処理概要

workspace/didChangeConfiguration通知は、エディタやIDEの設定が変更された際に、クライアントからclojure-lspサーバーへ送信される通知である。clojure-lspの現在の実装では、この通知を受信するとサーバー内部の設定を更新する。

**業務上の目的・背景**：ユーザーがエディタの設定を変更した際、その変更をサーバーに反映させることで、ユーザーの意図に沿った言語機能の提供を実現する。例えば、フォーマット設定、診断設定、ソースパス設定などの変更がランタイムで反映される。これにより、エディタの再起動なしに設定変更を適用できる。

**通知の送信タイミング**：ユーザーがエディタの設定画面で設定を変更した時、または設定ファイルが更新された時に、エディタ(LSPクライアント)がこの通知を送信する。

**通知の受信者**：clojure-lspサーバープロセスがこの通知を受信する。サーバーは非同期（eventually）で処理を実行する。

**通知内容の概要**：通知には、変更された設定のセクションが含まれる。LSP仕様では設定のセクション名が指定されるが、clojure-lspでは設定オブジェクト全体を受け取り、既存の設定とマージする。

**期待されるアクション**：サーバーは受信後、新しい設定を既存の設定とディープマージし、DBに保存する。設定変更後の再解析は自動的には実行されず、必要に応じて他の通知（didSaveなど）をトリガーとして再解析が行われる。

## 通知種別

LSP通知 (クライアント → サーバー)

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（eventually） |
| 優先度 | 中（設定更新） |
| リトライ | なし（通知のため応答なし） |

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

クライアントからサーバーへの一方向通知のため、送信先決定ロジックは不要。

## 通知テンプレート

### パラメータ構造

| 項目 | 内容 |
|-----|------|
| メソッド名 | workspace/didChangeConfiguration |
| パラメータ型 | DidChangeConfigurationParams |
| プロトコル | JSON-RPC 2.0 over stdio |

### パラメータ定義

```json
{
  "settings": {
    "source-paths": ["src", "test"],
    "cljfmt": {
      "remove-trailing-whitespace?": true
    },
    "linters": {
      "clj-kondo": {
        "level": "on"
      }
    }
  }
}
```

### 添付ファイル

該当なし（LSP通知にファイル添付機能なし）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| settings | 設定オブジェクト | クライアント（エディタ設定） | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | 設定画面での変更 | サーバー接続中 | ユーザーがエディタ設定を変更した時 |
| ファイル変更 | 設定ファイル更新 | サーバー接続中 | settings.jsonなどの更新時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| サーバー未接続 | LSPサーバーが起動していない/接続されていない場合 |
| 初期化完了前 | サーバーの初期化が完了していない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[設定変更] --> B[workspace/didChangeConfiguration通知送信]
    B --> C[サーバーで受信]
    C --> D[handler/did-change-configurationを呼び出し]
    D --> E[settings/set-allを呼び出し]
    E --> F[既存設定を取得]
    F --> G[新設定とディープマージ]
    G --> H[DBに保存]
    H --> I[終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| db/settings | 既存設定の参照 | マージ元 |

### テーブル別参照項目詳細

#### db/settings

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| :settings | 既存の設定オブジェクト | - |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| db/settings | UPDATE | 設定のマージ結果を保存 |

#### db/settings更新詳細

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| ASSOC | :settings | マージ後の設定 | deep-merge結果 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 設定形式エラー | 不正なJSON形式 | ログ出力して処理継続 |
| マージエラー | 設定構造の不整合 | 既存設定を維持 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（常時処理可能）

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

- 設定内容にはファイルパスが含まれる可能性がある
- 設定の内容は信頼されたクライアントから送信されることを前提とする

## 備考

- LSP仕様: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeConfiguration
- この通知は応答を返さない(notification)
- 通知一覧.csvの備考欄には「現在はログ出力のみ」と記載されているが、実際にはsettings/set-allで設定が更新される
- 設定の自動リフレッシュ機能（settings-auto-refresh?）により、TTL（1000ms）経過後に設定ファイルから再読み込みされることもある

---

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

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

### 推奨読解順序

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

まず、プログラム間で受け渡されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | settings.clj | `lib/src/clojure_lsp/settings.clj` | 設定構造、clean-client-settings |
| 1-2 | config.clj | `lib/src/clojure_lsp/config.clj` | deep-merge-considering-settings |

**読解のコツ**: 設定のマージ戦略（deep-merge）を理解すること。特にネストした設定がどのようにマージされるかを確認する。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | receive-notification multimethod定義 |

**主要処理フロー**:
1. **453-456行目**: `workspace/didChangeConfiguration`メソッドのdefmethod定義
2. **454-456行目**: handler/did-change-configurationへの委譲、eventually内で実行

#### Step 3: ハンドラー層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | did-change-configuration関数の定義 |

**主要処理フロー**:
- **535-539行目**: did-change-configuration関数本体
- **539行目**: settings/set-allへの委譲

#### Step 4: 設定管理層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | settings.clj | `lib/src/clojure_lsp/settings.clj` | set-all関数の実装 |

**主要処理フロー**:
- **95-100行目**: set-all関数本体
- **97行目**: 既存設定を取得
- **99行目**: deep-mergeで新設定とマージ
- **100行目**: DBに保存

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

```
jsonrpc.server/receive-notification "workspace/didChangeConfiguration"
    |
    +-- server.clj (453-456行目)
           |
           +-- eventually (非同期)
                  |
                  +-- handler/did-change-configuration (handlers.clj 535-539行目)
                         |
                         +-- settings/set-all (settings.clj 95-100行目)
                                |
                                +-- deref db* (97行目)
                                +-- shared/deep-merge (99行目)
                                +-- swap! db* (100行目)
```

### データフロー図

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

DidChangeConfigurationParams
    |
    +-- settings ----+
                     |
                     +---> handler/did-change-configuration
                     |            |
                     |            v
                     +---> settings/set-all
                                  |
                                  +---> 既存設定取得 (@db* :settings)
                                  |            |
                                  |            v
                                  +---> shared/deep-merge (old-settings, new-settings)
                                  |            |
                                  |            v
                                  +---> swap! db* assoc :settings
                                               |
                                               v
                                        更新された設定がDBに保存
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSPサーバーのエントリーポイント、通知受信 |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | 各種LSPメッセージのハンドラー |
| settings.clj | `lib/src/clojure_lsp/settings.clj` | ソース | 設定管理、マージ処理 |
| config.clj | `lib/src/clojure_lsp/config.clj` | ソース | 設定ファイルの読み込み、マージ戦略 |
| shared.clj | `lib/src/clojure_lsp/shared.clj` | ソース | deep-merge関数 |
