# serve-d コードリーディングガイドライン

## はじめに

このガイドラインは、serve-dのコードベースを効率的に理解するための手引きです。
D言語に精通していないエンジニアでも、段階的に学習できるよう構成されています。

serve-dは、Microsoft Language Server Protocol (LSP) のD言語向け実装であり、code-dなどのエディタ拡張機能のバックエンドとして動作するサーバーアプリケーションです。

**対象読者:**
- プロジェクトに新規参画するエンジニア
- 他言語からの経験者
- コードレビューを行う担当者

---

## 1. 言語基礎

> このセクションでは、D言語の基本構文と概念を解説します。

### 1.1 プログラム構造

D言語のソースファイルは `.d` 拡張子を持ち、ファイル先頭に `module` 宣言を記述します。モジュール名はディレクトリ構造と対応します。

```d
// ファイル: source/served/types.d:1
module served.types;
```

この宣言は、ファイルが `served.types` というモジュール名で識別されることを意味します。`source/served/types.d` というパスに対応しています。

エントリーポイントは `main` 関数です。

```d
// ファイル: source/app.d:77-78
int main(string[] args)
{
```

### 1.2 データ型と変数

D言語は静的型付け言語であり、C/C++に類似した型システムを持ちます。本プロジェクトでは特に以下の型が頻出します。

**構造体 (struct):** 値型のデータ構造。

```d
// ファイル: source/served/types.d:74-76
@serdeIgnoreUnexpectedKeys
struct Configuration
{
@serdeIgnoreUnexpectedKeys:
@serdeOptional:

    struct D
    {
        @serdeOptional:
        Nullable!(string, string[]) stdlibPath = Nullable!(string, string[])("auto");
        string dcdClientPath = "dcd-client", dcdServerPath = "dcd-server";
```

**enum:** 列挙型。文字列値を持つenumが多用されます。

```d
// ファイル: source/served/types.d:57-62
enum ManyProjectsAction : string
{
    ask = "ask",
    skip = "skip",
    load = "load"
}
```

**Nullable:** 値がnullになりうることを型で表現するラッパー型。

```d
// ファイル: source/served/types.d:82
Nullable!(string, string[]) stdlibPath = Nullable!(string, string[])("auto");
```

### 1.3 制御構造

D言語の制御構造はC/C++とほぼ同じです。特徴的なのは `static foreach` と `static if` です。

**static foreach:** コンパイル時にループを展開します。

```d
// ファイル: source/app.d:97-102
static foreach (levelName; __traits(allMembers, LogLevel))
{
case levelName:
    globalLogLevel = __traits(getMember, LogLevel, levelName);
    return;
}
```

**static if:** コンパイル時に条件分岐を行います。

```d
// ファイル: source/app.d:82-85
static if (__VERSION__ < 2101)
    sharedLog = new FileLogger(io.stderr);
else
    sharedLog = (() @trusted => cast(shared) new FileLogger(io.stderr))();
```

**version:** プラットフォームやビルド設定による条件コンパイルを行います。

```d
// ファイル: source/app.d:57-70
version (AArch64)
    string arch = "aarch64";
else version (ARM)
    string arch = "arm";
else version (X86_64)
    string arch = "x86_64";
```

### 1.4 関数/メソッド定義

D言語の関数定義はC/C++に類似しています。クラスメソッドもCのような形式で定義されます。

```d
// ファイル: workspace-d/source/workspaced/com/dfmt.d:37-48
string formatSync(scope const(char)[] code, string[] arguments = [])
{
    if (!code.strip.length)
        return null;

    Config config = parseConfig(arguments);
    auto output = appender!string;
    fmt("stdin", cast(ubyte[]) code, output, &config);
    if (output.data.length)
        return output.data;
    else
        return code.idup;
}
```

**特徴的なアノテーション:** `@property`, `nothrow`, `@nogc`, `@safe`, `@trusted`, `scope` などの属性が関数に付与されます。

```d
// ファイル: workspace-d/source/workspaced/api.d:32
alias ImportPathProvider = string[] delegate() nothrow;
```

### 1.5 モジュール/インポート

D言語のインポートシステムは以下の形式で記述します。

**基本インポート:**

```d
// ファイル: source/app.d:18-33
import core.thread;
import core.sync.mutex;

import fs = std.file;
import io = std.stdio;
import std.algorithm;
import std.conv;
```

**エイリアス付きインポート:** `import fs = std.file;` のように別名を付けることで、名前空間の衝突を回避できます。本プロジェクトでは `fs` (ファイルシステム) と `io` (標準入出力) のエイリアスが全域で使われています。

**選択的インポート:** 特定のシンボルだけをインポートする形式。

```d
// ファイル: source/served/commands/complete.d:10-11
import workspaced.com.dfmt : DfmtComponent;
import workspaced.com.dcd;
```

**public import:** インポート元の全シンボルを再エクスポートします。

```d
// ファイル: source/served/extension.d:35-53
public import served.commands.calltips;
public import served.commands.code_actions;
public import served.commands.code_lens;
```

**static import:** 完全修飾名でのみアクセスを許可するインポート。

```d
// ファイル: source/served/types.d:10
static import served.extension;
```

---

## 2. プロジェクト固有の概念

> このセクションでは、当プロジェクト特有の概念を解説します。

### 2.1 フレームワーク固有の概念

#### Language Server Protocol (LSP)

本プロジェクトはMicrosoft Language Server Protocol (LSP) のD言語実装です。LSPは、エディタ/IDE (クライアント) と言語サーバー (サーバー) の間の通信プロトコルを標準化するものです。主要な概念は以下の通りです。

- **Request/Response:** クライアントからのリクエストに対してサーバーがレスポンスを返す
- **Notification:** 一方向の通知 (レスポンス不要)
- **JSON-RPC:** 通信はJSON-RPCプロトコルで行われる (stdin/stdout経由)

