# 画面設計書 2-グローバルスタートアップ

## 概要

本ドキュメントは、serve-d LSPサーバーにおけるグローバルスタートアップ処理の画面設計書である。サーバー初期化完了後に各コンポーネント（DCD, DScanner, dfmt, DlangUI等）をグローバルに登録・初期化し、プログレス通知をクライアントに送信する。

### 本画面の処理概要

**業務上の目的・背景**：serve-dはD言語のコード補完、静的解析、フォーマットなど多数の機能を提供するが、これらの機能はそれぞれ独立したコンポーネント（DCD, DScanner, dfmt等）として実装されている。グローバルスタートアップは、これらのコンポーネントを一括でバックエンドに登録し、全ワークスペースで利用可能にする処理である。また、DCDが古い場合にはユーザーに更新を促すダイアログをトリガーする重要な判断点でもある。

**画面へのアクセス方法**：`initialize` 完了後、最初の `workspace/didChangeConfiguration` 通知を受信した際に `changedConfig` -> `ensureStartedUp` -> `doGlobalStartup` の順で自動的に呼び出される。一度だけ実行される（`startedUp` フラグで制御）。

**主要な操作・処理内容**：
1. グローバル設定（DUBコンパイラ、DCDパス、DMDパス等）をバックエンドに設定する
2. 進捗通知 `ProgressType.globalStartup` をクライアントに送信する
3. DubComponent, FSWorkspaceComponent, DCDComponent等の全コンポーネントをバックエンドに登録する
4. デフォルトスニペットの登録を行う（設定により）
5. DCDが古い/未インストールの場合、DCD更新確認ダイアログ（No.4）をトリガーする
6. `onRegisteredComponents` イベントを発行する

**画面遷移**：
- 遷移元：No.1 LSPサーバー初期化（initialize） → changedConfig → ensureStartedUp
- 遷移先：No.4 DCD更新確認ダイアログ（DCDが古い場合）、No.3 ワークスペーススタートアップ

**権限による表示制御**：なし。サーバー内部処理のため権限制御は存在しない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | 初期化 (initialize) | 補助機能 | initialize完了後にensureStartedUp経由でグローバルスタートアップが呼び出される |
| 63 | DCD更新 (served/updateDCD) | 遷移先機能 | DCDが古い場合にDCD更新処理をトリガーする |
| 82 | 進捗レポート | 補助機能 | グローバルスタートアップの進捗状況をクライアントに通知する |

## 画面種別

サーバー内部処理（バックグラウンド初期化 + クライアントへの進捗通知）

## URL/ルーティング

明示的なLSPメソッドではない。`changedConfig` -> `ensureStartedUp` -> `doGlobalStartup` の内部呼び出しチェーンで実行される。

## 入出力項目

### 入力

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| config | UserConfiguration | はい | ユーザー設定（DCD/DMDパス、コンパイラ設定等） |

### 出力（クライアントへの通知）

| 項目名 | 種別 | 説明 |
|--------|------|------|
| progress通知 | ログ出力 | `[progress] [globalStartup]: Initializing serve-d...` |
| DCD更新ダイアログ | requestMessage | DCDが古い場合にエラーメッセージ + 選択肢を表示 |

## 表示項目

### 登録されるコンポーネント一覧

| 順序 | コンポーネント名 | 即時初期化 | 説明 |
|------|---------------|-----------|------|
| 1 | DubComponent | false（遅延） | DUBパッケージマネージャ連携 |
| 2 | FSWorkspaceComponent | false（遅延） | ファイルシステムベースのワークスペース |
| 3 | DCDComponent | true | D言語コード補完デーモン |
| 4 | DCDExtComponent | true | DCD拡張機能 |
| 5 | DMDComponent | true | DMDコンパイラ連携 |
| 6 | DscannerComponent | true | D-Scanner静的解析 |
| 7 | DfmtComponent | true | dfmtフォーマッタ |
| 8 | DlanguiComponent | true | DlangUI連携 |
| 9 | ImporterComponent | true | インポート管理 |
| 10 | ModulemanComponent | true | モジュール管理 |
| 11 | SnippetsComponent | true | スニペット管理 |
| 12 | IndexComponent | true | インデックス管理 |
| 13 | ReferencesComponent | true | 参照検索 |

