# 機能設計書 5-設定変更処理

## 概要

本ドキュメントは、serve-d LSPサーバーにおける設定変更処理機能の設計を記述する。エディタからの設定変更通知を受け取り、DCD・DUB・リンター等の各コンポーネントに設定を反映する。

### 本機能の処理概要

LSPの設定変更通知（workspace/didChangeConfiguration等）に応じて呼ばれるchangedConfig関数を中心とした設定反映処理である。変更された設定パスに応じて、対応するバックエンドコンポーネント（DCDのインポートパス、DUBのビルド設定・アーキテクチャ・ビルドタイプ・コンパイラ、オートコンプリート・リンティングの有効/無効等）に動的に設定を反映する。

**業務上の目的・背景**：D言語開発者がエディタの設定画面からserve-dの動作パラメータ（コンパイラパス、ビルド設定、リンティングの有効化等）を変更した際に、サーバーの再起動なしに即座に反映させる必要がある。これにより開発効率が大幅に向上する。

**機能の利用シーン**：ユーザーがVSCodeの設定（settings.json）でD言語関連の設定を変更した際に自動的に呼び出される。

**主要な処理内容**：
1. 設定変更の進捗レポートを送信
2. ensureStartedUpでグローバル初期化を保証
3. 対象ワークスペースの特定と妥当性チェック
4. ワークスペース未初期化の場合はdoStartupを実行
5. 変更された設定パスごとにswitch文で対応処理を実行:
   - d.stdlibPath: DCDにインポートパス追加
   - d.projectImportPaths: DCDにプロジェクトインポートパス追加
   - d.dubConfiguration: DUBビルド設定の切り替え
   - d.dubArchType: DUBアーキテクチャの切り替え
   - d.dubBuildType: DUBビルドタイプの切り替え
   - d.dubCompiler: DUBコンパイラの切り替え
   - d.enableAutoComplete: DCDサーバーの起動/停止
   - d.enableLinting/enableStaticLinting/enableDubLinting: リンターのクリア

**関連システム・外部連携**：LSPクライアント。バックエンドコンポーネント（DCD, DUB, DScanner, dfmt）。

**権限による制御**：特に権限制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | 設定変更通知 | 主機能 | クライアントからの設定変更通知を受け取り各コンポーネントに反映 |
| 8 | エラーメッセージ通知 | 主機能 | 無効な設定値が指定された場合にshowErrorMessageでエラー表示 |
| 3 | ワークスペーススタートアップ | 補助機能 | 設定変更時にワークスペースが未初期化の場合にdoStartupが呼び出される |

## 機能種別

データ連携（設定反映・コンポーネント制御）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| target | ConfigWorkspace | Yes | 設定変更対象のワークスペース情報 | indexとnumWorkspacesを含む |
| paths | string[] | Yes | 変更された設定パスの一覧 | 設定キー名のリスト |
| config | Configuration | Yes | 変更後の設定値 | Configuration構造体 |

### 入力データソース

LSPクライアントからの設定変更通知をConfigHandlerミックスインが処理し、changedConfig関数に渡す。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| なし | - | 通知処理のためレスポンスは返却しない |

### 出力先

バックエンドコンポーネントの内部状態更新。エラー時はLSPクライアントへのshowErrorMessage通知。

## 処理フロー

### 処理シーケンス

```
1. 進捗レポート送信
   └─ reportProgress(ProgressType.configLoad, ...)
2. グローバル初期化保証
   └─ ensureStartedUp(config) - 初回のみdoGlobalStartupを実行
3. ワークスペースの特定
   └─ target.uriが空の場合の処理
      └─ isUnnamedWorkspaceでないなら: エラー出力して終了
      └─ isUnnamedWorkspaceなら: fallbackWorkspaceのURIを使用
4. ワークスペース妥当性チェック
   └─ workspace(target.uri)でワークスペースを取得
   └─ fallbackWorkspaceかつisUnnamedWorkspaceでない場合: エラー出力して終了
5. ワークスペース未初期化の場合
   └─ doStartup(proj.folder.uri, config)を実行
   └─ proj.initialized = trueに設定
6. 設定パス別処理（switch文）
   └─ d.stdlibPath → DCDにインポートパス追加
   └─ d.projectImportPaths → DCDにプロジェクトインポートパス追加
   └─ d.dubConfiguration → DUBビルド設定切り替え（無効値はエラー通知）
   └─ d.dubArchType → DUBアーキテクチャ切り替え（無効値はエラー通知）
   └─ d.dubBuildType → DUBビルドタイプ切り替え（無効値はエラー通知）
   └─ d.dubCompiler → DUBコンパイラ切り替え（無効値はエラー通知）
   └─ d.enableAutoComplete → true:DCD起動 / false:DCD停止
   └─ d.enableLinting → false:DScanner・DUBリンタークリア
   └─ d.enableStaticLinting → false:DScannerリンタークリア
   └─ d.enableDubLinting → false:DUBリンタークリア
```

### フローチャート