#### DUBパッケージマネージャ

D言語のビルドシステム兼パッケージマネージャです。本プロジェクトは `dub.json` (トップレベル) と `dub.sdl` (サブパッケージ) の2形式を使用しています。

```json
// ファイル: dub.json:1-5
{
    "name": "serve-d",
    "description": "Microsoft Language Server Protocol library and D Server",
    "license": "MIT",
    "copyright": "Copyright 2017-2023, webfreak",
```

#### DCD (D Completion Daemon)

D言語のコード補完やシンボル検索を提供するバックエンドツールです。serve-dはDCDをコンポーネントとして内部で使用しています。

#### D-Scanner / dfmt

それぞれD言語の静的解析ツールとコードフォーマッタです。ライブラリとしてserve-d内にバンドル (コンパイル時に組み込み) されています。

### 2.2 プロジェクト独自のパターン

#### コンポーネントシステム

workspace-dサブパッケージは、各機能を「コンポーネント」として独立した単位で管理します。コンポーネントは `@component` UDAで宣言され、`ComponentWrapper` を継承します。

```d
// ファイル: workspace-d/source/workspaced/com/dcd.d:26-29
@component("dcd")
class DCDComponent : ComponentWrapper
{
    mixin DefaultComponentWrapper;
```

コンポーネントには以下の2種類があります。

- **グローバルコンポーネント:** `@globalOnly` UDA付き。全ワークスペースで共有 (例: `DfmtComponent`, `ImporterComponent`)
- **インスタンスコンポーネント:** `@instancedOnly` UDA付き。ワークスペースごとに独立 (例: `DubComponent`, `FSWorkspaceComponent`)

#### UDA (User Defined Attribute) による宣言的プログラミング

LSPメソッドのルーティングは、UDAで宣言的に行われます。

```d
// ファイル: source/served/commands/dub.d:25-26
@protocolMethod("served/listConfigurations")
string[] listConfigurations()
```

主要なUDAは以下の通りです。

| UDA | 用途 | 定義場所 |
|-----|------|---------|
| `@protocolMethod` | LSPリクエストハンドラの登録 | `serverbase/source/served/utils/events.d:14` |
| `@protocolNotification` | LSP通知ハンドラの登録 | `serverbase/source/served/utils/events.d:33` |
| `@postProtocolMethod` | リクエスト処理後のフック | `serverbase/source/served/utils/events.d:19` |
| `@initializeHook` | 初期化時のフック | `serverbase/source/served/utils/events.d:63` |
| `@onConfigChanged` | 設定変更時のフック | `source/served/extension.d:59` |
| `@component` | コンポーネント名の宣言 | `workspace-d/source/workspaced/api.d:70` |
| `@globalOnly` | グローバルコンポーネント指定 | `workspace-d/source/workspaced/api.d:53` |
| `@instancedOnly` | インスタンスコンポーネント指定 | `workspace-d/source/workspaced/api.d:58` |

#### Future / Fiber による非同期処理

重い処理は `Future(T)` パターンで非同期化され、`Fiber` (コルーチン) で並行実行されます。

```d
// ファイル: workspace-d/source/workspaced/future.d:9-17
class Future(T)
{
    import core.thread : Fiber, Thread;

    static if (!is(T == void))
        private T value;
    Throwable exception;
    bool has;
    void delegate() _onDone;
```

非同期メソッドは `.getYield` で結果を取得しつつ、ファイバーをyieldして他のタスクに実行を譲ります。

```d
// ファイル: source/served/commands/definition.d:27
auto result = instance.get!DCDComponent.findDeclaration(doc.rawText, bytes).getYield;
```

#### mixin テンプレート

D言語のmixinテンプレートは、共通コードをテンプレート化して複数箇所に「混入」させる仕組みです。

```d
// ファイル: workspace-d/source/workspaced/com/dcd.d:29
mixin DefaultComponentWrapper;
```

```d
// ファイル: source/served/types.d:25
mixin LanguageServerRouter!(served.extension, lsConfig) lspRouter;
```

この `LanguageServerRouter` は `serverbase/source/served/serverbase.d:65` で定義されたmixinテンプレートであり、LSPサーバーのコア機能(リクエストルーティング、RPC処理、ファイバスケジューラなど)を生成します。

---

## 3. 命名規則

> このセクションでは、プロジェクト全体で使用される命名規則を解説します。

### 3.1 ファイル・ディレクトリ命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `snake_case.d` | 通常のソースファイル | `code_actions.d`, `lazy_workspaced.d` |
| `package.d` | D言語のパッケージファイル (ディレクトリのindex) | `workspace-d/source/workspaced/com/snippets/package.d` |
| `_basic.d`, `_package_tests.d` | テスト用ファイル (アンダースコアプレフィックス) | `test/data/list_definition/_basic.d` |
| `dub.json` / `dub.sdl` | DUBパッケージマニフェスト | トップレベル: `dub.json`, サブパッケージ: `dub.sdl` |
| `tc_*` | テストケースディレクトリ | `test/tc_fsworkspace/`, `test/tc_dub/` |

### 3.2 クラス・関数・変数命名