## イベント仕様

### 1-グローバルスタートアップ開始

1. `ensureStartedUp` が呼ばれ、`startedUp` フラグがfalseの場合のみ `doGlobalStartup` を実行
2. グローバル設定をバックエンドに適用（DUBコンパイラ、DCD client/serverパス、DMDパス、ポート9166）
3. `reportProgress(ProgressType.globalStartup, 0, 0, "Initializing serve-d...")` でクライアントに進捗通知

### 2-コンポーネント登録

1. 13個のコンポーネントを順次バックエンドに登録
2. DubComponentとFSWorkspaceComponentは `false` 引数で遅延登録
3. その他のコンポーネントはデフォルト（即時）登録

### 3-スニペット登録

1. `registerDefaultSnippets` が `true` の場合、`SnippetsComponent.registerBuiltinDependencySnippets()` を実行
2. SnippetsComponentの初期化に失敗していた場合はエラーログを出力

### 4-DCD更新判定

1. DCDComponentが存在しない、またはDCDが古い(`isOutdated`)場合に更新フローに入る
2. `config.d.aggressiveUpdate` が `true` の場合: 自動的に `updateDCD` をファイバーで実行
3. `config.d.aggressiveUpdate` が `false` の場合: ユーザーに選択肢ダイアログを表示（No.4へ遷移）

### 5-コンポーネント登録完了イベント

1. `onRegisteredComponents` イベントを発行し、登録済みコンポーネントを通知

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

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

本画面ではデータベースへのアクセスは発生しない。

| 操作（イベント） | 対象データ | 操作種別 | 概要 |
|----------------|-----------|---------|------|
| グローバルスタートアップ | backend.globalConfiguration | 初期化 | バックエンドのグローバル設定を構成 |
| コンポーネント登録 | backend（コンポーネントレジストリ） | 登録 | 各コンポーネントをバックエンドに登録 |
| DCD更新判定 | dcdUpdating（フラグ） | 更新 | DCD更新中フラグの設定 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|------------|------|--------------|----------|
| d.served.outdatedDCD | error | "DCD is outdated. (target={0}, installed={1})" | DCDが古いまたは未インストールの場合 |
| d.ext.compileProgram | アクションボタン | "Compile {0}" | ソースからビルドする場合の選択肢 |
| d.ext.downloadProgram | アクションボタン | "Download {0}" | バイナリをダウンロードする場合の選択肢 |
| d.served.ignoreDCDUpdate | アクションボタン | "Continue anyway" | DCD更新を無視する選択肢 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| コンポーネント登録中に例外発生 | エラーログを出力し、可能な範囲で処理を継続する（try-catchで囲まれている） |
| SnippetsComponent初期化失敗 | エラーログ "SnippetsComponent failed to initialize, can't register default snippets" を出力 |
| doGlobalStartup全体の例外 | "Failed to fully globally initialize" メッセージをエラーログに出力 |

## 備考

- `ensureStartedUp` は `__gshared bool startedUp` フラグで一度だけの実行を保証している
- DubComponentとFSWorkspaceComponentが遅延登録（`false`引数）なのは、ワークスペースごとにインスタンス化されるため
- DCDのデフォルトポートは9166
- `aggressiveUpdate` のデフォルト値は `false`（code-dのデフォルト設定とは意図的に異なる）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.d | `source/served/types.d` | `Configuration` 構造体（74行目〜）の `D` 内部構造体で `aggressiveUpdate`, `dcdClientPath`, `dcdServerPath` 等の設定項目を確認 |
| 1-2 | progress.d | `source/served/utils/progress.d` | `ProgressType.globalStartup`（20行目）の定義を確認 |

