# 機能設計書 62-QuickInfo

## 概要

本ドキュメントは、Visual Studio統合におけるF#のQuickInfo（ホバー時情報表示）機能の設計について記述する。この機能は、ユーザーがコード上のシンボルにマウスカーソルを合わせた際に、そのシンボルの型情報、ドキュメント、シグネチャなどをツールチップとして表示する。

### 本機能の処理概要

**業務上の目的・背景**：
F#のような静的型付け言語では、変数や関数の型情報を即座に確認できることが開発効率に直結する。本機能により、開発者はコードから離れることなく、シンボルの詳細情報を瞬時に把握でき、型推論の結果確認やAPI理解が容易になる。

**機能の利用シーン**：
- 関数の引数や戻り値の型を確認したい場合
- 変数の推論された型を確認したい場合
- XMLドキュメントコメントを参照したい場合
- キーワードの意味を確認したい場合

**主要な処理内容**：
1. マウスカーソル位置のレキサーシンボルを特定
2. シンボルの種類に応じたツールチップ情報を取得
3. XMLドキュメントからドキュメント情報を抽出
4. リッチなビジュアル表示用にコンテンツを構築
5. ナビゲーションリンク付きのQuickInfoアイテムを生成

**関連システム・外部連携**：
- Microsoft.VisualStudio.Language.Intellisense: VS IntelliSense API
- FSharp.Compiler.EditorServices: F#コンパイラのツールチップAPI
- XMLドキュメントサービス: XMLMemberIndexService

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | QuickInfo オプション設定画面 | 設定画面 | ナビゲーションリンクスタイル、説明幅、remarksの表示設定 |

## 機能種別

情報表示機能

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 対象のドキュメント | null不可 |
| position | int | Yes | マウスカーソル位置（文字オフセット） | 0以上、ドキュメント長未満 |
| width | int | No | 説明の最大幅（オプション） | 正の整数 |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| QuickInfoItem | QuickInfoItem | ツールチップ表示用のアイテム |
| TrackingSpan | ITrackingSpan | ツールチップ対象のテキスト範囲 |
| Content | UIElement | 表示用のビジュアルコンテンツ |

### 出力先

Visual Studio エディタ上のツールチップUI

## 処理フロー

### 処理シーケンス

```
1. トリガーポイントの取得
   └─ セッションからマウス位置を取得

2. レキサーシンボルの取得
   └─ TryFindFSharpLexerSymbolAsyncでシンボル特定

3. ツールチップ情報の取得
   └─ シンボル種別に応じてGetToolTipまたはGetKeywordTooltipを呼び出し

4. ドキュメント情報の構築
   └─ XMLドキュメントからドキュメント・説明を抽出

5. ビジュアルコンテンツの生成
   └─ QuickInfoViewProvider.provideContentでUI要素を生成

6. QuickInfoアイテムの作成
   └─ TrackingSpanとコンテンツを組み合わせてアイテム生成
```

### フローチャート