| プレフィックス/サフィックス | 意味 | 例 |
|---------------------------|------|-----|
| `*Component` | workspace-dのコンポーネントクラス | `DCDComponent`, `DubComponent`, `DfmtComponent` |
| `*Wrapper` | ラッパー基底クラス | `ComponentWrapper` |
| `provide*` / `list*` | LSPリクエストハンドラ関数 | `provideCodeActions`, `listConfigurations` |
| `*Params` | リクエストパラメータ型 | `CodeActionParams`, `RenameParams` |
| `do*` | 実行系フラグ | `doCompleteSnippets`, `doTrackTests` |
| `let*` | 許可系フラグ | `letEditorDownload` |
| `*Sync` | 同期版関数 | `formatSync` |
| `get*` | 取得系関数 | `getConfig`, `getBuildType` |
| `switch*` | 切替系関数 | `switchConfig`, `switchArchType` |
| `is*` / `has*` | 判定系関数 | `isValidDIdentifier`, `has!DCDComponent` |
| `on*` | イベントハンドラ / コールバック | `onConfigChanged`, `onLazyLoad` |
| `*Provider` | データ提供者 | `importPathProvider`, `SnippetProvider` |
| `*Id` / `*ID` | 識別子型 | `WarningId`, `DocumentUri` |

### 3.3 プログラム分類一覧

| 分類 | モジュールプレフィックス | 説明 |
|------|------------------------|------|
| LSPコマンド | `served.commands.*` | LSPリクエスト/通知のハンドラ実装 |
| リンター | `served.linters.*` | D-Scanner, dfmt, dubによるコード解析 |
| ユーティリティ | `served.utils.*` | 共通ヘルパー、非同期処理、翻訳 |
| バックエンド | `served.backend.*` | LazyWorkspaceD等のバックエンド管理 |
| IO | `served.io.*` | ファイルシステム、HTTP通信 |
| LSP基盤 | `served.lsp.*` | JSON-RPC、プロトコル型定義 |
| ワーカー | `served.workers.*` | バックグラウンド処理 (GCプロファイラ等) |
| コンポーネント | `workspaced.com.*` | workspace-dの各機能コンポーネント |
| ビジター | `workspaced.visitors.*` | DParse ASTのビジターパターン実装 |

---

## 4. ディレクトリ構造

> このセクションでは、プロジェクトのディレクトリ構造を解説します。

```
serve-d-master/
+-- source/                      # メインアプリケーション (serve-d本体)
|   +-- app.d                    # エントリーポイント
|   +-- crash_handler.d          # クラッシュハンドラ (バックトレース)
|   +-- served/
|   |   +-- extension.d          # LSP拡張機能の中核、初期化とコマンドディスパッチ
|   |   +-- info.d               # バージョン情報
|   |   +-- types.d              # 共通型定義、Configuration、LSPルーター生成
|   |   +-- commands/            # LSPリクエスト/通知ハンドラ群
|   |   +-- linters/             # リンター統合 (DScanner, dfmt, dub)
|   |   +-- lsp/                 # LSPプロトコル拡張型
|   |   +-- backend/             # LazyWorkspaceD (遅延ロード)
|   |   +-- io/                  # IO関連 (HTTP, ファイルシステム, git)
|   |   +-- utils/               # ユーティリティ (翻訳, ddoc, 進捗, トレース)
|   |   +-- workers/             # バックグラウンドワーカー
|   +-- external/                # 外部ツール設定 (ldc)
+-- serverbase/                  # [サブパッケージ] LSPサーバー基盤フレームワーク
|   +-- source/served/
|       +-- serverbase.d         # LanguageServerRouter mixinテンプレート
|       +-- utils/               # イベント処理, ファイバ管理, 非同期処理
+-- lsp/                         # [サブパッケージ] LSPプロトコル型とRPC基盤
|   +-- source/served/lsp/
|       +-- jsonrpc.d            # RPCProcessor (JSON-RPC通信)
|       +-- filereader.d         # ファイルリーダー (stdin読み取り)
|       +-- textdocumentmanager.d # テキストドキュメント管理
+-- protocol/                    # [サブパッケージ] LSPプロトコル型定義のみ
+-- workspace-d/                 # [サブパッケージ] D言語ワークスペース機能の実装
|   +-- source/workspaced/
|       +-- api.d                # コンポーネントAPI基盤、WorkspaceD定義
|       +-- backend.d            # Configuration、WorkspaceD.Instance
|       +-- coms.d               # 全コンポーネントの公開インポート集約
|       +-- future.d             # Future(T)非同期パターン
|       +-- helpers.d            # ヘルパー関数
|       +-- com/                 # 各機能コンポーネント
|       +-- visitors/            # AST解析ビジター
|       +-- completion/          # 補完機能
|       +-- dub/                 # dub診断
+-- dcd/                         # [サブパッケージ] DCDクライアント通信
|   +-- source/served/dcd/
|       +-- client.d             # DCD直接通信クライアント
+-- http/                        # [サブパッケージ] HTTP通信
+-- views/                       # テンプレートファイル (翻訳テキスト等)
+-- test/                        # テストスイート
|   +-- tc_*/                    # 各機能のテストケース
|   +-- data/                    # テストデータ
+-- ci/                          # CI設定
+-- null_server/                 # NULLサーバー (テスト/デバッグ用)
+-- null_server_test/            # NULLサーバーのテスト
+-- index-utils/                 # インデックスユーティリティ
```

### 各ディレクトリの役割

| ディレクトリ | 役割 | 主要ファイル |
|-------------|------|-------------|
| `source/` | serve-d本体。LSPコマンドとワークスペース機能を繋ぐ | `app.d`, `served/extension.d`, `served/types.d` |
| `source/served/commands/` | 各LSPリクエスト/通知のハンドラ実装 | `complete.d`, `definition.d`, `code_actions.d`, `dub.d` |
| `source/served/linters/` | コード解析結果の統合管理 | `diagnosticmanager.d`, `dscanner.d`, `dub.d` |
| `serverbase/` | LSPサーバーの共通フレームワーク | `serverbase.d`, `utils/events.d`, `utils/fibermanager.d` |
| `lsp/` | JSON-RPC通信とLSPプロトコル型 | `jsonrpc.d`, `filereader.d`, `textdocumentmanager.d` |
| `protocol/` | LSPプロトコル型定義のみ (依存最小) | - |
| `workspace-d/` | D言語処理の中核実装 | `api.d`, `backend.d`, `com/dcd.d`, `com/dub.d` |
| `workspace-d/source/workspaced/com/` | 個別機能コンポーネント | `dcd.d`, `dfmt.d`, `dscanner.d`, `dub.d`, `snippets/` |
| `dcd/` | DCD直接通信クライアント | `client.d` |
| `http/` | HTTP通信 (依存関係ダウンロード等) | - |
| `test/` | テストスイート | `tc_fsworkspace/`, `tc_dub/`, `tc_implement_interface/` |

