# 機能設計書 61-参照検索

## 概要

本ドキュメントは、Visual Studio統合におけるF#の「参照の検索（Find All References）」機能の設計について記述する。この機能は、ユーザーが選択したシンボルのすべての使用箇所をプロジェクトおよびソリューション全体から検索し、結果を一覧表示する。

### 本機能の処理概要

**業務上の目的・背景**：
大規模なF#プロジェクトにおいて、変数・関数・型などのシンボルがどこで使用されているかを把握することは、コードの理解・リファクタリング・影響範囲の特定に不可欠である。本機能により、開発者は特定のシンボルの全使用箇所を瞬時に把握でき、コードベースの保守性が大幅に向上する。

**機能の利用シーン**：
- シンボルの名前変更前に影響範囲を確認したい場合
- 関数や型がどこで呼び出されているかを調査する場合
- 未使用のコードを特定したい場合
- コードレビュー時に変更の影響範囲を確認する場合

**主要な処理内容**：
1. カーソル位置のレキサーシンボルを特定
2. F#コンパイラサービスを使用してシンボル情報を取得
3. 宣言位置を特定し、定義アイテムを作成
4. ソリューション全体でシンボルの使用箇所を検索
5. 検索結果をRoslynのFind Usagesコンテキストに報告

**関連システム・外部連携**：
- Microsoft.CodeAnalysis.ExternalAccess.FSharp.FindUsages: Roslynの参照検索インターフェース
- FSharp.Compiler.EditorServices: F#コンパイラのエディタサービスAPI
- Visual Studio Find All References ツールウィンドウ: 結果表示UI

**権限による制御**：
特になし。すべてのユーザーがこの機能を利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | 言語サービスパフォーマンスオプション画面 | 設定画面 | 高速参照検索とリネームの有効化設定 |

## 機能種別

コード解析・検索機能

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 対象のドキュメント | null不可 |
| position | int | Yes | カーソル位置（文字オフセット） | 0以上、ドキュメント長未満 |
| context | IFSharpFindUsagesContext | Yes | 検索結果の報告先コンテキスト | null不可 |

### 入力データソース

- Visual Studioエディタのカーソル位置
- 開いているドキュメントのソーステキスト
- F#コンパイラサービスの解析結果

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| DefinitionItem | FSharpDefinitionItem | シンボルの定義情報 |
| SourceReferenceItem | FSharpSourceReferenceItem | 各参照箇所の位置情報 |

### 出力先

Visual Studio の「Find All References」ツールウィンドウ

## 処理フロー

### 処理シーケンス

