# 機能設計書 19-ホバー情報 (textDocument/hover)

## 概要

本ドキュメントは、serve-d LSPサーバーにおける「ホバー情報」機能の設計を記述する。LSPの `textDocument/hover` リクエストを処理し、カーソル位置のシンボルのDDoc文書・宣言情報をホバー表示用に返却する機能である。

### 本機能の処理概要

エディタ上でシンボル（変数名・関数名・型名等）にマウスカーソルを乗せた際に、そのシンボルのドキュメント（DDoc）および宣言情報を取得し、ホバーポップアップ表示用のMarkedString配列として返却する。DCDからのドキュメント取得とfindDeclarationImplによる宣言テキスト取得の2段階処理を行う。

**業務上の目的・背景**：コードリーディング中に関数の引数や戻り値の型、変数の宣言、ドキュメントコメントをすばやく参照できることは、コード理解の効率化に直結する。ホバー情報は最も頻繁に使用されるエディタ機能の一つであり、品質の高いホバー表示はD言語開発体験の向上に大きく貢献する。

**機能の利用シーン**：開発者がエディタ上でシンボルにマウスカーソルを合わせた際、またはキーボードショートカットでホバー情報を要求した際にトリガーされる。

**主要な処理内容**：
1. DCDComponent.getDocumentation でDDocドキュメントを取得
2. DDocをMarkdown形式のMarkedStringに変換
3. findDeclarationImpl で宣言テキスト（フォーマット済み）を取得
4. 宣言テキストをD言語コードブロックとしてMarkedStringの先頭に追加
5. Hoverオブジェクトとして返却

**関連システム・外部連携**：DCDComponent、DCDExtComponent、DfmtComponent、DDoc処理ユーティリティ

**権限による制御**：DCDComponentが利用可能である必要がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 30 | ホバー（textDocument/hover） | 主機能 | カーソル位置のシンボルのDDoc文書・宣言情報をホバー表示用に返却する |

## 機能種別

データ取得・変換処理 / ドキュメント表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| params | TextDocumentPositionParams | Yes | ホバー要求の位置情報 | - |
| params.textDocument.uri | DocumentUri | Yes | 対象ドキュメントのURI | 有効なURI文字列 |
| params.position | Position | Yes | カーソル位置（行・列） | 0ベースの行・列番号 |

### 入力データソース

- LSPクライアントからの `textDocument/hover` リクエスト
- DCDComponentからのドキュメント情報
- findDeclarationImplからの宣言テキスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| contents | MarkedString[] | ホバー表示内容の配列 |
| contents[0] | MarkedString | 宣言テキスト（D言語コードブロック）※利用可能な場合 |
| contents[1..] | MarkedString | DDocドキュメント（Markdown変換済み） |

### 出力先

LSPクライアントへのレスポンスメッセージ

## 処理フロー

### 処理シーケンス

```
1. TextDocumentPositionParams を受信
2. DCDComponent 対応のバックエンドインスタンスを取得
   └─ getBestInstance!DCDComponent で取得、なければ Hover.init 返却
3. ドキュメント取得と言語ID確認
   └─ "d" 以外は Hover.init 返却
4. DCDComponent.getDocumentation でDDocドキュメント取得
5. ddocToMarked でDDocをMarkedString配列に変換
6. findDeclarationImpl で宣言テキスト取得（includeDefinition=false）
   └─ 宣言テキストを strip して空でなければ先頭に追加
7. Hover オブジェクトを構築して返却
```

### フローチャート