---

## 5. アーキテクチャ

> このセクションでは、プロジェクトのアーキテクチャパターンを解説します。

### 5.1 全体アーキテクチャ

serve-dは**レイヤードアーキテクチャ**と**コンポーネントパターン**の組み合わせで構成されています。DUBのサブパッケージ機能により、各層が独立したパッケージとして分離されています。

```
                        [エディタ (VSCode, Vim等)]
                                |
                        stdin/stdout (JSON-RPC)
                                |
                    +==========================+
                    |   LSP層 (lsp/)           |
                    |   - RPCProcessor         |
                    |   - FileReader           |
                    |   - TextDocumentManager  |
                    +==========================+
                                |
                    +==========================+
                    |   サーバー基盤層          |
                    |   (serverbase/)           |
                    |   - LanguageServerRouter  |
                    |   - EventProcessor       |
                    |   - FiberManager         |
                    +==========================+
                                |
                    +==========================+
                    |   コマンド層 (source/)    |
                    |   - extension.d          |
                    |   - commands/*           |
                    |   - linters/*            |
                    +==========================+
                                |
                    +==========================+
                    |   バックエンド層          |
                    |   (workspace-d/)          |
                    |   - WorkspaceD           |
                    |   - ComponentWrapper     |
                    |   - 各種Component        |
                    +==========================+
                                |
                +--------+--------+--------+
                |        |        |        |
            [DCD]   [D-Scanner] [dfmt]   [dub]
```

### 5.2 レイヤー構成

| レイヤー | 責務 | 代表的なファイル |
|---------|------|-----------------|
| LSP通信層 | JSON-RPC通信の読み書き、メッセージのパース | `lsp/source/served/lsp/jsonrpc.d` |
| プロトコル型層 | LSPプロトコルの型定義 | `protocol/` |
| サーバー基盤層 | リクエストルーティング、ファイバスケジューリング、イベント処理 | `serverbase/source/served/serverbase.d` |
| コマンド層 | LSPリクエストの具体的なハンドリング、リンター統合 | `source/served/commands/`, `source/served/linters/` |
| バックエンド層 | D言語固有の処理 (補完、解析、フォーマット等) をコンポーネントとして提供 | `workspace-d/source/workspaced/com/` |
| ツール統合層 | 外部ツール (DCD, D-Scanner, dfmt, dub) との統合 | `dcd/`, `http/` |

### 5.3 データフロー

典型的なLSPリクエストのデータフローは以下の通りです。

1. **エディタ** -> stdin -> **RPCProcessor** (JSON-RPCメッセージ受信)
2. **RPCProcessor** -> **LanguageServerRouter** (UDAベースのメソッドディスパッチ)
3. **LanguageServerRouter** -> **コマンドハンドラ** (例: `provideCodeActions`)
4. **コマンドハンドラ** -> **WorkspaceD.Instance** -> **Component** (例: `DCDComponent.findDeclaration`)
5. **Component** -> 処理結果を `Future(T)` で返却
6. **コマンドハンドラ** -> `.getYield` で結果取得 -> LSPレスポンス構築
7. **RPCProcessor** -> stdout -> **エディタ** (JSON-RPCレスポンス送信)

---

## 6. 主要コンポーネント

> このセクションでは、主要なコンポーネントとその連携を解説します。

### 6.1 エントリーポイント

アプリケーションのエントリーポイントは `source/app.d` の `main` 関数です。

```d
// ファイル: source/app.d:77-78
int main(string[] args)
{
```

起動時の処理フロー:

1. ログ設定の初期化 (デバッグ時: trace, リリース時: info)
2. コマンドライン引数のパース (`--require`, `--provide`, `--version` 等)
3. `--provide` フラグに基づく機能の有効化 (`http`, `implement-snippets`, `context-snippets` 等)
4. `lspRouter.run()` でLSPサーバーのメインループを開始

```d
// ファイル: source/app.d:219
auto ret = lspRouter.run() ? 0 : 1;
```

`lspRouter` は `source/served/types.d:25` で定義されたmixinテンプレートインスタンスです。

```d
// ファイル: source/served/types.d:25
mixin LanguageServerRouter!(served.extension, lsConfig) lspRouter;
```

### 6.2 ビジネスロジック

ビジネスロジックは主に2箇所に分かれています。

**コマンド層 (`source/served/commands/`):** LSPプロトコルとworkspace-dの橋渡し

各ファイルは特定のLSP機能を担当し、`@protocolMethod` UDAでルーティングされます。

| ファイル | 機能 |
|---------|------|
| `complete.d` | コード補完 |
| `definition.d` | 定義へのジャンプ |
| `code_actions.d` | コードアクション (クイックフィックス等) |
| `rename.d` | リネーム |
| `references.d` | 参照検索 |
| `highlight.d` | ドキュメントハイライト |
| `format.d` | コードフォーマット |
| `dub.d` | DUB固有のカスタムリクエスト |
| `symbol_search.d` | シンボル検索 |
| `calltips.d` | シグネチャヘルプ |
| `code_lens.d` | コードレンズ |
| `folding.d` | コード折りたたみ |
| `inlay_hints.d` | インレイヒント |
| `test_provider.d` | テストディスカバリ |

