# 画面設計書 27-参照検索（textDocument/references）

## 概要

本ドキュメントは、serve-d LSPサーバーにおける `textDocument/references` リクエストの処理仕様を定義する画面設計書である。カーソル位置のシンボルが参照されている全箇所を検索し、Location配列として返却する機能を記述する。

### 本画面の処理概要

**業務上の目的・背景**：D言語開発において、関数・変数・型などのシンボルがプロジェクト内のどこで使用されているかを網羅的に把握することは、リファクタリングや影響範囲分析に不可欠な機能である。本機能はLSPプロトコルの `textDocument/references` を通じて、エディタの「参照の検索（Find All References）」機能を実現する。非同期処理で実行され、結果が見つかり次第順次返却する `AsyncReceiver` パターンを採用している。

**画面へのアクセス方法**：エディタ上でD言語ソースファイルのシンボル上にカーソルを置き、「参照の検索」コマンド（通常はShift+F12等）を実行する。エディタが `textDocument/references` リクエストをLSPサーバーに送信する。

**主要な操作・処理内容**：
1. カーソル位置のシンボルに対し、ReferencesComponentを使用して全参照箇所を非同期検索する
2. 検索結果はAsyncReceiverを通じてストリーミング形式で返却される
3. 宣言箇所を含めるかどうかは `context.includeDeclaration` パラメータで制御される
4. 各参照箇所はファイルパスからURIに変換され、ワード範囲を付与してLocationとして返却される

**画面遷移**：参照検索結果はエディタの「参照一覧」パネルに表示される。各参照箇所をクリックすると対象ファイルの該当位置にジャンプする。画面遷移図の「シンボル操作」サブグラフにおいて「参照検索」として位置付けられている。

**権限による表示制御**：権限による表示制御は存在しない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | 参照検索 (textDocument/references) | 主機能 | カーソル位置のシンボルの全参照箇所を非同期で検索し返却する |

## 画面種別

情報提供（LSPプロトコルレスポンス / 非同期ストリーミング）

## URL/ルーティング

- LSPメソッド: `textDocument/references`

## 入出力項目

| 項目名 | 型 | 入力/出力 | 必須 | 説明 |
|--------|-----|----------|------|------|
| params.textDocument.uri | DocumentUri | 入力 | Yes | 対象ドキュメントのURI |
| params.position | Position | 入力 | Yes | カーソル位置 |
| params.context.includeDeclaration | bool | 入力 | Yes | 宣言箇所を結果に含めるかどうか |
| Location[] | Location[] | 出力 | - | 参照箇所のLocation配列（非同期ストリーミング） |
| Location.uri | DocumentUri | 出力 | - | 参照箇所のドキュメントURI |
| Location.range | TextRange | 出力 | - | 参照箇所のワード範囲 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|---------|------|
| 参照一覧 | パネル表示 | 検索結果がエディタの参照パネルにファイル名・行番号付きで一覧表示される |

## イベント仕様

### 1-参照検索実行

ユーザーが「参照の検索」を実行した際の処理フロー。

1. `AsyncReceiver!Location` を作成する（行16）
2. ドキュメントを取得し、カーソル位置をバイトオフセットに変換する（行17-18）
3. ファイルパスを取得する（行19）
4. DCDコンポーネントの存在を確認し、ない場合は即座にreceiverを終了して返却する（行22-26）
5. `includeDeclaration` フラグを取得する（行28）
6. `setImmediate` で非同期タスクを開始する（行29）:
   a. `ReferencesComponent.findReferences` でシンボルの全参照箇所を検索する（行35-36）
   b. コールバック内で各参照結果を処理する:
      - `includeDeclaration` がfalseの場合、定義箇所（definitionFile/definitionLocation）と一致する参照を除外する（行41）
      - `resolveLocation` でファイルパス→URI変換とワード範囲取得を行う（行43）
      - 結果を `receiver.put` で蓄積する（行45）
   c. 完了時に `receiver.end()` を呼び出す（行30-31）

### 2-位置解決（resolveLocation）

`resolveLocation` 関数（行57-63）の処理フロー。

