# 画面設計書 22-定義ジャンプ（textDocument/definition）

## 概要

本ドキュメントは、serve-d LSPサーバーにおける `textDocument/definition` リクエストの処理仕様を定義する画面設計書である。カーソル位置のシンボルの定義箇所へジャンプする機能を提供し、DCDコンポーネントを使用してシンボル解決を行う。

### 本画面の処理概要

**業務上の目的・背景**：D言語開発において、関数・変数・型などのシンボルの定義箇所へ素早く移動できることは、コードリーディングやデバッグの効率に直結する重要な機能である。本機能はLSPプロトコルの `textDocument/definition` を通じて、エディタの「定義へ移動（Go to Definition）」機能を実現する。DCD（D Completion Daemon）を使用してシンボルの定義位置を解決し、同一ファイル内および外部ファイルの定義箇所にジャンプできる。

**画面へのアクセス方法**：エディタ上でD言語ソースファイルのシンボル上にカーソルを置き、「定義へ移動」コマンド（通常はF12キーまたはCtrl+クリック）を実行する。エディタが `textDocument/definition` リクエストをLSPサーバーに送信する。

**主要な操作・処理内容**：
1. DCDコンポーネントを使用して、カーソル位置のシンボルの定義箇所（ファイル・位置）を解決する
2. 定義箇所のファイルが外部ファイルの場合はURIに変換する
3. DCDExtコンポーネントが利用可能な場合は、宣言範囲を精密に取得する
4. DfmtComponentが利用可能な場合は、宣言テキストのフォーマットを行う
5. 定義位置情報を `Location` として返却する

**画面遷移**：定義ジャンプの結果、エディタは対象ファイルの定義箇所を開いて移動する。遷移先は定義が存在する任意のD言語ソースファイルとなる。画面遷移図の「シンボル操作」サブグラフにおいて「定義へ移動」として位置付けられている。

**権限による表示制御**：権限による表示制御は存在しない。D言語ファイルであれば一律に定義ジャンプ機能が利用可能である。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 18 | 定義ジャンプ (textDocument/definition) | 主機能 | DCDを使用してカーソル位置のシンボルの定義元位置を返却する |

## 画面種別

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

## URL/ルーティング

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

## 入出力項目

| 項目名 | 型 | 入力/出力 | 必須 | 説明 |
|--------|-----|----------|------|------|
| params.textDocument.uri | DocumentUri | 入力 | Yes | 対象ドキュメントのURI |
| params.position | Position | 入力 | Yes | カーソル位置（行・列） |
| ArrayOrSingle!Location | Location[] | 出力 | - | 定義箇所のLocation（見つからない場合はinit） |
| Location.uri | DocumentUri | 出力 | - | 定義箇所のドキュメントURI |
| Location.range | TextRange | 出力 | - | 定義箇所のテキスト範囲 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|---------|------|
| 定義箇所 | エディタ遷移 | 定義が見つかった場合、対象ファイルの該当位置にエディタが遷移する |

## イベント仕様

### 1-定義ジャンプ実行

ユーザーが「定義へ移動」を実行した際の処理フロー。

1. `backend.getBestInstance!DCDComponent` でカレントファイルに最適なDCDインスタンスを取得する
2. インスタンスが存在しない場合は空の結果を返却する
3. 言語IDが `"d"` でなければ空の結果を返却する
4. `document.positionToBytes` でカーソル位置をバイトオフセットに変換する
5. `findDeclarationImpl` で定義箇所を検索する:
   a. DCDの `findDeclaration` でシンボルの定義位置を取得する
   b. 結果ファイルが `"stdin"` でない場合はURIに変換する
   c. 対象ファイルのドキュメントを取得（ファイルシステムから一時ロードする場合あり）
   d. DCDExtComponentが利用可能なら `getDeclarationRange` で宣言範囲を精密に取得する
   e. DfmtComponentが利用可能なら宣言テキストをフォーマットする（`includeDefinition=true`）
   f. 一時ロードしたドキュメントはアンロードする
6. 結果を `Location` として返却する

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

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

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

## メッセージ仕様

本機能は明示的なメッセージ表示を行わない。定義が見つからない場合はinit値が返却され、エディタ側で「定義が見つかりません」等のメッセージが表示される（エディタ側の実装依存）。

## 例外処理

| 条件 | 挙動 |
|------|------|
| DCDコンポーネントが利用不可 | `ArrayOrSingle!Location.init` を返却 |
| D言語ファイル以外 | `ArrayOrSingle!Location.init` を返却 |
| DCDがシンボルを見つけられない | `ArrayOrSingle!Location.init` を返却 |
| 相対パスの結果ファイル | URIがnullとなり、Locationの構築に影響 |

