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

## 概要

本ドキュメントは、Lua Language Serverにおける「ホバー情報」機能の設計を記述する。この機能は、LSPの`textDocument/hover`リクエストに対応し、カーソル位置のシンボル情報をホバー表示する機能を提供する。

### 本機能の処理概要

ホバー情報機能は、カーソル位置のシンボル（変数、関数、フィールドなど）に関する詳細情報をMarkdown形式で返す機能である。型情報、ドキュメントコメント、関数シグネチャ、パラメータ説明などが含まれる。

**業務上の目的・背景**：コードを読む際に、変数の型や関数のシグネチャを素早く確認したいというニーズは非常に高い。この機能により、開発者はコード上でマウスをホバーするだけで必要な情報を取得でき、コード理解が大幅に効率化される。LuaDocアノテーションによる型情報も表示される。

**機能の利用シーン**：
- 変数の型を確認したい場合
- 関数のパラメータと戻り値を確認したい場合
- ドキュメントコメントを確認したい場合
- 文字列のバイト数/文字数を確認したい場合
- 数値の10進表現を確認したい場合（16進数など）

**主要な処理内容**：
1. カーソル位置のソースノードを特定
2. ソースの種類に応じたラベル（型情報）を生成
3. ソースに関連するドキュメント（説明）を収集
4. 関数の場合は全てのオーバーロードを表示
5. Markdown形式で結果をフォーマット

**関連システム・外部連携**：
- LSPプロトコルの`textDocument/hover`リクエストハンドラ
- 型推論システム（vm.getInfer）
- LuaDocパーサー

**権限による制御**：`Lua.hover.enable`設定で有効/無効を切り替え可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ホバー情報表示 | 主機能 | 変数・関数へのホバー時に型情報・ドキュメントを表示する主処理 |
| 3 | 補完アイテム詳細 | 補助機能 | 補完候補のホバー情報を取得 |
| 40 | ドキュメント生成 | 補助機能 | ドキュメント生成時のホバー情報取得 |

## 機能種別

情報表示 / ドキュメント生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | uri | Yes | 対象ファイルのURI | 有効なファイルURI |
| position | integer | Yes | カーソル位置 | 正の整数 |
| level | integer | No | テーブル展開レベル | デフォルト: 1 |

### 入力データソース

- 対象ファイルのAST状態（files.getState）
- LuaDocアノテーション

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| contents | MarkupContent | Markdown形式のホバー情報 |
| range | Range | ソースノードの範囲 |
| maxLevel | integer | テーブルの最大展開レベル |

### 出力先

LSPレスポンスとしてクライアントに返される

## 処理フロー

### 処理シーケンス

