# 機能設計書 21-ワークスペースシンボル (workspace/symbol)

## 概要

本ドキュメントは、serve-d LSPサーバーにおけるワークスペースシンボル検索機能（workspace/symbol）の設計を記述する。ワークスペース全体からクエリに一致するシンボルをファジーマッチで検索して返却する機能である。

### 本機能の処理概要

**業務上の目的・背景**：大規模なD言語プロジェクトでは、多数のモジュールに定義された関数・クラス・構造体等のシンボルを横断的に検索する必要がある。本機能は、エディタの「Go to Symbol in Workspace」（Ctrl+T等）に対応し、開発者がプロジェクト全体から目的のシンボルを迅速に発見できるようにする。

**機能の利用シーン**：開発者がエディタ上でワークスペース全体のシンボル検索コマンドを実行した際に呼び出される。クエリ文字列に基づくファジーマッチングにより、タイプミスや部分一致でも候補を返却する。

**主要な処理内容**：
1. 全ワークスペースフォルダを走査し、IndexComponentが有効なフォルダのインデクサーを取得する
2. インデクサーの全エントリをイテレートし、インポート可能かつ標準ライブラリでないシンボルをフィルタする
3. クエリ文字列に対するファジーマッチを実行し、一致するシンボルをSymbolInformation形式で収集する
4. コンテナ名（モジュール名）を付与してクライアントに返却する

**関連システム・外部連携**：IndexComponent（バックグラウンドインデックス機能）、DScanner（シンボル定義の解析）、fuzzymatchライブラリ（ファジーマッチング）

**権限による制御**：特になし。ただし、`config.d.enableIndex`が有効なワークスペースのみ検索対象となる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | ワークスペースシンボル（workspace/symbol） | 主画面 | ワークスペース全体からクエリに一致するシンボルをファジーマッチで検索して返却する |

## 機能種別

データ検索（シンボルインデックスからのファジーマッチ検索）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| query | string | Yes | 検索クエリ文字列 | 空文字列でもエラーにはならないが、ファジーマッチの性質上全件が一致する可能性がある |

### 入力データソース

- LSPクライアントからのworkspace/symbolリクエストのWorkspaceSymbolParamsオブジェクト
- 各ワークスペースフォルダのIndexComponentに保持されたインデックスデータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| name | string | シンボル名 |
| kind | SymbolKind | シンボルの種類（関数、クラス、構造体等） |
| location.uri | DocumentUri | シンボルが定義されたファイルのURI |
| location.range | TextRange | シンボルの位置範囲（開始行・列） |
| containerName | string | シンボルが所属するモジュール名（コンテナ名が未設定の場合に補完される） |
| tags | SymbolTag[] | deprecated等のタグ情報 |
| detail | string | シグネチャや詳細情報 |

### 出力先

LSPクライアント（JSON-RPCレスポンスとして返却）

## 処理フロー

### 処理シーケンス

```
1. workspace/symbolリクエスト受信
   └─ WorkspaceSymbolParamsからqueryを取得
2. fuzzymatchモジュールをインポート
   └─ ファジーマッチング用ライブラリの遅延ロード
3. 全ワークスペースフォルダのイテレーション
   └─ workspaces配列を走査
4. IndexComponent有効性チェック
   └─ config.d.enableIndex かつ backend.has!IndexComponent を確認
5. インデクサーの全エントリイテレーション
   └─ indexer.iterateAll でデリゲートベースの走査
6. フィルタ条件の適用
   └─ isImportable, !isStdLib, fuzzyMatchesString の全条件を満たすもの
7. SymbolInformation構築
   └─ makeSymbolInfoExで定義情報をLSP型に変換
8. containerName補完
   └─ containerNameが未設定の場合にモジュール名を設定
9. 結果返却
   └─ infos.dataとして蓄積された全候補を返却
```

### フローチャート