```mermaid
flowchart TD
    A[changedConfig呼び出し] --> B[進捗レポート送信]
    B --> C[ensureStartedUp]
    C --> D{target.uri空?}
    D -->|Yes| E{isUnnamedWorkspace?}
    E -->|No| F[エラー出力・終了]
    E -->|Yes| G[fallbackWorkspace URI使用]
    D -->|No| H[workspace取得]
    G --> H
    H --> I{未初期化?}
    I -->|Yes| J[doStartup実行]
    I -->|No| K[設定パスごとの処理ループ]
    J --> K
    K --> L[各パスのswitch処理]
    L --> M[処理完了ログ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 無効DUB設定のエラー通知 | dubConfiguration, dubArchType, dubBuildType, dubCompilerに無効値が指定された場合showErrorMessageで通知 | 各設定値がバックエンドに存在しない場合 |
| BR-02 | 未初期化ワークスペースの自動初期化 | 設定変更時にワークスペースが未初期化の場合、doStartupを呼び出して初期化する | proj.initialized == false |
| BR-03 | DCD起動制御 | enableAutoCompleteがtrueに変更されたらDCDサーバーを起動、falseなら停止 | d.enableAutoComplete変更時 |
| BR-04 | リンター制御 | enableLinting/enableStaticLinting/enableDubLintingがfalseに変更された場合、対応するリンターの結果をクリア | 各リンティング設定がfalseに変更された時 |

### 計算ロジック

特になし。

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

本機能ではデータベース操作は発生しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| d.ext.noConfigurations.project | 情報 | DUBプロジェクトに設定が0個の場合 | showInformationMessageで通知 |
| d.ext.config.invalid.configuration | エラー | 無効なdubConfigurationが指定された場合 | showErrorMessageで通知 |
| d.ext.config.invalid.archType | エラー | 無効なdubArchTypeが指定された場合 | showErrorMessageで通知 |
| d.ext.config.invalid.buildType | エラー | 無効なdubBuildTypeが指定された場合 | showErrorMessageで通知 |
| d.ext.config.invalid.compiler | エラー | 無効なdubCompilerが指定された場合 | showErrorMessageで通知 |

### リトライ仕様

リトライは行わない。

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

トランザクションは存在しない。

## パフォーマンス要件

設定変更処理自体は軽量だが、doStartupが呼ばれる場合はプロジェクト初期化の時間がかかる。処理時間はStopWatchで計測され、完了時にtraceログに出力される（extension.d 201-202行目）。

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

特になし。

## 備考

- changedConfig関数は@onConfigChangedアトリビュートでマークされ、ConfigHandlerミックスイン（extension.d 211行目）により自動的にディスパッチされる。
- configFinished関数（205-209行目）は@onConfigFinishedアトリビュートで、全ワークスペースの設定変更が完了した際に呼ばれる。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.d | `source/served/types.d` | Configuration構造体（74-268行目）: D, DFmt, DScanner等の全設定項目 |
| 1-2 | types.d | `source/served/types.d` | Workspace構造体（270-327行目）: config()プロパティ（320-326行目）で設定取得 |

**読解のコツ**: `@onConfigChanged`はserve-dのイベントシステムのアトリビュートで、設定変更時に自動的にこの関数が呼ばれる仕組みになっている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | extension.d | `source/served/extension.d` | changedConfig関数（59-203行目）: @onConfigChangedハンドラ |

**主要処理フロー**:
1. **67行目**: reportProgressで進捗通知
2. **69行目**: ensureStartedUpでグローバル初期化
3. **71-93行目**: ワークスペースの特定と妥当性チェック
4. **95-99行目**: 未初期化ワークスペースの自動初期化
5. **103-199行目**: 設定パス別のswitch処理

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | extension.d | `source/served/extension.d` | switch文（105-199行目）: 10種類の設定パスに対する処理分岐 |

**主要処理フロー**:
- **107-110行目**: d.stdlibPath → DCDにインポートパス追加
- **111-115行目**: d.projectImportPaths → DCDにプロジェクトインポートパス追加
- **116-137行目**: d.dubConfiguration → DUBビルド設定切り替え
- **138-143行目**: d.dubArchType → DUBアーキテクチャ切り替え
- **156-168行目**: d.enableAutoComplete → DCDサーバー起動/停止

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

```
changedConfig(target, paths, config)  [@onConfigChanged]
    |
    +-- reportProgress(ProgressType.configLoad, ...)
    +-- ensureStartedUp(config)
    +-- workspace(target.uri)
    +-- [未初期化時] doStartup(uri, config)
    |
    +-- [パス別処理]
        +-- d.stdlibPath → DCDComponent.addImports(...)
        +-- d.projectImportPaths → DCDComponent.addImports(...)
        +-- d.dubConfiguration → DubComponent.setConfiguration(...)
        +-- d.dubArchType → DubComponent.setArchType(...)
        +-- d.dubBuildType → DubComponent.setBuildType(...)
        +-- d.dubCompiler → DubComponent.setCompiler(...)
        +-- d.enableAutoComplete → lazyStartDCDServer(...) / stopServer()
        +-- d.enableLinting → dscanner.clear() / dub.clear()
        +-- d.enableStaticLinting → dscanner.clear()
        +-- d.enableDubLinting → dub.clear()
```

### データフロー図

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

ConfigWorkspace  ─────> changedConfig()
  target.uri     ─────>   ワークスペース特定
string[] paths   ─────>   パス別switch処理
Configuration    ─────>   各コンポーネントへの反映 ─────> DCD/DUB/リンター状態更新
                                                  ─────> エラーメッセージ(showErrorMessage)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| extension.d | `source/served/extension.d` | ソース | changedConfig関数、configFinished関数の実装 |
| types.d | `source/served/types.d` | ソース | Configuration構造体、Workspace構造体の定義 |
| translate.d | `source/served/utils/translate.d` | ソース | エラーメッセージの翻訳 |
| progress.d | `source/served/utils/progress.d` | ソース | 進捗レポート送信 |
