# 画面設計書 7-設定変更通知

## 概要

本ドキュメントは、serve-d LSPサーバーにおける設定変更通知処理の画面設計書である。クライアントからの `workspace/didChangeConfiguration` 通知を受け取り、DCD、DScanner、dfmt等の各コンポーネントに設定変更を反映する。

### 本画面の処理概要

**業務上の目的・背景**：ユーザーがエディタの設定を変更した場合（例: コンパイラの変更、リンターの有効/無効切り替え、DUB設定の変更等）、それらの変更をserve-dの各コンポーネントにリアルタイムで反映する必要がある。本処理は設定変更のハブとして機能し、各コンポーネントへの設定配信を一元管理する。

**画面へのアクセス方法**：クライアントがユーザー設定を変更した際に `workspace/didChangeConfiguration` 通知が自動送信される。serve-dは `@onConfigChanged` アノテーションで `changedConfig` 関数を設定変更ハンドラとして登録している。

**主要な操作・処理内容**：
1. 変更された設定パスに基づいてswitch文で各コンポーネントの設定を更新する
2. `d.stdlibPath` 変更時: DCDのインポートパスを更新
3. `d.projectImportPaths` 変更時: DCDのプロジェクトインポートパスを更新
4. `d.dubConfiguration` 変更時: DUBのビルド設定を切り替え（無効な場合はエラー表示）
5. `d.dubArchType` / `d.dubBuildType` / `d.dubCompiler` 変更時: 各DUB設定を更新
6. `d.enableAutoComplete` 変更時: DCDサーバーの起動/停止を制御
7. `d.enableLinting` / `d.enableStaticLinting` / `d.enableDubLinting` 変更時: リンター設定を更新
8. ワークスペースが未初期化の場合は `doStartup` を呼び出す

**画面遷移**：
- 遷移元：クライアント設定変更（workspace/didChangeConfiguration）
- 遷移先：No.2 グローバルスタートアップ（初回設定変更時、ensureStartedUp経由）、No.3 ワークスペーススタートアップ（ワークスペース未初期化時）、No.8 エラーメッセージ通知（無効な設定値の場合）

**権限による表示制御**：なし。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | 設定変更処理 | 主機能 | クライアントからの設定変更通知を受け取り、DCD・DUB・リンター等の各コンポーネントに設定を反映する |
| 3 | トレース設定 ($/setTrace) | 補助機能 | 設定変更処理内でログレベルの変更も処理する |

## 画面種別

LSPプロトコル通知ハンドラ（`workspace/didChangeConfiguration`）

## URL/ルーティング

LSP通知名: `workspace/didChangeConfiguration`（`@onConfigChanged` アノテーション経由）

## 入出力項目

### 入力

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| target | ConfigWorkspace | はい | 設定変更対象のワークスペース情報（URI、インデックス等） |
| paths | string[] | はい | 変更された設定パスの配列（例: "d.stdlibPath", "d.dubConfiguration"等） |
| config | Configuration | はい | 更新後の設定値 |

### 出力

| 項目名 | 種別 | 説明 |
|--------|------|------|
| なし | - | 通知ハンドラのため戻り値なし。エラー時はクライアントにメッセージ表示 |

## 表示項目

### 処理対象設定パス一覧

| 設定パス | 対象コンポーネント | 処理内容 |
|---------|-------------------|---------|
| d.stdlibPath | DCDComponent | 標準ライブラリパスのインポート追加 |
| d.projectImportPaths | DCDComponent | プロジェクトインポートパスの追加 |
| d.dubConfiguration | DubComponent | DUBビルド設定の切り替え |
| d.dubArchType | DubComponent | アーキテクチャタイプの変更 |
| d.dubBuildType | DubComponent | ビルドタイプの変更 |
| d.dubCompiler | DubComponent | コンパイラの変更 |
| d.enableAutoComplete | DCDComponent | DCD補完の有効/無効切り替え |
| d.enableLinting | DScanner/DUB | 全リンターのクリア（無効化時） |
| d.enableStaticLinting | DScanner | DScannerリンターのクリア（無効化時） |
| d.enableDubLinting | DUB | DUBリンターのクリア（無効化時） |

## イベント仕様

### 1-設定変更通知受信

1. `changedConfig` 関数が `@onConfigChanged` アノテーションにより呼び出される
2. `reportProgress(ProgressType.configLoad, ...)` で進捗通知を送信
3. `ensureStartedUp(config)` でグローバル初期化を保証（初回のみ）
4. ワークスペースURIの妥当性を検証

### 2-各設定パスの処理

1. `paths` 配列を走査し、各パスに応じたswitch文で処理を分岐
2. 各設定パスに対応するコンポーネントの設定更新を実行
3. 無効な設定値の場合は `rpc.window.showErrorMessage` でクライアントにエラー通知（No.8へ遷移）

### 3-ワークスペース未初期化の場合

1. `proj.initialized` が `false` の場合
2. `doStartup(proj.folder.uri, config)` を呼び出し
3. `proj.initialized = true` に設定

### 4-設定変更完了

1. `configFinished` が呼ばれ `reportProgress(ProgressType.configFinish, ...)` で完了通知

## データベース更新仕様

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

