# 画面設計書 25-ドキュメントハイライト（textDocument/documentHighlight）

## 概要

本ドキュメントは、serve-d LSPサーバーにおける `textDocument/documentHighlight` リクエストの処理仕様を定義する画面設計書である。カーソル位置のシンボルと同一のシンボルが使用されている箇所をハイライト表示する機能を記述する。

### 本画面の処理概要

**業務上の目的・背景**：D言語ソースコードを編集する際に、カーソル位置のシンボル（変数名、関数名等）がドキュメント内の他の箇所でも使用されている場合、それらの箇所を視覚的にハイライト表示する機能である。これにより、変数のスコープ内での使用状況を素早く把握でき、コードの理解やリファクタリングの計画に役立つ。DCDによるローカル使用箇所検索（主方式）と、DCDExtによるフォールバック方式の二段構えで実装されている。

**画面へのアクセス方法**：エディタ上でD言語ソースファイルのシンボル上にカーソルを置くと、自動的に `textDocument/documentHighlight` リクエストが送信される。ユーザーが明示的に操作する必要はない。

**主要な操作・処理内容**：
1. DCDによるハイライト（enableDCDHighlight設定有効時）: DCDの `findLocalUse` を使用してローカル変数の宣言箇所と使用箇所を検出する
2. DCDExtによるフォールバックハイライト（enableFallbackHighlight設定有効時）: DCDの結果が空の場合にDCDExtの `highlightRelated` で関連するトークンを検出する
3. 宣言箇所は `write` 種別、使用箇所は `read` 種別、フォールバックは `text` 種別でハイライト情報を返却する

**画面遷移**：本機能は独立した情報提供機能であり、他の画面への遷移は発生しない。ただし、`documentHighlightImpl` 関数はリネーム機能（No.28）からも内部的に呼び出される。

**権限による表示制御**：権限による表示制御は存在しない。設定 `config.d.enableDCDHighlight` および `config.d.enableFallbackHighlight` によりハイライト方式の有効/無効を制御できる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 22 | ドキュメントハイライト (textDocument/documentHighlight) | 主機能 | カーソル位置のシンボルのローカル使用箇所をハイライト情報として返却する（DCD・DCDExtの二段構え） |

## 画面種別

情報提供（LSPプロトコルレスポンス）

## URL/ルーティング

- LSPメソッド: `textDocument/documentHighlight`

## 入出力項目

| 項目名 | 型 | 入力/出力 | 必須 | 説明 |
|--------|-----|----------|------|------|
| params.textDocument.uri | DocumentUri | 入力 | Yes | 対象ドキュメントのURI |
| params.position | Position | 入力 | Yes | カーソル位置 |
| DocumentHighlight[] | DocumentHighlight[] | 出力 | - | ハイライト情報の配列 |
| DocumentHighlight.range | TextRange | 出力 | - | ハイライト対象のテキスト範囲 |
| DocumentHighlight.kind | DocumentHighlightKind | 出力 | - | ハイライト種別（write/read/text） |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|---------|------|
| 宣言箇所ハイライト | writeハイライト | シンボルの宣言箇所（通常は太い下線や背景色の変更） |
| 使用箇所ハイライト | readハイライト | シンボルの参照箇所（通常は薄い背景色の変更） |
| 関連トークンハイライト | textハイライト | フォールバック時の関連トークン |

## イベント仕様

### 1-ドキュメントハイライト検出

カーソル位置が変更された際に自動的にトリガーされる処理フロー。

1. ドキュメントをcloneして不変（immutable）コピーを作成する（行14）
2. カーソル位置をバイトオフセットに変換する（行15）
3. ファイルの設定（fileConfig）を取得する（行16）
4. `enableDCDHighlight` 設定が有効な場合、`documentHighlightImpl` を呼び出す（行18）
5. DCDの結果が空で `enableFallbackHighlight` が有効な場合、`fallbackDocumentHighlight` を呼び出す（行20-21）

### 2-DCDによるハイライト（documentHighlightImpl）

`documentHighlightImpl` 関数（行26-58）の処理フロー。

1. DCDコンポーネントの存在を確認する（行31）
2. `DCDComponent.findLocalUse` でカーソル位置のシンボルのローカル使用箇所を検索する（行39）
3. 宣言箇所が `"stdin"`（現在のファイル内）の場合:
   a. `wordRangeAt` で宣言箇所のワード範囲を取得する（行43）
   b. `DocumentHighlightKind.write` として登録する（行46）
4. 各使用箇所について:
   a. `wordRangeAt` でワード範囲を取得する（行51）
   b. `DocumentHighlightKind.read` として登録する（行54）