**ワークスペース層 (`workspace-d/source/workspaced/com/`):** D言語処理の実装

| コンポーネント | 機能 | スコープ |
|--------------|------|---------|
| `DCDComponent` | コード補完、定義検索、シンボル検索 | インスタンス |
| `DCDExtComponent` | DCD拡張機能 (calltips、implementAll等) | インスタンス |
| `DubComponent` | DUBプロジェクト管理、ビルド設定 | インスタンスのみ |
| `DscannerComponent` | 静的解析、リンティング | インスタンス |
| `DfmtComponent` | コードフォーマット | グローバルのみ |
| `ImporterComponent` | インポート文の管理、追加 | グローバルのみ |
| `ModulemanComponent` | モジュール管理、リネーム | インスタンス |
| `FSWorkspaceComponent` | ファイルシステムベースのワークスペース | インスタンスのみ |
| `SnippetsComponent` | スニペット補完 | インスタンス |
| `IndexComponent` | コードインデックス | インスタンス |
| `ReferencesComponent` | 参照検索 | インスタンス |
| `ClangCompilationDatabaseComponent` | Clangコンパイルデータベース | インスタンス |

### 6.3 データアクセス

本プロジェクトはデータベースを使用しません。データアクセスは以下の形態です。

**テキストドキュメント管理:**

```d
// ファイル: source/served/types.d:54
alias documents = lspRouter.documents;
```

`TextDocumentManager` がエディタで開かれているファイルの内容をメモリ上で管理します。

**DUBプロジェクト設定:**

`DubComponent` がDUBのプロジェクトファイル (`dub.json` / `dub.sdl`) を読み込み、ビルド設定やインポートパスを管理します。

```d
// ファイル: workspace-d/source/workspaced/com/dub.d:57-80
protected void load()
{
    if (!refInstance)
        throw new Exception("dub requires to be instanced");

    if (config.get!bool("dub", "registerImportProvider", true))
        importPathProvider = &imports;
```

### 6.4 ユーティリティ/共通機能

**翻訳システム:**

多言語対応のUIメッセージ翻訳。`views/` ディレクトリに翻訳ファイル (en.txt, de.txt, fr.txt, ja.txt, ru.txt) が配置されています。

```d
// ファイル: source/served/utils/translate.d:16-22
shared static this()
{
    translations = [
        "en": parseTranslation!(import("en.txt")),
        "de": parseTranslation!(import("de.txt")),
        "fr": parseTranslation!(import("fr.txt")),
        "ja": parseTranslation!(import("ja.txt")),
        "ru": parseTranslation!(import("ru.txt")),
    ];
}
```

**診断マネージャ:**

複数のリンター (DScanner, dub, dfmt) からの診断結果を統合して管理します。

```d
// ファイル: source/served/linters/diagnosticmanager.d:9-11
enum NumDiagnosticProviders = 3;
alias DiagnosticCollection = PublishDiagnosticsParams[];
DiagnosticCollection[NumDiagnosticProviders] diagnostics;
```

**LazyWorkspaceD:**

コンポーネントの遅延ロードを実現するWorkspaceDの拡張です。コンポーネントが初めてアクセスされたときにのみロードされます。

```d
// ファイル: source/served/backend/lazy_workspaced.d:14-16
class LazyWorkspaceD : WorkspaceD
{
    static class LazyInstance : WorkspaceD.Instance
```

---

## 7. よく使われるパターン

> このセクションでは、コード内で頻出するパターンを解説します。

### パターン一覧

| パターン | 説明 | 出現頻度 | 代表的なファイル |
|---------|------|---------|-----------------|
| UDAベースルーティング | `@protocolMethod` 等でLSPメソッドを宣言的に登録 | 高 | `source/served/commands/*.d` |
| コンポーネントパターン | `@component` + `ComponentWrapper` | 高 | `workspace-d/source/workspaced/com/*.d` |
| Futureパターン | 非同期処理結果の遅延取得 | 高 | `workspace-d/source/workspaced/future.d` |
| mixinテンプレート | 共通コードの自動生成 | 高 | `serverbase/source/served/serverbase.d` |
| public import集約 | 関連モジュールの一括エクスポート | 中 | `workspace-d/source/workspaced/coms.d` |
| エイリアスインポート | `fs = std.file`, `io = std.stdio` | 高 | 全ソースファイル |
| 遅延ロード | LazyWorkspaceDによるオンデマンドロード | 中 | `source/served/backend/lazy_workspaced.d` |
| ビジターパターン | DParse ASTの走査 | 中 | `workspace-d/source/workspaced/visitors/` |

### 各パターンの詳細

#### パターン1: UDAベースルーティング

**目的:** LSPプロトコルメソッドと関数を宣言的にバインドし、ディスパッチを自動化する。

**実装例:**
```d
// ファイル: source/served/commands/dub.d:25-31
@protocolMethod("served/listConfigurations")
string[] listConfigurations()
{
    if (!activeInstance || !activeInstance.has!DubComponent)
        return null;
    return activeInstance.get!DubComponent.configurations;
}
```

**解説:** `@protocolMethod("served/listConfigurations")` UDAを付与するだけで、JSON-RPCで `served/listConfigurations` メソッドが呼ばれたときにこの関数が自動的にディスパッチされます。パラメータのデシリアライズとレスポンスのシリアライズは `LanguageServerRouter` の `EventProcessor` mixin が自動的に処理します。

#### パターン2: コンポーネントパターン

**目的:** D言語ツールの各機能を独立したコンポーネントとして管理し、必要に応じてワークスペースごとに動的にロード/アンロードする。

