# 機能設計書 51-コンパイラ切り替え

## 概要

本ドキュメントは、serve-dのLSPカスタムリクエスト `served/switchCompiler` の機能設計を記述する。DUBプロジェクトで使用するD言語コンパイラを切り替えるための機能である。

### 本機能の処理概要

**業務上の目的・背景**：D言語の開発では、DMD・LDC2・GDCなど複数のコンパイラが存在し、プロジェクトの要件に応じて使い分ける必要がある。本機能は、エディタ上からDUBのビルドコンパイラをリアルタイムに切り替え可能にすることで、開発者がIDEを離れることなくコンパイラの選択を変更できるようにする。

**機能の利用シーン**：開発者がLDC2での最適化ビルドをテストしたい場合や、DMDでのデバッグビルドに切り替えたい場合に、エディタのコマンドパレット等からコンパイラを切り替える際に使用される。

**主要な処理内容**：
1. クライアントから `served/switchCompiler` リクエストを受信する
2. アクティブなDUBインスタンスの存在を確認する
3. DubComponentの `setCompiler` メソッドを呼び出してコンパイラを切り替える
4. 切り替えの成否をbool値で返却する

**関連システム・外部連携**：workspace-dサブパッケージのDubComponentに処理を委譲する。DubComponentは内部でDUBのビルド設定を管理している。

**権限による制御**：特に権限による制御はない。アクティブなワークスペースインスタンスとDubComponentの存在が前提条件となる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 52 | コンパイラ切り替え（served/switchCompiler） | 主画面 | DUBのコンパイラを切り替えるリクエスト処理 |

## 機能種別

設定変更処理（DUBビルドコンパイラの切り替え）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value | string | Yes | 切り替え先のコンパイラ名（例: "dmd", "ldc2", "gdc"）。SwitchCompilerParams構造体またはstring直接指定に対応 | なし（DubComponent側で検証） |

### 入力データソース

LSPクライアントからのJSON-RPCリクエスト。SwitchCompilerParamsはSingleValueParams!string mixinを使用しており、`{"value": "dmd"}` のような構造体形式と `"dmd"` のようなstring直接形式の両方をデシリアライズ可能。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | bool | コンパイラ切り替えの成否。trueなら成功、falseなら失敗（アクティブインスタンスまたはDubComponentがない場合を含む） |

### 出力先

LSPクライアントへのJSON-RPCレスポンス

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ SwitchCompilerParamsとしてデシリアライズ（string直接指定にも対応）
2. アクティブインスタンス確認
   └─ activeInstanceがnullまたはDubComponentを持たない場合はfalseを返却
3. コンパイラ切り替え実行
   └─ activeInstance.get!DubComponent.setCompiler(value) を呼び出し
4. 結果返却
   └─ setCompilerの戻り値（bool）をそのまま返却
```

### フローチャート

```mermaid
flowchart TD
    A[served/switchCompiler リクエスト受信] --> B{activeInstance が有効?}
    B -->|No| C[false を返却]
    B -->|Yes| D{DubComponent を保持?}
    D -->|No| C
    D -->|Yes| E[DubComponent.setCompiler を呼出]
    E --> F[結果を bool で返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-51-01 | アクティブインスタンス必須 | アクティブなWorkspaceDインスタンスが存在しない場合はfalseを返却する | 常時 |
| BR-51-02 | DubComponent必須 | アクティブインスタンスがDubComponentを保持していない場合はfalseを返却する | 常時 |
| BR-51-03 | コンパイラ名の受け入れ | DubComponentの内部でコンパイラ名の妥当性を判定する | コンパイラ切り替え時 |

### 計算ロジック

特になし。

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

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

本機能はデータベースを使用しない。DubComponentのインメモリ状態を変更する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 暗黙的失敗 | activeInstanceがnullの場合 | falseを返却 |
| - | 暗黙的失敗 | DubComponentが存在しない場合 | falseを返却 |
| - | 暗黙的失敗 | setCompilerが失敗した場合 | setCompilerの結果（false）をそのまま返却 |

### リトライ仕様

リトライは不要。失敗時はクライアント側で再度リクエストを送信する。

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

トランザクション管理は不要。インメモリ状態の変更のみ。

## パフォーマンス要件

即時応答が期待される。DubComponentのsetCompilerはインメモリ操作であり、遅延は発生しない。

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

特になし。LSPプロトコルのセキュリティモデルに準拠する。

## 備考

- コンパイラ切り替え後、ビルドタスク（No.56）やDUBビルド診断（No.36）の結果は新しいコンパイラ設定を使用する
- コンパイラ名の取得にはNo.50（served/getCompiler）を使用する
- SwitchCompilerParamsはSingleValueParams mixinにより、JSON-RPCの柔軟なデシリアライズに対応している

---

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

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

### 推奨読解順序

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

SwitchCompilerParamsの構造とSingleValueParams mixinの仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protoext.d | `source/served/lsp/protoext.d` | SwitchCompilerParams構造体（519-523行目）がSingleValueParams!string mixinを使用していることを確認 |
| 1-2 | protoext.d | `source/served/lsp/protoext.d` | SingleValueParams mixin（422-488行目）のデシリアライズロジック。構造体形式とstring直接形式の両方をサポートする仕組み |

**読解のコツ**: D言語のmixin templateはコンパイル時にコードを展開する機構である。`mixin SingleValueParams!string` により、SwitchCompilerParamsに `value` フィールドと `alias _implicitValue this`（暗黙の変換）、そしてカスタムデシリアライザが追加される。

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

served/switchCompilerリクエストのハンドラ関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dub.d | `source/served/commands/dub.d` | switchCompiler関数（124-130行目）がリクエストハンドラとして登録されている |

**主要処理フロー**:
1. **124行目**: `@protocolMethod("served/switchCompiler")` - LSPメソッド登録デコレータ
2. **125行目**: `bool switchCompiler(SwitchCompilerParams value)` - パラメータの受取とbool返却
3. **127-128行目**: activeInstanceとDubComponentの存在チェック。なければfalse返却
4. **129行目**: `activeInstance.get!DubComponent.setCompiler(value)` - DubComponentへの委譲。SingleValueParamsの `alias _implicitValue this` により、SwitchCompilerParamsがstringとして暗黙に変換される

#### Step 3: 共通パターンを理解する

activeInstanceとDubComponentの取得パターンは、本ファイル内の多くの関数で共通している。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | types.d | `source/served/types.d` | activeInstanceプロパティ（463-474行目）の定義。WorkspaceD.Instanceのグローバルな参照 |

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

```
switchCompiler(SwitchCompilerParams) [source/served/commands/dub.d:125]
    |
    +-- activeInstance [source/served/types.d:471]
    |
    +-- activeInstance.has!DubComponent [workspace-d API]
    |
    +-- activeInstance.get!DubComponent [workspace-d API]
    |       |
    |       +-- DubComponent.setCompiler(value) [workspace-d内部]
    |
    +-- return bool
```

### データフロー図

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

SwitchCompilerParams     -->  switchCompiler()                 -->  bool (成否)
  (value: string)              |
                               +-- activeInstance確認
                               +-- DubComponent.setCompiler()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dub.d | `source/served/commands/dub.d` | ソース | switchCompiler関数の実装（124-130行目） |
| protoext.d | `source/served/lsp/protoext.d` | ソース | SwitchCompilerParams構造体定義（519-523行目）、SingleValueParams mixin（422-488行目） |
| types.d | `source/served/types.d` | ソース | activeInstanceプロパティ、backend定義 |
| extension.d | `source/served/extension.d` | ソース | LSPプロトコルメソッドのルーティング基盤 |