```
1. レキサーシンボルの取得
   └─ TryFindFSharpLexerSymbolAsyncでカーソル位置のシンボルを特定

2. 型チェック結果の取得
   └─ GetFSharpParseAndCheckResultsAsyncで解析結果を取得

3. シンボル使用情報の取得
   └─ GetSymbolUseAtLocationでシンボル使用情報を取得

4. 宣言位置の特定
   └─ GetDeclarationLocationで宣言位置を取得

5. 定義アイテムの作成
   └─ 宣言位置からFSharpDefinitionItemを作成

6. 参照箇所の検索
   └─ findSymbolUsesでソリューション全体を検索

7. 結果の報告
   └─ OnReferenceFoundAsyncで各参照箇所を報告
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[レキサーシンボル取得]
    B --> C{シンボル発見?}
    C -->|No| Z[終了]
    C -->|Yes| D[型チェック結果取得]
    D --> E[シンボル使用情報取得]
    E --> F{シンボル使用あり?}
    F -->|No| Z
    F -->|Yes| G[宣言位置特定]
    G --> H[定義アイテム作成]
    H --> I[定義報告]
    I --> J[参照箇所検索]
    J --> K[参照報告]
    K --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-61-01 | 外部定義の扱い | 外部アセンブリで定義されたシンボルはナビゲート不可の定義アイテムとして表示 | シンボルが外部アセンブリに存在する場合 |
| BR-61-02 | 重複排除 | 同一ファイルが複数プロジェクトに含まれる場合、定義スパンは重複排除される | 共有ファイルが存在する場合 |
| BR-61-03 | 宣言除外 | allReferences=falseの場合、宣言位置は結果から除外 | FindImplementationsAsyncの場合 |

### 計算ロジック

該当なし

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

該当なし（メモリ内解析のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 検索失敗 | シンボルが特定できない場合 | 結果なしで終了 |
| - | 参照報告失敗 | OnReferenceFoundAsync内部でエラー | try/withで捕捉し継続 |

### リトライ仕様

リトライなし。エラー発生時は該当参照をスキップして継続。

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

該当なし（読み取り専用操作）

## パフォーマンス要件

- 大規模ソリューションでも数秒以内に結果表示を開始
- インクリメンタルに結果を報告し、ユーザーは途中結果を確認可能

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

該当なし

## 備考

- FindReferencesAsyncとFindImplementationsAsyncは同一の内部実装を使用し、allReferencesパラメータで挙動を切り替える
- ソースコード54-57行目でOnReferenceFoundAsyncのRoslyn内部エラーを捕捉している（既知の問題への対応）

---

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

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

### 推奨読解順序

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

まず、参照検索で使用される主要なデータ型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Symbols.fs | `src/Compiler/Symbols/Symbols.fs` | FSharpSymbolUse、FSharpSymbol等の基本型定義 |

**読解のコツ**: F#コンパイラサービスのシンボル型は階層構造を持つ。FSharpSymbolが基底で、FSharpMemberOrFunctionOrValue等が派生型となる。

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

IFSharpFindUsagesServiceインターフェースの実装から読み始める。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FindUsagesService.fs | `vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs` | サービスのエントリーポイント |

**主要処理フロー**:
1. **167-176行目**: FSharpFindUsagesServiceクラスの定義とIFSharpFindUsagesServiceインターフェースの実装
2. **170-172行目**: FindReferencesAsyncの実装（allReferences=true）
3. **174-176行目**: FindImplementationsAsyncの実装（allReferences=false）

#### Step 3: コア検索ロジックを理解する

findReferencedSymbolsAsync関数が検索の中核ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FindUsagesService.fs | `vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs` | findReferencedSymbolsAsync関数 |

**主要処理フロー**:
- **87-163行目**: findReferencedSymbolsAsync関数の本体
- **96-98行目**: レキサーシンボルの取得
- **100-106行目**: 型チェック結果からシンボル使用情報を取得
- **120-128行目**: 宣言スパンの取得と重複排除
- **137-142行目**: 定義アイテムの作成
- **162行目**: SymbolHelpers.findSymbolUsesによるソリューション全体検索

#### Step 4: 参照報告ロジックを理解する

onSymbolFound関数が各参照箇所の報告処理を行う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FindUsagesService.fs | `vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs` | onSymbolFound関数 |

**主要処理フロー**:
- **20-59行目**: onSymbolFound関数
- **35-38行目**: 宣言位置との一致チェック、allReferencesフラグのチェック
- **42-49行目**: 定義アイテムの選択（外部 vs ローカル）
- **51-57行目**: 参照アイテムの報告（エラーハンドリング含む）

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

```
FSharpFindUsagesService.FindReferencesAsync
    │
    └─ findReferencedSymbolsAsync
           │
           ├─ document.TryFindFSharpLexerSymbolAsync
           │      └─ Tokenizer.getSymbolAtPosition
           │
           ├─ document.GetFSharpParseAndCheckResultsAsync
           │      └─ BackgroundCompiler
           │
           ├─ checkFileResults.GetSymbolUseAtLocation
           │
           ├─ checkFileResults.GetDeclarationLocation
           │
           ├─ rangeToDocumentSpans
           │      └─ Tokenizer.TryFSharpRangeToTextSpanForEditor
           │
           ├─ context.OnDefinitionFoundAsync
           │
           └─ SymbolHelpers.findSymbolUses
                  └─ onSymbolFound (callback)
                         └─ context.OnReferenceFoundAsync
```

### データフロー図

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

Document      ───────▶ TryFindFSharpLexerSymbol ──┐
                                                  │
Position      ───────▶ GetSymbolUseAtLocation ────┼──▶ FSharpDefinitionItem
                                                  │         │
                       GetDeclarationLocation ────┘         │
                              │                             ▼
                              ▼                    IFSharpFindUsagesContext
                       findSymbolUses ──────────────────────┘
                              │
                              ▼
                       FSharpSourceReferenceItem[]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FindUsagesService.fs | `vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs` | ソース | 参照検索サービスの実装 |
| SymbolHelpers.fs | `vsintegration/src/FSharp.Editor/Common/SymbolHelpers.fs` | ソース | シンボル検索ヘルパー関数 |
| Tokenizer.fs | `vsintegration/src/FSharp.Editor/Common/Tokenizer.fs` | ソース | トークン化・スパン変換 |
| RoslynHelpers.fs | `vsintegration/src/FSharp.Editor/Common/RoslynHelpers.fs` | ソース | Roslyn型変換ヘルパー |
| Symbols.fs | `src/Compiler/Symbols/Symbols.fs` | ソース | F#シンボル型定義 |