**実装例:**
```d
// ファイル: workspace-d/source/workspaced/com/dscanner.d:43-46
@component("dscanner")
class DscannerComponent : ComponentWrapper
{
    mixin DefaultComponentWrapper;
```

**解説:** `@component("dscanner")` でコンポーネント名を宣言し、`ComponentWrapper` を継承。`mixin DefaultComponentWrapper` でインスタンス管理の定型コードを自動生成。利用側では `instance.get!DscannerComponent` のようにテンプレート引数で取得します。

#### パターン3: Futureパターン

**目的:** 時間のかかる処理を非同期で実行し、結果が必要なタイミングでファイバーをyieldしつつ待機する。

**実装例:**
```d
// ファイル: workspace-d/source/workspaced/com/dfmt.d:30-33
Future!string format(scope const(char)[] code, string[] arguments = [])
{
    mixin(gthreadsAsyncProxy!`formatSync(code, arguments)`);
}
```

```d
// ファイル: source/served/commands/definition.d:27
auto result = instance.get!DCDComponent.findDeclaration(doc.rawText, bytes).getYield;
```

**解説:** `gthreadsAsyncProxy` mixinにより、同期関数をスレッドプールで実行するFutureを自動生成します。呼び出し側は `.getYield` を使うことで、結果が返るまでファイバーをyieldして他のリクエスト処理に実行を譲ります。

#### パターン4: public import集約

**目的:** 関連モジュールを1箇所でまとめてエクスポートし、利用側のインポート文を簡潔にする。

**実装例:**
```d
// ファイル: workspace-d/source/workspaced/coms.d:1-16
module workspaced.coms;

public import workspaced.com.ccdb : ClangCompilationDatabaseComponent;
public import workspaced.com.dcd : DCDComponent;
public import workspaced.com.dcdext : DCDExtComponent;
public import workspaced.com.dfmt : DfmtComponent;
public import workspaced.com.dlangui : DlanguiComponent;
public import workspaced.com.dmd : DMDComponent;
public import workspaced.com.dscanner : DscannerComponent;
public import workspaced.com.dub : DubComponent;
```

**解説:** `workspaced.coms` をインポートするだけで全コンポーネントにアクセスできます。同様に `source/served/extension.d` でも全コマンドモジュールをpublic importしています。

---

## 8. 業務フロー追跡の実践例

> このセクションでは、実際の業務フローをコードで追跡する方法を解説します。

### 8.1 フロー追跡の基本手順

1. エントリーポイントを特定 (`source/app.d` の `main` 関数)
2. LSPメソッド名から `@protocolMethod` UDAを検索
3. ハンドラ関数内で呼び出されるコンポーネントのメソッドを追跡
4. コンポーネント内の処理ロジックを確認
5. レスポンスの構築と返却を確認

### 8.2 フロー追跡の実例

#### 例1: コード補完リクエスト (textDocument/completion)

**概要:** エディタでユーザーが `.` を入力した際に、コード補完候補を返す処理。

**処理フロー:**
```
エディタ -> stdin -> RPCProcessor -> EventProcessor -> provideComplete -> DCDComponent.complete -> DCD処理 -> レスポンス -> stdout -> エディタ
```

**詳細な追跡:**

1. **JSON-RPCメッセージ受信** (`lsp/source/served/lsp/jsonrpc.d:19-28`)
   ```d
   class RPCProcessor : Fiber
   {
       this(FileReader reader, File writer)
       {
           super(&run, 4096 * 32);
           this.reader = reader;
           this.writer = writer;
       }
   ```

2. **リクエストディスパッチ** (`serverbase/source/served/serverbase.d:112-113`)
   ```d
   ResponseMessageRaw processRequest(RequestMessageRaw msg)
   {
   ```
   `EventProcessor` mixinが `@protocolMethod` UDAを持つ全関数をスキャンし、メソッド名に基づいてディスパッチします。

3. **補完ハンドラの実行** (`source/served/commands/complete.d`)
   `@protocolMethod("textDocument/completion")` が付与された関数がDCDComponentを利用して補完候補を取得します。DCDの結果を `convertFromDCDType` でLSP型に変換します。

   ```d
   // ファイル: source/served/commands/complete.d:41-78
   CompletionItemKind convertFromDCDType(string type)
   {
       if (type.length != 1)
           return CompletionItemKind.text;

       switch (type[0])
       {
       case 'c': // class name
           return CompletionItemKind.class_;
       case 'i': // interface name
           return CompletionItemKind.interface_;
   ```

4. **結果返却** JSON-RPCレスポンスとしてstdoutへ書き出し

#### 例2: 定義へのジャンプ (textDocument/definition)

**概要:** ユーザーがシンボルの定義位置にジャンプする処理。

**処理フロー:**
```
エディタ -> provideDefinition -> findDeclarationImpl -> DCDComponent.findDeclaration -> DCDExtComponent.getDeclarationRange -> レスポンス
```

**詳細な追跡:**

1. **ハンドラ関数** (`source/served/commands/definition.d`)

2. **DCDに問い合わせ** (`source/served/commands/definition.d:24-28`)
   ```d
   DeclarationInfo findDeclarationImpl(WorkspaceD.Instance instance, scope ref Document doc,
       int bytes, bool includeDefinition)
   {
       auto result = instance.get!DCDComponent.findDeclaration(doc.rawText, bytes).getYield;
       if (result == DCDDeclaration.init)
           return DeclarationInfo.init;
   ```

3. **DCDExtで範囲の精密化** (`source/served/commands/definition.d:49-55`)
   ```d
   if (instance.has!DCDExtComponent)
   {
       auto dcdext = instance.get!DCDExtComponent;
       range = getDeclarationRange(dcdext, found, byteOffset, includeDefinition);
       trace("  declaration refined to ", range);
   }
   ```