```mermaid
flowchart TD
    A[マウスホバー検出] --> B[トリガーポイント取得]
    B --> C{位置有効?}
    C -->|No| Z[null返却]
    C -->|Yes| D[レキサーシンボル取得]
    D --> E{シンボル発見?}
    E -->|No| Z
    E -->|Yes| F{シンボル種別判定}
    F -->|Keyword| G[GetKeywordTooltip]
    F -->|String| H[GetToolTip with String tag]
    F -->|Other| I[GetToolTip with IDENT tag]
    G --> J[ドキュメント構築]
    H --> J
    I --> J
    J --> K[ビジュアルコンテンツ生成]
    K --> L[QuickInfoItem作成]
    L --> M[返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-62-01 | シンボル種別分岐 | Keyword/String/その他で異なるツールチップ取得メソッドを使用 | シンボル種別判定時 |
| BR-62-02 | 相対パス表示 | ナビゲーションリンクのツールチップにはプロジェクト/ソリューション相対パスを使用 | リンク生成時 |
| BR-62-03 | Remarks表示制御 | editorOptions.QuickInfo.ShowRemarksに応じてremarks要素の表示を制御 | ドキュメント構築時 |

### 計算ロジック

リンクツールチップの相対パス計算（45-50行目）：
- プロジェクトディレクトリからの相対パスとソリューションディレクトリからの相対パスを計算
- より短い方を選択して表示

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | シンボル不在 | カーソル位置にシンボルがない | nullを返却 |
| - | ツールチップ空 | ToolTipTextが空リスト | nullを返却 |
| - | スパン変換失敗 | FSharpRangeをTextSpanに変換できない | nullを返却 |

### リトライ仕様

リトライなし。エラー発生時はツールチップを表示しない。

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

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

## パフォーマンス要件

- マウスホバーから100ms以内に表示開始
- 非同期処理によりUIスレッドをブロックしない

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

該当なし

## 備考

- FSharpAsyncQuickInfoSourceは非同期でツールチップを取得するためIAsyncQuickInfoSourceを実装
- QuickInfoViewProviderによりリッチなWPFコンテンツとして表示

---

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

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

### 推奨読解順序

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

QuickInfoで使用される主要なデータ型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | QuickInfoProvider.fs | `vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs` | ToolTipText、LexerSymbol型の使用 |

**読解のコツ**: F#コンパイラのToolTipTextはToolTipElementのリストであり、各要素がシグネチャ、ドキュメント、型情報を含む。

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

IAsyncQuickInfoSourceProviderの実装から読み始める。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | QuickInfoProvider.fs | `vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs` | FSharpAsyncQuickInfoSourceProviderクラス |

**主要処理フロー**:
1. **144-159行目**: FSharpAsyncQuickInfoSourceProviderクラスの定義
2. **156-159行目**: TryCreateQuickInfoSourceでソースインスタンス作成
3. **157行目**: XMLMemberIndexServiceの取得

#### Step 3: QuickInfoソースの実装を理解する

FSharpAsyncQuickInfoSourceクラスが実際のツールチップ取得を行う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | QuickInfoProvider.fs | `vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs` | FSharpAsyncQuickInfoSourceクラス |

**主要処理フロー**:
- **23-74行目**: FSharpAsyncQuickInfoSourceクラス定義
- **26-74行目**: getQuickInfoItem関数（ToolTipTextからQuickInfoItemを構築）
- **31-39行目**: XMLドキュメントからシンボル・説明・ドキュメントを抽出
- **52-58行目**: QuickInfoViewProvider.provideContentでビジュアル生成
- **70-73行目**: TrackingSpanとコンテンツでQuickInfoItem作成

#### Step 4: ツールチップ取得ロジックを理解する

TryGetToolTip静的メソッドがコンパイラサービスとやり取りする。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | QuickInfoProvider.fs | `vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs` | TryGetToolTip静的メソッド |

**主要処理フロー**:
- **76-115行目**: TryGetToolTip静的メソッド
- **80行目**: レキサーシンボル取得
- **93-112行目**: シンボル種別に応じた分岐処理
- **94行目**: Keywordの場合はGetKeywordTooltip
- **95-103行目**: Stringの場合はFSharpTokenTag.String付きでGetToolTip
- **104-112行目**: その他はFSharpTokenTag.IDENT付きでGetToolTip

#### Step 5: IAsyncQuickInfoSource実装を理解する

GetQuickInfoItemAsyncが非同期インターフェースの実装。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | QuickInfoProvider.fs | `vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs` | IAsyncQuickInfoSource実装 |

**主要処理フロー**:
- **117-142行目**: IAsyncQuickInfoSourceインターフェース実装
- **120-141行目**: GetQuickInfoItemAsyncメソッド
- **125-130行目**: トリガーポイントの検証
- **132-133行目**: TryGetToolTipの呼び出し
- **137行目**: getQuickInfoItemでアイテム生成

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

```
FSharpAsyncQuickInfoSourceProvider.TryCreateQuickInfoSource
    │
    └─ FSharpAsyncQuickInfoSource (インスタンス生成)
           │
           └─ IAsyncQuickInfoSource.GetQuickInfoItemAsync
                  │
                  ├─ TryGetToolTip
                  │      │
                  │      ├─ document.TryFindFSharpLexerSymbolAsync
                  │      │
                  │      ├─ document.GetFSharpParseAndCheckResultsAsync
                  │      │
                  │      └─ checkFileResults.GetToolTip / GetKeywordTooltip
                  │
                  └─ getQuickInfoItem
                         │
                         ├─ XmlDocumentation.BuildSingleTipText
                         │
                         ├─ QuickInfoViewProvider.provideContent
                         │
                         └─ QuickInfoItem (生成)
```

### データフロー図

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

IAsyncQuickInfoSession
       │
       ├─ GetTriggerPoint ──▶ position
       │
       ▼
Document ──────────────▶ TryGetToolTip ────────────────┐
                              │                        │
                              ├─ LexerSymbol           │
                              │                        │
                              └─ ToolTipText ──────────┤
                                                       │
XMLMemberIndexService ──▶ BuildSingleTipText ──────────┤
                                                       ▼
                                              QuickInfoItem
                                                       │
                                                       ▼
                                              VS ToolTip UI
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| QuickInfoProvider.fs | `vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs` | ソース | QuickInfoサービスの実装 |
| QuickInfoViewProvider.fs | `vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoViewProvider.fs` | ソース | ビジュアルコンテンツの生成 |
| XmlDocumentation.fs | `vsintegration/src/FSharp.Editor/Common/XmlDocumentation.fs` | ソース | XMLドキュメント処理 |
| Tokenizer.fs | `vsintegration/src/FSharp.Editor/Common/Tokenizer.fs` | ソース | トークン化・シンボル取得 |
| FSharpNavigation.fs | `vsintegration/src/FSharp.Editor/Navigation/FSharpNavigation.fs` | ソース | ナビゲーションリンク生成 |
