# 画面設計書 33-ワークスペースシンボル（workspace/symbol）

## 概要

本ドキュメントは、serve-d LSPサーバーが提供する `workspace/symbol` リクエストハンドラの画面設計書である。ワークスペース全体からクエリに一致するシンボルをファジーマッチで検索し、クライアントに返却する機能を定義する。

### 本画面の処理概要

本機能は、ワークスペースに含まれる全プロジェクトのインデックスを横断的に検索し、ユーザーが指定したクエリ文字列に対してファジーマッチするシンボルの一覧を返却する。

**業務上の目的・背景**：大規模なD言語プロジェクトにおいて、開発者がプロジェクト全体から特定のシンボル（クラス、関数、変数等）を素早く検索・ナビゲーションする必要がある。本機能はエディタの「Go to Symbol in Workspace」コマンド（通常 Ctrl+T）に対応し、プロジェクト横断的なシンボル検索を実現する。標準ライブラリのシンボルは除外され、インポート可能なシンボルのみが検索対象となる。

**画面へのアクセス方法**：ユーザーがエディタのコマンドパレットから「Go to Symbol in Workspace」を実行するか、ショートカットキー（Ctrl+T等）を押下し、検索クエリを入力する。クライアントが `workspace/symbol` リクエストをサーバーに送信することで呼び出される。

**主要な操作・処理内容**：
1. クライアントから `workspace/symbol` リクエスト（クエリ文字列付き）を受信する
2. 全ワークスペースを走査する
3. 各ワークスペースでIndexComponentが有効かつインデックス機能が有効化されているか確認する
4. IndexComponentの `iterateAll` メソッドで全インデックスエントリを走査する
5. 各エントリについてインポート可能性、標準ライブラリ除外、ファジーマッチの3条件でフィルタする
6. 条件に合致するシンボルをSymbolInformation形式に変換する
7. 結果配列を返却する

**画面遷移**：本機能は単独のリクエスト・レスポンスである。ユーザーが検索結果からシンボルを選択すると、エディタ内で該当ファイルの該当位置にジャンプする（クライアント側処理）。

**権限による表示制御**：特別な権限制御はない。ワークスペース設定の `d.enableIndex` が有効でない場合はそのワークスペースの結果は含まれない。

## 関連機能

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

## 画面種別

LSPリクエスト・レスポンス（ワークスペースシンボル検索）

## URL/ルーティング

LSPメソッド: `workspace/symbol`

## 入出力項目

### 入力（リクエストパラメータ）

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| query | string | Yes | 検索クエリ文字列（ファジーマッチ対象） |

### 出力（レスポンス）

| 項目名 | 型 | 説明 |
|--------|------|------|
| (配列要素).name | string | シンボル名 |
| (配列要素).kind | SymbolKind | シンボル種別 |
| (配列要素).location.uri | DocumentUri | シンボルが定義されているファイルのURI |
| (配列要素).location.range | TextRange | シンボルの位置範囲 |
| (配列要素).containerName | string | 所属モジュール名（containerNameが未設定の場合） |

## 表示項目

エディタのシンボル検索UIに表示される項目。

| 表示項目 | 説明 |
|----------|------|
| シンボル名 | 検索に合致したシンボルの名前 |
| シンボルアイコン | シンボル種別に応じたアイコン |
| ファイルパス | シンボルが定義されているファイル |
| モジュール名 | シンボルが所属するモジュール名 |

## イベント仕様

### 1-workspaceSymbolリクエスト

1. `provideWorkspaceSymbols` 関数がエントリーポイントとして呼び出される
2. 全ワークスペースをループで走査する
3. 各ワークスペースについて `config.d.enableIndex` と `IndexComponent` の有効性を確認
4. `IndexComponent.iterateAll` でインデックスの全エントリにデリゲートを適用
5. 各エントリについて以下のフィルタ条件を適用：
   - `def.isImportable` - インポート可能なシンボルであること
   - `!mod.isStdLib` - 標準ライブラリのシンボルでないこと
   - `def.name.fuzzyMatchesString(params.query)` - クエリにファジーマッチすること