## 備考

- 本関数は `findDeclarationImpl` を `includeDefinition=true` で呼び出すため、宣言だけでなく定義本体の範囲も含む
- `findDeclarationImpl` は `textDocument/hover` (provideHover) でも `includeDefinition=false` で共有使用されている
- DCDExtComponentが利用可能な場合は宣言範囲が精密に取得され、利用不可の場合は単一位置（Position→Position）の範囲となる
- DfmtComponentによるフォーマットは、宣言テキストの整形のみを目的とし、ファイル自体は変更しない

---

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

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

### 推奨読解順序

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

定義ジャンプの入出力に使用されるデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | definition.d | `source/served/commands/definition.d` | `DeclarationInfo` 構造体（行18-22）: 宣言テキストと位置を保持する内部構造体 |
| 1-2 | protocol.d | `source/served/lsp/protocol.d` | `Location`, `TextDocumentPositionParams`, `Position`, `TextRange` の定義を確認 |

**読解のコツ**: `DeclarationInfo` は内部構造体であり、LSPレスポンスには `Location` 部分のみが使用される。`declaration` フィールドはhover表示で利用される。

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

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

**主要処理フロー**:
1. **行99**: `@protocolMethod("textDocument/definition")` でLSPメソッドにバインド
2. **行102-103**: `backend.getBestInstance!DCDComponent` でDCDインスタンス取得
3. **行108**: 言語IDチェック（`"d"` 以外は除外）
4. **行111-112**: `findDeclarationImpl` を `includeDefinition=true` で呼び出し
5. **行116**: `Location` を返却

#### Step 3: 定義検索の内部処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | definition.d | `source/served/commands/definition.d` | `findDeclarationImpl` 関数（行24-89）がDCD呼び出しとURIの解決を行う |
| 3-2 | definition.d | `source/served/commands/definition.d` | `getDeclarationRange` 関数（行91-97）がDCDExtによる精密な宣言範囲取得を行う |

**主要処理フロー**:
- **行27**: `instance.get!DCDComponent.findDeclaration` でDCDに定義位置を問い合わせ
- **行32-38**: 結果ファイルが `"stdin"` でなければ絶対パスからURIに変換
- **行44**: `documents.getOrFromFilesystem` でドキュメント取得（一時ロード含む）
- **行49-55**: DCDExtComponentが利用可能なら `getDeclarationRange` で宣言範囲を精密に取得
- **行56-60**: 精密な範囲が得られない場合はバイト位置から `Position` を算出
- **行67-81**: DfmtComponentによる宣言テキストのフォーマット
- **行83-84**: 一時ロードしたドキュメントはアンロード

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

```
textDocument/definition リクエスト
    |
    +-- provideDefinition (definition.d:99)
           |
           +-- backend.getBestInstance!DCDComponent (インスタンス取得)
           +-- documents[uri] (ドキュメント取得)
           +-- document.positionToBytes (位置変換)
           +-- findDeclarationImpl (definition.d:24)
                  |
                  +-- DCDComponent.findDeclaration (DCD呼び出し)
                  +-- uriFromFile (URI変換)
                  +-- documents.getOrFromFilesystem (外部ファイルロード)
                  +-- getDeclarationRange (definition.d:91)
                  |      +-- DCDExtComponent.getDeclarationRange
                  |      +-- doc.byteRangeToTextRange
                  +-- DfmtComponent.formatSync (宣言テキストフォーマット)
                  +-- documents.unloadDocument (一時ファイルアンロード)
```

### データフロー図

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

TextDocumentPositionParams ---> provideDefinition ----------------> Location
  textDocument.uri                |
  position                        +-- DCDComponent.findDeclaration
                                  |      --> ファイルパス + バイトオフセット
                                  +-- URI変換 / ドキュメント取得
                                  +-- DCDExtComponent (宣言範囲精密化)
                                  +-- DfmtComponent (テキストフォーマット)
                                  +-- Location(uri, range) 構築
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| definition.d | `source/served/commands/definition.d` | ソース | 定義ジャンプとホバーの主処理 |
| types.d | `source/served/types.d` | ソース | 共通型定義・documents・backend等のエイリアス |
| protocol.d | `source/served/lsp/protocol.d` | ソース | LSPプロトコル型定義 |
| extension.d | `source/served/extension.d` | ソース | activeInstance等のグローバル変数定義 |
| textdocumentmanager.d | `source/served/lsp/textdocumentmanager.d` | ソース | ドキュメント管理、位置変換 |
| uri.d | `source/served/lsp/uri.d` | ソース | URI変換ユーティリティ |
