# 機能設計書 32-インレイヒント (textDocument/inlayHint)

## 概要

本ドキュメントは、LSPプロトコルの `textDocument/inlayHint` リクエストに対応するインレイヒント提供機能の設計を記述する。型推論結果等のヒント情報をエディタ上にインラインで表示するための情報を返却する。

### 本機能の処理概要

**業務上の目的・背景**：D言語では型推論（`auto`キーワード等）が多用されるが、推論された型が明示的にコード上に現れないため、コード理解が困難になることがある。インレイヒントにより、エディタ上で推論された型情報をインラインで表示し、開発者のコード理解を支援する。LSP仕様の `textDocument/inlayHint` に準拠する。

**機能の利用シーン**：開発者がD言語ソースファイルをエディタで表示している際、エディタがバックグラウンドでこのリクエストを送信し、型推論結果等のインレイヒントを取得する。エディタはコード中の適切な位置にヒントテキストを薄い色で表示する。

**主要な処理内容**：
1. リクエストパラメータからテキストドキュメントを特定し、DCDComponentが利用可能か確認する
2. ドキュメントの言語がD言語であることを確認する
3. DCDComponentの `getInlayHints` を呼び出し、型情報等のヒントデータを取得する
4. 取得したヒントのバイトオフセットをLSPのPositionに変換する
5. ヒント種別（kind 'l' = type）をLSPのInlayHintKindにマッピングする

**関連システム・外部連携**：DCDComponent（DCDサーバー）が型推論結果の取得を担当する。DCDはD言語のセマンティック解析を行い、型情報を提供する。

**権限による制御**：設定項目 `d.enableInlayHints` で有効/無効を切り替え可能（デフォルトはfalse）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | インレイヒント（textDocument/inlayHint） | 主画面 | 型推論結果等のインレイヒントをエディタに提供する |

## 機能種別

データ取得処理（セマンティック解析結果の取得・変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| params.textDocument | TextDocumentIdentifier | Yes | 対象ドキュメントの識別子（URI） | ドキュメントが管理下に存在すること |
| params.range | TextRange | Yes | ヒントを取得する範囲 | - |

### 入力データソース

LSPクライアントからの `textDocument/inlayHint` リクエスト。テキストドキュメントの生テキストはDocumentManagerから取得する。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | InlayHint[] | インレイヒントの配列。エラー時やD言語以外の場合はnull |
| InlayHint.position | Position | ヒントの表示位置 |
| InlayHint.label | string | ヒントのラベルテキスト（型名等） |
| InlayHint.kind | Optional!InlayHintKind | ヒント種別（type=1, parameter=2） |

### 出力先

LSPクライアントへのレスポンスとして返却する。

## 処理フロー

### 処理シーケンス

```
1. DCDComponentインスタンス取得
   └─ backend.getBestInstance!DCDComponent でファイルに対応するインスタンスを取得
   └─ インスタンスが存在しない場合はnullを返却
2. ドキュメント取得・言語チェック
   └─ documents[params.textDocument.uri]でドキュメント取得
   └─ getLanguageId != "d" の場合はnullを返却
3. インレイヒント取得
   └─ instance.get!DCDComponent.getInlayHints(document.rawText).getYield で非同期取得
   └─ 結果が空の場合はnullを返却
4. ヒント変換ループ
   └─ 各ヒントについて:
     └─ kind 'l' → InlayHintKind.type に変換
     └─ symbolLocation を movePositionBytes でPositionに変換
     └─ identifier をlabelに設定
5. 結果返却
   └─ InlayHint配列を返却
```

### フローチャート