6. フィルタを通過したシンボルを `makeSymbolInfoEx` で SymbolInformation に変換
7. containerName が未設定の場合はモジュール名を設定
8. 結果配列を返却

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

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

本機能はデータベースへの更新を行わない（読み取り専用）。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| workspaceSymbolリクエスト | なし | SELECT | インデックスからの読み取りのみ |

## メッセージ仕様

| メッセージ種別 | 条件 | メッセージ内容 |
|---------------|------|---------------|
| 空応答 | インデックス未有効またはクエリに合致なし | 空配列を返却 |

## 例外処理

| 例外条件 | 処理内容 |
|----------|----------|
| IndexComponentが利用不可 | そのワークスペースをスキップ |
| enableIndex設定がfalse | そのワークスペースをスキップ |

## 備考

- ファジーマッチには `fuzzymatch` モジュールが使用される
- 標準ライブラリ（`mod.isStdLib`）のシンボルは検索結果から除外される
- インポート不可能なシンボルも除外される
- 結果のcontainerNameが設定されていない場合、モジュール名が自動設定される
- 位置情報の行番号は DScanner の1始まりから LSP の0始まりに変換される（`def.line - 1`）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | symbol_search.d | `source/served/commands/symbol_search.d` | SymbolInformationEx型の構造（SymbolInformationの拡張型）を確認 |
| 1-2 | index.d (workspaced) | workspacedサブパッケージ | ModuleRef, DefinitionElement の型定義を確認 |

**読解のコツ**: `iterateAll` は全インデックスエントリに対してデリゲートを適用するメソッドである。コールバック形式で処理が行われる点に注意。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | symbol_search.d | `source/served/commands/symbol_search.d` | `provideWorkspaceSymbols` 関数（行21-49） |

**主要処理フロー**:
1. **行21**: `@protocolMethod("workspace/symbol")` でLSPメソッドとして登録
2. **行27**: 全ワークスペースのループ
3. **行30**: `enableIndex` 設定と `IndexComponent` の有効性チェック
4. **行33**: `indexer.iterateAll` で全エントリ走査
5. **行34-36**: 3条件フィルタ（isImportable, !isStdLib, fuzzyMatch）
6. **行40**: `makeSymbolInfoEx` でSymbolInformation変換
7. **行41-42**: containerName設定

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

```
provideWorkspaceSymbols (symbol_search.d:22)
    |
    +-- workspaces ループ
    |   |
    |   +-- backend.has!IndexComponent 確認
    |   |
    |   +-- backend.get!IndexComponent
    |       |
    |       +-- indexer.iterateAll (デリゲートコールバック)
    |           |
    |           +-- def.isImportable チェック
    |           +-- mod.isStdLib チェック
    |           +-- fuzzyMatchesString チェック
    |           +-- makeSymbolInfoEx (symbol_search.d:108)
    |
    +-- 結果配列返却
```

### データフロー図

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

WorkspaceSymbolParams  --->  provideWorkspaceSymbols    --->  SymbolInformation[]
  .query                      |                                .name
                              +-- ワークスペース走査            .kind
                              +-- IndexComponent取得            .location
                              +-- iterateAll                    .containerName
                              +-- ファジーマッチフィルタ
                              +-- makeSymbolInfoEx変換
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| symbol_search.d | `source/served/commands/symbol_search.d` | ソース | ワークスペースシンボル検索ハンドラ |
| complete.d | `source/served/commands/complete.d` | ソース | convertFromDscannerType関数の定義 |
| extension.d | `source/served/extension.d` | ソース | workspaces, backend等のグローバル変数 |
| types.d | `source/served/types.d` | ソース | SymbolInformation等のLSP型定義 |