4. **dfmtで整形** (`source/served/commands/definition.d:67-80`)
   ```d
   if (instance.has!DfmtComponent)
   {
       trace("Formatting declaration ", [ret.declaration]);
       ret.declaration = instance.get!DfmtComponent.formatSync(ret.declaration, ...);
   }
   ```

#### 例3: DUB設定切り替え (served/switchConfig)

**概要:** エディタからカスタムリクエストでDUBビルド設定を切り替える処理。

**処理フロー:**
```
エディタ -> switchConfig -> DubComponent.setConfiguration -> レスポンス
```

**詳細な追跡:**

1. **ハンドラ関数** (`source/served/commands/dub.d:33-39`)
   ```d
   @protocolMethod("served/switchConfig")
   bool switchConfig(SwitchConfigParams value)
   {
       if (!activeInstance || !activeInstance.has!DubComponent)
           return false;
       return activeInstance.get!DubComponent.setConfiguration(value);
   }
   ```

### 8.3 フロー追跡チェックリスト

- [ ] エントリーポイントを特定したか (`source/app.d`)
- [ ] `@protocolMethod` / `@protocolNotification` でメソッドを検索したか
- [ ] ハンドラ関数内のコンポーネント呼び出しを把握したか
- [ ] `Future(T)` / `.getYield` の非同期パターンを理解したか
- [ ] エラーハンドリングを確認したか
- [ ] 最終的なレスポンス構築を確認したか

---

## 9. 設計書の参照順序

> このセクションでは、プロジェクト理解のための設計書参照順序を案内します。

### 9.1 目的別ロードマップ

#### 全体像を把握したい場合
1. `README.md` - プロジェクト概要、サブパッケージ構成、使い方
2. `dub.json` - 依存関係とサブパッケージ一覧
3. `source/served/types.d` - 共通型定義、`lspRouter` の生成
4. `source/served/extension.d` - コマンドの集約と初期化処理

#### 特定のLSP機能を理解したい場合
1. 対応する `source/served/commands/*.d` を特定
2. そのファイル内で使用されている `workspaced.com.*` コンポーネントを確認
3. コンポーネントの実装 (`workspace-d/source/workspaced/com/*.d`) を読む

#### LSPサーバーフレームワークを理解したい場合
1. `serverbase/source/served/serverbase.d` - `LanguageServerRouter` mixinテンプレート
2. `serverbase/source/served/utils/events.d` - `EventProcessor`, UDA定義
3. `lsp/source/served/lsp/jsonrpc.d` - `RPCProcessor`
4. `serverbase/source/served/utils/fibermanager.d` - ファイバ管理

#### コンポーネントを追加・修正したい場合
1. `workspace-d/source/workspaced/api.d` - `ComponentWrapper` の基盤
2. 既存コンポーネント (`workspace-d/source/workspaced/com/dfmt.d` など) を参考にする
3. `workspace-d/source/workspaced/coms.d` にpublic importを追加

### 9.2 ドキュメント一覧

| ドキュメント | 概要 | 参照タイミング |
|-------------|------|---------------|
| `README.md` | プロジェクト概要、機能、エディタ設定ガイド | 最初に読む |
| `dub.json` | メインパッケージの依存関係と設定 | 全体構造の把握時 |
| `*/dub.sdl` | 各サブパッケージの依存関係 | 特定レイヤーの理解時 |
| `editor-*.md` | 各エディタでの設定方法 | エディタ統合の理解時 |
| `source/served/info.d` | バージョン情報 | リリース管理時 |

---

## 10. トラブルシューティング

> このセクションでは、コードリーディング時によくある問題と解決法を解説します。

### よくある疑問と回答

#### Q: `mixin LanguageServerRouter!(served.extension, lsConfig) lspRouter;` は何をしているのか?
A: `serverbase/source/served/serverbase.d:65` で定義されたmixinテンプレートです。`served.extension` モジュール内の `@protocolMethod` 等のUDAが付いた関数を全てスキャンし、JSON-RPCリクエストを受け取ったときに適切な関数にディスパッチするルーターを自動生成します。同時にRPC通信、ファイバスケジューリング、GC管理なども含まれます。

#### Q: `mixin DefaultComponentWrapper;` は何をしているのか?
A: `workspace-d/source/workspaced/api.d` で定義されたmixinです。コンポーネントの初期化、インスタンス管理、設定アクセス (`config`)、ワークスペース参照 (`workspaced`)、スレッドプール (`gthreads`) などの定型的なフィールドとメソッドを自動生成します。

#### Q: `.getYield` とは何か?
A: `Future(T)` オブジェクトの結果を取得するメソッドです。結果がまだ利用可能でない場合、現在のファイバーをyieldして他のタスクに実行を譲り、結果が準備できたときに再開します。これにより、非同期処理を同期的なコードスタイルで記述できます。

#### Q: `@serdeIgnoreUnexpectedKeys` や `@serdeOptional` は何か?
A: mir-ionライブラリ (JSON/IONシリアライゼーション) のUDAです。`@serdeIgnoreUnexpectedKeys` はデシリアライズ時に未知のキーを無視し、`@serdeOptional` はフィールドがJSON上に存在しなくても良いことを示します。

#### Q: `version (Posix)` や `version (Windows)` は何か?
A: D言語の条件コンパイル機能です。コンパイル対象のプラットフォームに基づいて、コードブロックを選択的にコンパイルします。C/C++の `#ifdef` に相当しますが、D言語組み込みの機能です。

#### Q: `static this()` と `shared static this()` の違いは?
A: `static this()` はスレッドローカルな初期化子 (各スレッドで実行)、`shared static this()` はプロセス全体で1回だけ実行される初期化子です。翻訳テーブルの初期化 (`source/served/utils/translate.d:15`) やstdin/stdoutの差し替え (`serverbase/source/served/serverbase.d:13`) に使われています。