```mermaid
flowchart TD
    A[workspace/symbol リクエスト受信] --> B[クエリ文字列取得]
    B --> C[全ワークスペースループ開始]
    C --> D{enableIndex && has IndexComponent?}
    D -->|No| C2[次のワークスペースへ]
    D -->|Yes| E[IndexComponentのインデクサー取得]
    E --> F[iterateAll で全シンボルイテレーション]
    F --> G{isImportable && !isStdLib && fuzzyMatch?}
    G -->|No| F
    G -->|Yes| H[makeSymbolInfoEx でSymbolInformation構築]
    H --> I{containerName未設定?}
    I -->|Yes| J[モジュール名をcontainerNameに設定]
    I -->|No| K[結果配列に追加]
    J --> K
    K --> F
    C2 --> C
    F --> L[全ワークスペース走査完了]
    L --> M[SymbolInformation配列を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-01 | インデックス有効チェック | enableIndexが無効なワークスペースはスキップする | 各ワークスペースの走査開始時 |
| BR-21-02 | 標準ライブラリ除外 | 標準ライブラリ（std.*）のシンボルは結果から除外する | 各シンボルのフィルタ時 |
| BR-21-03 | インポート可能性チェック | isImportableでないシンボル（ローカル変数等）は除外する | 各シンボルのフィルタ時 |
| BR-21-04 | ファジーマッチ | クエリ文字列に対してファジーマッチで一致判定する | 各シンボルのフィルタ時 |
| BR-21-05 | コンテナ名補完 | containerNameが未設定の場合、モジュール名（ModuleRef）を設定する | SymbolInformation構築後 |

### 計算ロジック

ファジーマッチは fuzzymatch ライブラリの `fuzzyMatchesString` 関数を使用する。部分文字列マッチではなく、文字の順序を維持した非連続一致を許容するファジーマッチングアルゴリズムである。

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

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

データベース操作は行わない。インメモリのIndexComponentインデックスデータのみを参照する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 空結果 | インデックスが未構築、または一致するシンボルがない場合 | 空配列を返却 |
| - | IndexComponent未登録 | ワークスペースにIndexComponentが存在しない場合 | 当該ワークスペースをスキップ |

### リトライ仕様

リトライは不要。インデックスが未構築の場合は空結果を返し、バックグラウンドインデックスの完了後に再度リクエストすれば結果が得られる。

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

トランザクションは使用しない（読み取り専用操作）。

## パフォーマンス要件

- ファジーマッチは全インデックスエントリに対して実行されるため、大規模プロジェクトではレイテンシが増大する可能性がある
- fuzzymatchモジュールの遅延インポートにより初回呼び出し時のみ若干のオーバーヘッドがある

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

特になし。ローカルファイルシステム上のインデックスデータのみを参照する。

## 備考

- 本機能はドキュメントシンボル（textDocument/documentSymbol, No.20）と同じsymbol_search.dモジュールに実装されている
- ドキュメントシンボルはDScannerを直接使用するのに対し、ワークスペースシンボルはIndexComponentの事前構築済みインデックスを使用する点が異なる
- 標準ライブラリのシンボルを除外しているのは、結果のノイズを減らすためと考えられる

---

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

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

### 推奨読解順序

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

まず、ワークスペースシンボル検索で使用されるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | symbol_search.d | `source/served/commands/symbol_search.d` | SymbolInformationEx構造体とDocumentSymbolInfo構造体の定義を確認（108-128行目のmakeSymbolInfoEx関数で構築される型の構造） |
| 1-2 | types.d | `source/served/types.d` | SymbolInformation、SymbolKind、Position等のLSP型定義を確認 |

**読解のコツ**: D言語の`alias symbol this;`（135行目）はサブタイピングを実現する構文で、DocumentSymbolInfoをDocumentSymbolとして透過的に使えるようにしている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | symbol_search.d | `source/served/commands/symbol_search.d` | provideWorkspaceSymbols関数（21-49行目）がLSPプロトコルメソッドのエントリーポイント |

**主要処理フロー**:
1. **21行目**: `@protocolMethod("workspace/symbol")` アトリビュートによるLSPメソッドバインディング
2. **24行目**: `import fuzzymatch;` ファジーマッチライブラリの遅延インポート
3. **26行目**: `appender!(SymbolInformation[])` 結果蓄積用のアペンダー初期化
4. **27-46行目**: ワークスペースループとインデクサーイテレーション
5. **34-36行目**: フィルタ条件（isImportable, !isStdLib, fuzzyMatchesString）

#### Step 3: シンボル情報構築を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | symbol_search.d | `source/served/commands/symbol_search.d` | makeSymbolInfoEx関数（108-128行目）でDScannerの定義情報をLSP SymbolInformation型に変換する処理 |

**主要処理フロー**:
- **110-113行目**: 基本情報（名前・URI・位置・種類）の設定
- **114行目**: `convertFromDscannerType` によるDScanner型からSymbolKindへの変換
- **118-120行目**: コンテナ名の設定（struct/class/enum/union属性から取得）
- **121-122行目**: deprecatedタグの設定
- **123-126行目**: シグネチャ・詳細情報の設定

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

```
provideWorkspaceSymbols (symbol_search.d:22)
    |
    +-- fuzzymatch.fuzzyMatchesString (外部ライブラリ)
    |
    +-- IndexComponent.iterateAll (workspaced/com/index.d)
    |       |
    |       +-- DefinitionElement の走査
    |
    +-- makeSymbolInfoEx (symbol_search.d:108)
    |       |
    |       +-- convertFromDscannerType
    |       +-- convertExtendedFromDscannerType
    |
    +-- uriFromFile (URI変換ユーティリティ)
```

### データフロー図

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

WorkspaceSymbolParams ------> provideWorkspaceSymbols -------> SymbolInformation[]
  (query: string)                    |
                                     v
                              IndexComponent.iterateAll
                                     |
                                     v
                              DefinitionElement (各シンボル)
                                     |
                                     v
                              fuzzyMatchesString フィルタ
                                     |
                                     v
                              makeSymbolInfoEx 変換
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| symbol_search.d | `source/served/commands/symbol_search.d` | ソース | ワークスペースシンボル検索のメイン実装（provideWorkspaceSymbols関数: 21-49行目） |
| types.d | `source/served/types.d` | ソース | LSP型定義（SymbolInformation, Position等） |
| index.d | `source/served/commands/index.d` | ソース | IndexComponentによるバックグラウンドインデックス管理 |
| extension.d | `source/served/extension.d` | ソース | workspaces配列の定義とワークスペース管理 |
| dscanner.d (workspaced) | `workspace-d/source/workspaced/com/dscanner.d` | ソース | DefinitionElement型の定義 |
| index.d (workspaced) | `workspace-d/source/workspaced/com/index.d` | ソース | IndexComponent・iterateAll関数の実装 |