1. ファイルパスをURIに変換する（行59）
2. `documents.getOrFromFilesystem` でドキュメントを取得する（行60）
3. バイトオフセットをPositionに変換する（行61）
4. `wordRangeAt` でワード範囲を取得する（行62）
5. `Location(uri, range)` を結果配列に追加する（行62）

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

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

本機能はデータベースに対する操作を行わない。

## メッセージ仕様

本機能は明示的なメッセージ表示を行わない。

## 例外処理

| 条件 | 挙動 |
|------|------|
| DCDコンポーネントが利用不可 | 空のAsyncReceiverを即座に終了して返却 |
| 非同期タスク内で例外発生 | `receiver.error` に例外を設定し、次のアクセス時にスロー |
| シンボルが見つからない | 空のLocation配列を返却 |

## 備考

- `AsyncReceiver` クラスはFiberベースの非同期パターンを実装しており、`wait` メソッドで `Fiber.yield()` を呼び出して結果を待機する
- `AsyncReceiver` は `Mutex` を使用してスレッドセーフなデータ蓄積を行う
- `front`/`popFront`/`empty` の各メソッドにより、range-basedインターフェースを提供する
- 参照検索はプロジェクト全体を対象とするため、大規模プロジェクトでは処理に時間がかかる可能性がある

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | references.d | `source/served/commands/references.d` | `AsyncReceiver` クラス（行65-141）: Fiber+Mutexベースの非同期レシーバー |
| 1-2 | protocol.d | `source/served/lsp/protocol.d` | `ReferenceParams`, `Location` の定義を確認 |

**読解のコツ**: `AsyncReceiver` はrange-basedインターフェース（`front`/`popFront`/`empty`）を実装しており、Fiberと組み合わせて非同期ストリーミングを実現している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | references.d | `source/served/commands/references.d` | `findReferences` 関数（行13-55）がLSPリクエストハンドラ |

**主要処理フロー**:
1. **行13**: `@protocolMethod("textDocument/references")` でバインド
2. **行16**: AsyncReceiver作成
3. **行22-26**: DCDコンポーネント確認
4. **行29**: `setImmediate` で非同期タスク起動
5. **行35-47**: ReferencesComponent.findReferencesのコールバック処理

#### Step 3: 位置解決を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | references.d | `source/served/commands/references.d` | `resolveLocation` 関数（行57-63）: ファイルパス+オフセットからLocationへの変換 |

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

```
textDocument/references リクエスト
    |
    +-- findReferences (references.d:13)
           |
           +-- AsyncReceiver!Location 作成
           +-- documents[uri] (ドキュメント取得)
           +-- positionToBytes (バイトオフセット変換)
           |
           +-- setImmediate (非同期タスク)
                  |
                  +-- ReferencesComponent.findReferences
                  |      +-- コールバック
                  |             +-- includeDeclaration判定
                  |             +-- resolveLocation (references.d:57)
                  |             |      +-- uriFromFile
                  |             |      +-- documents.getOrFromFilesystem
                  |             |      +-- bytesToPosition
                  |             |      +-- wordRangeAt
                  |             +-- receiver.put
                  |
                  +-- receiver.end()
```

### データフロー図

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

ReferenceParams ----------> findReferences ----------------------> Location[]
  textDocument.uri            |                                    (AsyncReceiver経由)
  position                    +-- ReferencesComponent.findReferences
  context.includeDecl         |      --> 参照箇所リスト
                              +-- resolveLocation
                              |      --> URI変換 + ワード範囲
                              +-- AsyncReceiver.put
                              +-- AsyncReceiver.end
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| references.d | `source/served/commands/references.d` | ソース | 参照検索の主処理・AsyncReceiver |
| types.d | `source/served/types.d` | ソース | 共通型定義 |
| async.d | `source/served/utils/async.d` | ソース | setImmediate等の非同期ユーティリティ |
| protocol.d | `source/served/lsp/protocol.d` | ソース | LSPプロトコル型定義 |
| uri.d | `source/served/lsp/uri.d` | ソース | URI変換ユーティリティ |
| textdocumentmanager.d | `source/served/lsp/textdocumentmanager.d` | ソース | ドキュメント管理 |