**読解のコツ**: `UserConfiguration` は `Configuration` のエイリアスである（types.d 72行目）。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | extension.d | `source/served/extension.d` | `ensureStartedUp` 関数（354行目〜361行目）が呼び出しの起点。`startedUp` フラグで一度だけ `doGlobalStartup` を呼ぶ |
| 2-2 | extension.d | `source/served/extension.d` | `doGlobalStartup` 関数（363行目〜484行目）が主処理 |

**主要処理フロー**:
1. **371-385行目**: グローバル設定の構築（dub, dcd, dmd セクション）
2. **389行目**: `reportProgress(ProgressType.globalStartup, 0, 0, "Initializing serve-d...")`
3. **392-416行目**: 13個のコンポーネントを順次登録
4. **418-424行目**: デフォルトスニペット登録
5. **426-473行目**: DCD更新判定とダイアログ表示ロジック
6. **475行目**: `onRegisteredComponents` イベント発行

#### Step 3: DCD更新判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | extension.d | `source/served/extension.d` | 426行目〜473行目のDCD更新判定ブロック。`isOutdated` チェックと `aggressiveUpdate` による分岐を確認 |
| 3-2 | translate.d | `source/served/utils/translate.d` | `translate!` テンプレート関数（41行目〜）による翻訳メッセージ解決の仕組み |
| 3-3 | en.txt | `views/en.txt` | 174行目: "d.served.outdatedDCD", 101行目: "d.ext.compileProgram", 102行目: "d.ext.downloadProgram" |

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

```
changedConfig(ConfigWorkspace, string[], Configuration)
    │
    └─ ensureStartedUp(config)  [354行目]
           │
           └─ doGlobalStartup(config)  [363行目]
                  │
                  ├─ backend.globalConfiguration.base 設定  [375-385行目]
                  │
                  ├─ reportProgress(globalStartup)  [389行目]
                  │
                  ├─ backend.register!DubComponent(false)  [392行目]
                  ├─ backend.register!FSWorkspaceComponent(false)  [394行目]
                  ├─ backend.register!DCDComponent  [396行目]
                  ├─ ... (他10コンポーネント)  [398-416行目]
                  │
                  ├─ SnippetsComponent.registerBuiltinDependencySnippets()  [423行目]
                  │
                  ├─ DCD更新判定  [426-473行目]
                  │      ├─ aggressiveUpdate=true → spawnFiber("updateDCD")
                  │      └─ aggressiveUpdate=false → rpc.window.requestMessage()
                  │             ├─ "Compile/Download" → spawnFiber("updateDCD")
                  │             └─ "Continue anyway" → ignoreOutdatedForSession()
                  │
                  └─ emitExtensionEvent!onRegisteredComponents  [475行目]
```

### データフロー図

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

UserConfiguration ──▶ doGlobalStartup() ──────────────▶ 進捗通知（globalStartup）
  .d.dubCompiler          │                              DCD更新ダイアログ
  .dcdClientPath          ├─ globalConfiguration設定      onRegisteredComponentsイベント
  .dcdServerPath          ├─ コンポーネント登録（13個）
  .d.dmdPath              ├─ スニペット登録
  .d.aggressiveUpdate     └─ DCD更新判定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| extension.d | `source/served/extension.d` | ソース | doGlobalStartup関数、ensureStartedUp関数の実装 |
| types.d | `source/served/types.d` | ソース | Configuration構造体、UserConfiguration型エイリアス |
| progress.d | `source/served/utils/progress.d` | ソース | ProgressType列挙型、reportProgress関数 |
| translate.d | `source/served/utils/translate.d` | ソース | 翻訳機能（translate!テンプレート） |
| en.txt | `views/en.txt` | リソース | 英語翻訳メッセージ定義 |
| dcd_update.d | `source/served/commands/dcd_update.d` | ソース | updateDCD関数（DCD更新処理本体） |