### 3-フォールバックハイライト（fallbackDocumentHighlight）

`fallbackDocumentHighlight` 関数（行60-80）の処理フロー。

1. DCDExtコンポーネントの存在を確認する（行63）
2. `DCDExtComponent.highlightRelated` でカーソル位置に関連するトークンを検索する（行72）
3. 各関連トークンについて:
   a. range情報からPositionに変換する（行74-75）
   b. `DocumentHighlightKind.text` として登録する（行76）

## データベース更新仕様

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

本機能はデータベースに対する操作を行わない。DCDの解析結果を参照する読み取り専用の処理である。

## メッセージ仕様

| メッセージ | 条件 | 種別 |
|-----------|------|------|
| `localUse: {result}` | DCDのfindLocalUse結果をログ出力 | ログ（trace） |

## 例外処理

| 条件 | 挙動 |
|------|------|
| DCDコンポーネントが利用不可 | `null` を返却 |
| DCDExtコンポーネントが利用不可（フォールバック時） | `null` を返却 |
| シンボルが見つからない | 空の `DocumentHighlight[]` を返却 |

## 備考

- `documentHighlightImpl` はpackageスコープで公開されており、リネーム機能（`served.commands.rename`）から直接呼び出される
- ドキュメントは `cast(immutable)documents[uri].clone()` で不変コピーを作成して処理する。これはスレッドセーフティのための設計である
- DCDの `findLocalUse` はローカル変数のスコープ内使用箇所を返すため、異なるスコープの同名変数は区別される
- フォールバック方式のDCDExtの `highlightRelated` は、DCDとは異なるアルゴリズムで関連トークンを検出する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protocol.d | `source/served/lsp/protocol.d` | `DocumentHighlight`, `DocumentHighlightKind`, `DocumentHighlightParams` の定義を確認 |

**読解のコツ**: `DocumentHighlightKind` は `text`(1), `read`(2), `write`(3) の3種類がある。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | highlight.d | `source/served/commands/highlight.d` | `provideDocumentHighlight` 関数（行11-24）: LSPリクエストハンドラ |

**主要処理フロー**:
1. **行11**: `@protocolMethod("textDocument/documentHighlight")` でバインド
2. **行14**: ドキュメントの不変コピー作成
3. **行16**: ファイル設定取得
4. **行18**: `enableDCDHighlight` 判定で `documentHighlightImpl` 呼び出し
5. **行20-21**: フォールバック判定で `fallbackDocumentHighlight` 呼び出し

#### Step 3: DCD方式のハイライトを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | highlight.d | `source/served/commands/highlight.d` | `documentHighlightImpl` 関数（行26-58）: DCDによるローカル使用箇所検索 |

**主要処理フロー**:
- **行39**: `findLocalUse` でDCDに問い合わせ
- **行41-47**: 宣言箇所を `write` 種別で登録
- **行49-55**: 使用箇所を `read` 種別で登録

#### Step 4: フォールバック方式を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | highlight.d | `source/served/commands/highlight.d` | `fallbackDocumentHighlight` 関数（行60-80）: DCDExtによるフォールバック |

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

```
textDocument/documentHighlight リクエスト
    |
    +-- provideDocumentHighlight (highlight.d:11)
           |
           +-- documents[uri].clone() (不変コピー作成)
           +-- config(document.uri) (設定取得)
           |
           +-- [enableDCDHighlight]
           |      +-- documentHighlightImpl (highlight.d:26)
           |             +-- backend.best!DCDComponent.findLocalUse
           |             +-- document.wordRangeAt (ワード範囲取得)
           |
           +-- [結果なし && enableFallbackHighlight]
                  +-- fallbackDocumentHighlight (highlight.d:60)
                         +-- backend.best!DCDExtComponent.highlightRelated
```

### データフロー図

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

DocumentHighlightParams ------> provideDocumentHighlight ---------> DocumentHighlight[]
  textDocument.uri                |
  position                        +-- DCDComponent.findLocalUse
                                  |      --> 宣言位置 + 使用箇所リスト
                                  |      --> DocumentHighlight(write/read)
                                  |
                                  +-- [フォールバック]
                                         DCDExtComponent.highlightRelated
                                         --> 関連トークンリスト
                                         --> DocumentHighlight(text)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| highlight.d | `source/served/commands/highlight.d` | ソース | ドキュメントハイライトの主処理 |
| rename.d | `source/served/commands/rename.d` | ソース | documentHighlightImplを呼び出すリネーム機能 |
| types.d | `source/served/types.d` | ソース | 共通型定義 |
| protocol.d | `source/served/lsp/protocol.d` | ソース | LSPプロトコル型定義 |