### デバッグのヒント

1. **ログレベルの変更:** `--loglevel trace` コマンドライン引数で詳細ログを出力できます。
2. **ログファイル出力:** `--logfile <path>` でログをファイルに出力できます。
3. **遅延起動:** `--wait` オプションで起動を1秒遅延させ、デバッガのアタッチが可能です。
4. **stdoutの置換:** `serverbase/source/served/serverbase.d:13-23` で `io.stdout` は `io.stderr` に置き換えられています。これは `writeln` 等の通常の出力がRPC通信チャネル (stdout) を汚染しないようにするためです。通常の出力は全てstderrに出力されます。
5. **UDA検索:** 特定のLSPメソッドのハンドラを見つけるには、`@protocolMethod("メソッド名")` でコードベースを検索してください。

---

## 付録

### A. 用語集

| 用語 | 説明 |
|-----|------|
| LSP | Language Server Protocol - エディタとIDEの間の通信プロトコル |
| JSON-RPC | JSON Remote Procedure Call - LSPで使用される通信プロトコル |
| DCD | D Completion Daemon - D言語のコード補完エンジン |
| D-Scanner | D言語の静的解析ツール |
| dfmt | D言語のコードフォーマッタ |
| DUB | D言語のビルドシステム兼パッケージマネージャ |
| Fiber | D言語の協調スレッド (コルーチン相当) |
| Future(T) | 非同期処理の結果を表す型 |
| UDA | User Defined Attribute - D言語のカスタムアトリビュート |
| mixin | コンパイル時コード生成メカニズム |
| ComponentWrapper | workspace-dのコンポーネント基底クラス |
| WorkspaceD | ワークスペース管理の中心クラス |
| LazyWorkspaceD | WorkspaceDの遅延ロード拡張 |
| Instance | WorkspaceD.Instance - 個別ワークスペースの状態管理単位 |
| serve-d | 本プロジェクト。D言語向けLSPサーバー |
| code-d | VSCode向けD言語拡張機能 (serve-dをバックエンドとして使用) |
| workspace-d | serve-dのサブパッケージ。D言語固有の処理を提供 |
| libdparse | D言語のソースコードパーサーライブラリ |
| vibe.d | D言語のWebフレームワーク (dietテンプレート対応で関連) |

### B. ファイル一覧

| ファイル/ディレクトリ | 説明 | 主な内容 |
|---------------------|------|---------|
| `source/app.d` | アプリケーションエントリーポイント | main関数、コマンドライン引数処理 |
| `source/served/extension.d` | LSP拡張の中核 | 初期化、全コマンドのpublic import |
| `source/served/types.d` | 共通型定義 | Configuration、lspRouter、エイリアス |
| `source/served/info.d` | バージョン情報 | Version、VersionSuffix |
| `source/served/commands/complete.d` | コード補完 | DCD補完結果のLSP変換 |
| `source/served/commands/definition.d` | 定義ジャンプ | DCD + DCDExt連携 |
| `source/served/commands/code_actions.d` | コードアクション | クイックフィックス、インターフェース実装 |
| `source/served/commands/dub.d` | DUBカスタムリクエスト | 設定切替、依存管理 |
| `source/served/linters/diagnosticmanager.d` | 診断統合 | 3プロバイダの結果統合 |
| `source/served/linters/dscanner.d` | D-Scannerリンター | 静的解析結果のLSP変換 |
| `source/served/backend/lazy_workspaced.d` | 遅延ロード | LazyWorkspaceD |
| `source/served/utils/translate.d` | 翻訳システム | 多言語UIメッセージ |
| `serverbase/source/served/serverbase.d` | サーバー基盤 | LanguageServerRouter mixin |
| `serverbase/source/served/utils/events.d` | イベントシステム | UDA定義、EventProcessor |
| `lsp/source/served/lsp/jsonrpc.d` | JSON-RPC通信 | RPCProcessor |
| `workspace-d/source/workspaced/api.d` | コンポーネントAPI | ComponentWrapper、WorkspaceD |
| `workspace-d/source/workspaced/backend.d` | バックエンド基盤 | Configuration、Instance |
| `workspace-d/source/workspaced/coms.d` | コンポーネント集約 | 全コンポーネントのpublic import |
| `workspace-d/source/workspaced/future.d` | 非同期処理 | Future(T)クラス |
| `workspace-d/source/workspaced/com/dcd.d` | DCDコンポーネント | コード補完、定義検索 |
| `workspace-d/source/workspaced/com/dub.d` | DUBコンポーネント | プロジェクト管理 |
| `workspace-d/source/workspaced/com/dfmt.d` | dfmtコンポーネント | コードフォーマット |
| `workspace-d/source/workspaced/com/dscanner.d` | D-Scannerコンポーネント | 静的解析 |
| `dcd/source/served/dcd/client.d` | DCDクライアント | DCD直接通信 |

### C. 参考資料

- [D言語公式ドキュメント](https://dlang.org/spec/spec.html) - D言語の仕様リファレンス
- [Language Server Protocol仕様](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/) - LSPの公式仕様
- [DUBドキュメント](https://dub.pm/) - D言語パッケージマネージャ
- [DCD GitHub](https://github.com/dlang-community/DCD) - D Completion Daemon
- [D-Scanner GitHub](https://github.com/dlang-community/D-Scanner) - D言語静的解析
- [dfmt GitHub](https://github.com/dlang-community/dfmt) - D言語フォーマッタ
- [code-d GitHub](https://github.com/Pure-D/code-d) - VSCode拡張 (serve-dクライアント)
- [code-d Wiki](https://github.com/Pure-D/code-d/wiki) - 機能説明Wiki