```mermaid
flowchart TD
    A[textDocument/hover 受信] --> B{DCDComponentインスタンスあり?}
    B -->|No| C[Hover.init 返却]
    B -->|Yes| D[ドキュメント取得]
    D --> E{言語ID == "d"?}
    E -->|No| C
    E -->|Yes| F[DCDComponent.getDocumentation]
    F --> G[ddocToMarked でMarkdown変換]
    G --> H[findDeclarationImpl 呼び出し]
    H --> I{宣言テキストあり?}
    I -->|Yes| J[MarkedString先頭に宣言テキスト追加]
    I -->|No| K[Hover構築]
    J --> K
    K --> L[Hover 返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-19-01 | D言語限定 | D言語以外のファイルではホバー情報を提供しない | 全リクエスト |
| BR-19-02 | 宣言テキスト優先表示 | 宣言テキストがある場合はMarkedStringの先頭に追加 | findDeclarationImplで宣言が取得できた場合 |
| BR-19-03 | includeDefinition=false | ホバーではシンボル名のみの範囲を取得（定義全体ではなく） | findDeclarationImpl呼び出し時 |
| BR-19-04 | 例外抑制 | findDeclarationImplの例外は握りつぶし、DDoc情報のみ返却 | try-catch |

### 計算ロジック

特になし

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

本機能ではデータベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | インスタンス不在 | DCDComponentのインスタンスがない | Hover.init返却 |
| - | 宣言解決失敗 | findDeclarationImplで例外発生 | 例外を握りつぶし、DDoc情報のみ返却 |

### リトライ仕様

リトライなし。

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

トランザクション管理なし。読み取り専用操作。

## パフォーマンス要件

マウスホバー時のリアルタイム応答が必要。DCDのgetDocumentationとfindDeclarationImplは順次実行される。

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

特になし。

## 備考

- `findDeclarationImpl` はNo.18定義ジャンプと共有される共通関数
- ホバーでは `includeDefinition=false` を使用し、定義全体ではなくシンボル名の範囲のみ取得
- 宣言テキストは `MarkedString(result.declaration, "d")` としてD言語コードブロック形式で表示

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | definition.d | `source/served/commands/definition.d` | `DeclarationInfo` 構造体（18-22行目）と `Hover` 型の関係を理解する |

**読解のコツ**: `MarkedString` は言語IDとテキストのペア（コードブロック表示用）または単なるMarkdownテキスト。`Hover.contents` は `MarkedString[]` 型で、先頭に宣言テキスト、以降にDDocドキュメントが格納される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | definition.d | `source/served/commands/definition.d` | `provideHover` 関数（119-152行目）がLSPメソッドのエントリーポイント |

**主要処理フロー**:
1. **119行目**: `@protocolMethod("textDocument/hover")` でLSPメソッド登録
2. **122-123行目**: DCDComponent対応のベストインスタンス取得
3. **127-129行目**: ドキュメント取得と言語ID確認
4. **131行目**: DCDComponent取得
5. **133-134行目**: `getDocumentation` でDDocドキュメント取得
6. **135行目**: `ddocToMarked` でMarkedString配列に変換
7. **137-147行目**: try-catch内で `findDeclarationImpl` 呼び出し（includeDefinition=false）
8. **141行目**: 宣言テキストをstrip
9. **143行目**: MarkedString先頭に宣言テキスト追加（D言語コードブロック）
10. **150行目**: Hover構築・返却

#### Step 3: DDoc変換処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ddoc.d | `source/served/utils/ddoc.d` | `ddocToMarked` 関数でDDocコメントをMarkedString配列に変換する処理 |

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

```
provideHover (definition.d:120)
    │
    ├─ DCDComponent.getDocumentation
    │
    ├─ ddocToMarked (ddoc.d)
    │
    └─ findDeclarationImpl (definition.d:24) ← try-catch内
           ├─ DCDComponent.findDeclaration
           ├─ DCDExtComponent.getDeclarationRange
           └─ DfmtComponent.formatSync
```

### データフロー図

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

TextDocumentPosition ──▶ provideHover ──────────────▶ Hover
                              │                         └─ contents: MarkedString[]
                              ├─ DCD.getDocumentation        ├─ [0] 宣言テキスト (D code)
                              │    └─ DDocテキスト           └─ [1..] DDocドキュメント
                              ├─ ddocToMarked                      (Markdown)
                              │    └─ Markdown変換
                              └─ findDeclarationImpl
                                   └─ 宣言テキスト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| definition.d | `source/served/commands/definition.d` | ソース | provideHover, findDeclarationImpl |
| ddoc.d | `source/served/utils/ddoc.d` | ソース | DDocパース・Markdown変換・ddocToMarked |
| extension.d | `source/served/extension.d` | ソース | コマンド登録 |