```
1. ホバーが有効か確認
   └─ Lua.hover.enable設定をチェック
2. ワークスペースの準備状況を確認
   └─ 準備中の場合はローディングメッセージを返す
3. ASTを取得
   └─ files.getState(uri)でファイル状態を取得
4. カーソル位置のソースを特定
   └─ findSource(ast, position, accept)で該当ノードを検索
5. @seeアノテーションの場合は実際のシンボルを検索
   └─ ワークスペースシンボル検索で解決
6. ホバー情報を構築
   └─ ラベル生成（label.lua）
   └─ 説明生成（description.lua）
   └─ 関数の場合はオーバーロードも処理
7. Markdown形式でフォーマット
   └─ コードブロックと説明を組み合わせ
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{ホバー有効?}
    B -->|No| C[nil を返す]
    B -->|Yes| D{ワークスペース準備完了?}
    D -->|No| E[ローディングメッセージを返す]
    D -->|Yes| F[AST取得]
    F --> G{AST存在?}
    G -->|No| C
    G -->|Yes| H[ソースノード特定]
    H --> I{ソース存在?}
    I -->|No| C
    I -->|Yes| J{@seeアノテーション?}
    J -->|Yes| K[ワークスペースシンボル検索]
    K --> L[ホバー情報構築]
    J -->|No| L
    L --> M[ラベル生成]
    M --> N[説明生成]
    N --> O{関数か?}
    O -->|Yes| P[オーバーロード処理]
    P --> Q[Markdown生成]
    O -->|No| Q
    Q --> R{内容あり?}
    R -->|No| C
    R -->|Yes| S[結果を返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 対象ノード型 | local, setlocal, getlocal, setglobal, getglobal, field, method, string, number, integer, doc.type.name, doc.class.name, doc.enum.name, function, doc.module, doc.see.name | ソース特定時 |
| BR-02 | ローディング表示 | ワークスペース準備中はローディングメッセージを表示 | ワークスペース未準備時 |
| BR-03 | 関数優先 | function型の定義はdoc.type.functionより先にソート | 関数ホバー時 |
| BR-04 | 重複除去 | 同一ラベル/説明は1回のみ表示 | ホバー構築時 |
| BR-05 | OOPマーク | guide.isOOPがtrueならメソッドとして表示 | 関数ラベル生成時 |

### ラベル生成ルール

| ソース型 | ラベル形式 |
|---------|-----------|
| function | `(async) function/method name(params) -> returns` |
| local | `local name: type = literal` |
| parameter | `(parameter) name: type` |
| upvalue | `(upvalue) name: type` |
| global | `(global) name: type` |
| field | `(field) name: type` |
| string | `X bytes (Y characters)` |
| number | 10進表現（16進等の場合） |
| doc.type.name | `(class/alias/enum) TypeName` |

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

この機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無視 | ASTが取得できない | nilを返す |
| - | 無視 | ソースノードが特定できない | nilを返す |
| - | 無視 | ホバー情報が空 | nilを返す |

### リトライ仕様

リトライは行わない。

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

該当なし

## パフォーマンス要件

- ホバー情報生成は非同期処理（@async）で実行
- テーブル展開レベルを制限してパフォーマンス確保
- LSPの応答性を維持するためprogress表示（0.5秒以上の処理時）

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

特になし

## 備考

- SHOWSOURCE/SHOWNODEデバッグオプションでソース/ノード情報を追加表示可能
- テーブルの展開レベルはクライアントからのパラメータで制御可能
- Markdown形式でコードブロックと説明を組み合わせて表示

---

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

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

### 推奨読解順序

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

ホバー情報の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | init.lua | `script/core/hover/init.lua` | accept テーブル（114-131行目）で対象ノード型を定義 |
| 1-2 | init.lua | `script/core/hover/init.lua` | getHover関数（13-112行目）の構造 |

**読解のコツ**: `markdown()`モジュールを使用してMarkdown形式の出力を構築している。

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

メイン関数の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | init.lua | `script/core/hover/init.lua` | getHoverByUri関数（135-160行目）が外部エントリーポイント |
| 2-2 | provider.lua | `script/provider/provider.lua` | textDocument/hover ハンドラ（340-385行目） |

**主要処理フロー**:
1. **349-351行目**: ホバー有効チェック
2. **352-360行目**: ワークスペース準備状況チェック
3. **362-366行目**: AST取得
4. **367-368行目**: hover.byUri呼び出し
5. **376-383行目**: 結果フォーマット

#### Step 3: ラベル生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | label.lua | `script/core/hover/label.lua` | asFunction関数（12-27行目） - 関数ラベル生成 |
| 3-2 | label.lua | `script/core/hover/label.lua` | asLocal関数（78-96行目） - ローカル変数ラベル生成 |
| 3-3 | label.lua | `script/core/hover/label.lua` | asGlobal関数（100-105行目） - グローバル変数ラベル生成 |
| 3-4 | label.lua | `script/core/hover/label.lua` | メイン関数（203-234行目） - 型別分岐 |

#### Step 4: 説明生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | description.lua | `script/core/hover/description.lua` | asString関数（78-85行目） - require解決 |
| 4-2 | description.lua | `script/core/hover/description.lua` | lookUpDocComments関数（175-213行目） - ドキュメントコメント収集 |
| 4-3 | description.lua | `script/core/hover/description.lua` | tryDocComment関数（400-424行目） - ドキュメント解析 |
| 4-4 | description.lua | `script/core/hover/description.lua` | メイン関数（528-545行目） - 型別分岐 |

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

```
provider.lua ('textDocument/hover' ハンドラ)
    │
    └─ hover/init.lua (byUri関数)
           │
           ├─ files.getState() [AST取得]
           ├─ findSource() [ソースノード特定]
           ├─ wssymbol() [@seeの場合のシンボル検索]
           │
           └─ getHover()
                  │
                  ├─ vm.getInfer() [型推論]
                  ├─ vm.getDefs() [定義取得]
                  │
                  ├─ label.lua (getLabel)
                  │      ├─ buildName() [名前生成]
                  │      ├─ buildArgs() [引数生成]
                  │      ├─ buildReturn() [戻り値生成]
                  │      └─ buildTable() [テーブル展開]
                  │
                  └─ description.lua (getDesc)
                         ├─ asString() [文字列説明]
                         ├─ lookUpDocComments() [ドキュメント収集]
                         ├─ getBindEnums() [列挙値収集]
                         └─ tryDocComment() [ドキュメント解析]
```

### データフロー図

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

URI ─────────────────────┐
                         │
カーソル位置 ─────────────┼──▶ hover.byUri() ──▶ MarkupContent
                         │         │
展開レベル ───────────────┘         │
                                   ▼
                         ┌────────────────┐
                         │ ソースノード特定 │
                         └────────────────┘
                                   │
                                   ▼
                         ┌────────────────┐
                         │   getHover()   │
                         └────────────────┘
                                   │
                         ┌─────────┴─────────┐
                         ▼                   ▼
                   ┌──────────┐       ┌──────────┐
                   │ getLabel │       │ getDesc  │
                   └──────────┘       └──────────┘
                         │                   │
                         ▼                   ▼
                   [型情報]           [ドキュメント]
                         │                   │
                         └─────────┬─────────┘
                                   ▼
                         ┌────────────────┐
                         │ Markdown結合   │
                         └────────────────┘
                                   │
                                   ▼
                         [contents, range]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| init.lua | `script/core/hover/init.lua` | ソース | ホバーのメインモジュール |
| label.lua | `script/core/hover/label.lua` | ソース | ラベル（型情報）生成 |
| description.lua | `script/core/hover/description.lua` | ソース | 説明（ドキュメント）生成 |
| name.lua | `script/core/hover/name.lua` | ソース | 名前生成ユーティリティ |
| args.lua | `script/core/hover/args.lua` | ソース | 引数生成ユーティリティ |
| return.lua | `script/core/hover/return.lua` | ソース | 戻り値生成ユーティリティ |
| table.lua | `script/core/hover/table.lua` | ソース | テーブル展開ユーティリティ |
| provider.lua | `script/provider/provider.lua` | ソース | LSPハンドラ |
| find-source.lua | `script/core/find-source.lua` | ソース | カーソル位置のソースノード特定 |
| markdown.lua | `script/provider/markdown.lua` | ソース | Markdown生成ユーティリティ |
| vm/infer.lua | `script/vm/infer.lua` | ソース | 型推論 |