| 操作（イベント） | 対象データ | 操作種別 | 概要 |
|----------------|-----------|---------|------|
| stdlibPath変更 | DCDComponent | 更新 | インポートパスリストにstdlibパスを追加 |
| dubConfiguration変更 | DubComponent | 更新 | DUBビルド設定を切り替え |
| enableAutoComplete無効化 | DCDComponent | 停止 | DCDサーバーを停止 |
| enableLinting無効化 | DScanner/DUB | クリア | 診断結果をクリア |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|------------|------|--------------|----------|
| d.ext.noConfigurations.project | info | "No configurations available for this project. Autocompletion could be broken!" | DUB設定が0件の場合 |
| d.ext.config.invalid.configuration | error | "Configuration '{0}' which is specified in the config is not available!" | 無効なDUB設定名 |
| d.ext.config.invalid.archType | error | "Arch Type '{0}' which is specified in the config is not available!" | 無効なアーキテクチャ |
| d.ext.config.invalid.buildType | error | "Build Type '{0}' which is specified in the config is not available!" | 無効なビルドタイプ |
| d.ext.config.invalid.compiler | error | "Compiler '{0}' which is specified in the config is not available!" | 無効なコンパイラ |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 空のワークスペースURI | エラーログ "Passed invalid empty workspace uri to changedConfig!" 出力、処理中断 |
| 未知のワークスペースURI | エラーログ "Did not find workspace ... when updating config?" 出力、処理中断 |
| 無効なDUB設定値 | showErrorMessage でクライアントにエラー通知 |
| コンポーネント未初期化 | `backend.has!` でチェックし、存在しない場合はスキップ |

## 備考

- `@onConfigChanged` は serve-d のカスタムアノテーションで、LSPの設定変更通知をハンドルする
- 設定変更処理の実行時間は `StopWatch` で計測され、トレースログに記録される
- `configFinished` は `@onConfigFinished` アノテーションで全ワークスペースの設定変更完了時に呼ばれる
- フォールバックワークスペース（ユーザーグローバル設定）への設定変更は特別扱いされる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.d | `source/served/types.d` | `Configuration` 構造体（74行目〜）の全フィールドを確認 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | extension.d | `source/served/extension.d` | `changedConfig` 関数（60行目〜203行目）がエントリーポイント |

**主要処理フロー**:
1. **62-63行目**: StopWatchで計測開始
2. **67行目**: `reportProgress(ProgressType.configLoad, ...)`
3. **69行目**: `ensureStartedUp(config)` - 初回のみグローバル初期化
4. **71-80行目**: ワークスペースURIの検証
5. **82-93行目**: Workspaceオブジェクトの取得と検証
6. **95-99行目**: ワークスペース未初期化時の `doStartup` 呼び出し
7. **103-198行目**: 設定パスごとのswitch文処理
8. **201-202行目**: 完了ログ出力

#### Step 3: 各設定パスの処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | extension.d | `source/served/extension.d` | 107-155行目: d.stdlibPath, d.projectImportPaths, d.dubConfiguration, d.dubArchType, d.dubBuildType, d.dubCompiler |
| 3-2 | extension.d | `source/served/extension.d` | 156-195行目: d.enableAutoComplete, d.enableLinting, d.enableStaticLinting, d.enableDubLinting |

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

```
[workspace/didChangeConfiguration]
    │
    └─ changedConfig(target, paths, config)  [60行目]
           │
           ├─ reportProgress(configLoad)  [67行目]
           ├─ ensureStartedUp(config)  [69行目]
           │
           ├─ [URI検証]  [71-93行目]
           │
           ├─ [未初期化] → doStartup(uri, config)  [97行目]
           │
           └─ [paths走査]  [103-198行目]
                  ├─ "d.stdlibPath" → DCDComponent.addImports()
                  ├─ "d.projectImportPaths" → DCDComponent.addImports()
                  ├─ "d.dubConfiguration" → DubComponent.setConfiguration()
                  │      └─ [無効] → showErrorMessage()
                  ├─ "d.dubArchType" → DubComponent.setArchType()
                  │      └─ [無効] → showErrorMessage()
                  ├─ "d.dubBuildType" → DubComponent.setBuildType()
                  │      └─ [無効] → showErrorMessage()
                  ├─ "d.dubCompiler" → DubComponent.setCompiler()
                  │      └─ [無効] → showErrorMessage()
                  ├─ "d.enableAutoComplete" → DCDサーバー起動/停止
                  ├─ "d.enableLinting" → DScanner/DUBリンタークリア
                  ├─ "d.enableStaticLinting" → DScannerクリア
                  └─ "d.enableDubLinting" → DUBリンタークリア
```

### データフロー図

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

ConfigWorkspace ──────▶ changedConfig()                  進捗通知（configLoad）
string[] paths             │                              エラーメッセージ（無効設定時）
Configuration config       ├─ ensureStartedUp()           進捗通知（configFinish）
                           ├─ URI検証
                           ├─ 未初期化判定 → doStartup()
                           └─ 設定パス別処理
                                  └─ コンポーネント設定更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| extension.d | `source/served/extension.d` | ソース | changedConfig関数、configFinished関数の実装 |
| types.d | `source/served/types.d` | ソース | Configuration構造体、Workspace構造体 |
| progress.d | `source/served/utils/progress.d` | ソース | ProgressType.configLoad, configFinish |
| translate.d | `source/served/utils/translate.d` | ソース | エラーメッセージの翻訳 |
| en.txt | `views/en.txt` | リソース | エラーメッセージ翻訳テキスト |