```mermaid
flowchart TD
    A[textDocument/inlayHint リクエスト受信] --> B{DCDComponent利用可能?}
    B -->|No| C[null を返却]
    B -->|Yes| D[ドキュメント取得]
    D --> E{言語がD言語?}
    E -->|No| C
    E -->|Yes| F[getInlayHints 呼び出し]
    F --> G{結果あり?}
    G -->|No| C
    G -->|Yes| H[バイトオフセット→Position変換]
    H --> I[kind マッピング]
    I --> J[InlayHint配列を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-32-01 | D言語限定 | D言語ファイル以外ではnullを返却する | 常時 |
| BR-32-02 | DCD必須 | DCDComponentが利用不可の場合はnullを返却する | 常時 |
| BR-32-03 | 種別マッピング | kind 'l' を InlayHintKind.type にマッピングする | 常時 |
| BR-32-04 | デフォルト無効 | d.enableInlayHints設定のデフォルトはfalse | 設定参照時 |

### 計算ロジック

特になし。

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

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

本機能にデータベース操作は存在しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | コンポーネント未初期化 | DCDComponentがバックエンドに登録されていない | nullを返却 |
| - | 非D言語ファイル | ドキュメントの言語IDが "d" でない | nullを返却 |
| - | 空結果 | DCDが結果を返さない場合 | nullを返却 |

### リトライ仕様

リトライは行わない。

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

トランザクション管理は不要（読み取り専用処理）。

## パフォーマンス要件

DCDサーバーとの通信が含まれるため、レスポンス時間はDCDサーバーの処理速度に依存する。getYieldによる非同期処理で待機するが、ファイバーベースのため他のリクエスト処理をブロックしない。

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

特になし。ローカルファイルの読み取り専用処理のみ。

## 備考

- 設定項目 `d.enableInlayHints` のデフォルト値はfalse（types.d 99行目）であり、ユーザーが明示的に有効化する必要がある。
- サーバー初期化時にinlayHintProviderがtrueとしてサーバーケイパビリティに登録される（extension.d 315行目）。
- 現在の実装ではkind 'l'（type）のみがマッピングされ、それ以外のkindはOptional未設定のまま送信される。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protocol.d | `protocol/source/served/lsp/protocol.d` | InlayHintParams（3091行目）、InlayHint構造体（3098行目）、InlayHintKind列挙型（3111行目）を確認 |
| 1-2 | types.d | `source/served/types.d` | 設定項目 `enableInlayHints`（99行目、デフォルトfalse）を確認 |

**読解のコツ**: InlayHintのlabelフィールドは `Variant!(string, InlayHintLabelPart[])` 型だが、本実装ではstringのみ使用している。

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

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

**主要処理フロー**:
1. **12-13行目**: `backend.getBestInstance!DCDComponent` でDCDインスタンス取得
2. **14-15行目**: インスタンスがなければnull返却
3. **18-19行目**: 言語IDが "d" でなければnull返却
4. **21行目**: `getInlayHints(document.rawText).getYield` で非同期にヒント取得
5. **32-36行目**: kind 'l' を `InlayHintKind.type` にマッピング
6. **40行目**: `movePositionBytes` でバイトオフセットをPosition変換
7. **41行目**: `identifier` をlabelに設定

#### Step 3: DCD側の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | client.d | `dcd/source/served/dcd/client.d` | DCDクライアントの `getInlayHints` メソッドがDCDサーバーへリクエストを送信 |
| 3-2 | dcd.d (workspace-d) | `workspace-d/source/workspaced/com/dcd.d` | DCDComponentの `getInlayHints` がクライアント経由でDCDサーバーにアクセス |

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

```
provideInlayHints (inlay_hints.d:10)
    |
    +-- backend.getBestInstance!DCDComponent (インスタンス取得)
    |
    +-- documents[uri] (ドキュメント取得)
    |
    +-- document.getLanguageId (言語チェック)
    |
    +-- instance.get!DCDComponent.getInlayHints(rawText)
    |       |
    |       +-- DCDサーバーへのリクエスト送信
    |       +-- .getYield (非同期結果待機)
    |
    +-- document.movePositionBytes (バイト→Position変換)
```

### データフロー図

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

InlayHintParams       ──▶  provideInlayHints             ──▶  InlayHint[]
  .textDocument.uri         |
  .range                    +-- DCDComponent
                            |     .getInlayHints(rawText)
                            |     (kind, symbolLocation,
                            |      identifier)
                            +-- movePositionBytes()
                            |     (バイト→Position変換)
                            +-- kindマッピング
                                  ('l' → type)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| inlay_hints.d | `source/served/commands/inlay_hints.d` | ソース | LSPリクエストハンドラ（メイン処理） |
| protocol.d | `protocol/source/served/lsp/protocol.d` | ソース | InlayHint/InlayHintParams等のLSP型定義 |
| client.d | `dcd/source/served/dcd/client.d` | ソース | DCDサーバーとの通信クライアント |
| dcd.d | `workspace-d/source/workspaced/com/dcd.d` | ソース | DCDComponent実装（getInlayHints） |
| extension.d | `source/served/extension.d` | ソース | サーバーケイパビリティにinlayHintProviderを登録（315行目） |
| types.d | `source/served/types.d` | ソース | 設定項目enableInlayHints定義（99行目） |
