# 画面設計書 5-定義へ移動

## 概要

本ドキュメントは、Lua Language Serverの「定義へ移動」機能の設計を記載したものである。LSP（Language Server Protocol）の `textDocument/definition` メソッドに対応し、シンボルの定義位置へジャンプする機能を提供する。

### 本画面の処理概要

**業務上の目的・背景**：
大規模なコードベースでは、変数や関数がどこで定義されているかを素早く特定することが重要である。本機能により、開発者はシンボル上でF12キーを押すだけで、そのシンボルが定義されている場所へ即座にジャンプできる。これにより、コードの理解とナビゲーションが大幅に効率化される。

**画面へのアクセス方法**：
エディタ（VS Code等）上でLuaファイルを開き、変数名・関数名・クラス名などのシンボル上で以下の操作を行う：
- F12キーを押す
- 右クリックメニューから「定義へ移動」を選択
- Ctrl+クリック

**主要な操作・処理内容**：
1. エディタからLSPサーバーへ `textDocument/definition` リクエストを送信
2. カーソル位置からソースオブジェクトを特定
3. `require` 文字列の場合、モジュールファイルを検索
4. `vm.getDefs` で定義を取得
5. 結果をソート・フィルタリング
6. Location または LocationLink 形式でエディタへ返却
7. エディタが定義位置へジャンプ（またはピークビュー表示）

**画面遷移**：
- 遷移元：エディタのコード編集画面
- 遷移先：定義位置のファイル（同一ファイルまたは別ファイル）
- 関連遷移：参照検索（定義位置から全参照を検索）

**権限による表示制御**：
本機能に権限による表示制御はない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | 定義へ移動 (textDocument/definition) | 主機能 | シンボルの定義位置へジャンプする主処理 |
| 16 | 参照検索 (textDocument/references) | 遷移先機能 | 定義位置から参照箇所を検索 |

## 画面種別

ナビゲーション

## URL/ルーティング

LSPメソッド: `textDocument/definition`

**リクエストパラメータ**:
```json
{
  "textDocument": {
    "uri": "file:///path/to/file.lua"
  },
  "position": {
    "line": 10,
    "character": 15
  }
}
```

## 入出力項目

### 入力項目

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| textDocument.uri | string | Yes | 対象ファイルのURI |
| position.line | integer | Yes | カーソル位置の行番号（0始まり） |
| position.character | integer | Yes | カーソル位置の列番号（0始まり） |

### 出力項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (配列) | Location[] または LocationLink[] | 定義位置のリスト |
| [].uri | string | 定義位置のファイルURI |
| [].range | Range | 定義位置の範囲 |
| [].targetUri | string | (LocationLink) ターゲットファイルURI |
| [].targetRange | Range | (LocationLink) ターゲット範囲 |
| [].targetSelectionRange | Range | (LocationLink) ターゲット選択範囲 |
| [].originSelectionRange | Range | (LocationLink) 元の選択範囲 |

## 表示項目

### 定義移動結果

| 表示項目 | 形式 | 説明 |
|---------|------|------|
| ジャンプ先 | エディタ表示 | 定義位置が1つの場合、直接ジャンプ |
| ピークビュー | ポップアップ | 定義位置が複数の場合、選択リスト表示 |

## イベント仕様

### 1-定義移動リクエスト処理

1. エディタがF12等を検出し、LSPサーバーへ `textDocument/definition` リクエストを送信
2. `provider.lua` の `textDocument/definition` ハンドラが呼び出される
3. ワークスペースの準備状態を確認
4. `core/definition.lua` の関数を呼び出し
5. `findSource` でカーソル位置のソースオブジェクトを特定
6. `checkRequire` で require 文字列の場合、モジュールファイルを検索
7. `checkSee` で LuaDoc の `@see` タグを処理
8. `vm.getDefs` でシンボルの定義を取得
9. 結果をソート（URI順、位置順）
10. ネストした結果をフィルタリング（小さい範囲を優先）
11. `jumpSource` で関数本体へのジャンプを調整
12. `convertDefinitionResult` で LSP 形式に変換
13. レスポンスとしてエディタへ返却

### 2-require解決処理

`require("module")` 文字列上で定義移動を実行した場合：

1. 文字列が `callargs` の第一引数であることを確認
2. 呼び出し先関数が `require` / `dofile` / `loadfile` であることを確認
3. `rpath.findUrisByRequireName` でモジュールファイルを検索
4. 見つかったファイルの先頭位置（0, 0）を定義位置として返却

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

本機能はデータベース操作を行わない（読み取り専用）。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|---------------|---------|
| WINDOW_PROCESSING_DEFINITION | 情報 | 処理中表示 | 定義検索実行中 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| ファイルが存在しない | `nil` を返却 |
| カーソル位置にシンボルがない | `nil` を返却 |
| 定義が見つからない | `nil` を返却 |

## 備考

- `linkSupport` クライアント能力がある場合、`LocationLink` 形式で返却
- `doc.class.name`, `doc.alias.name` 等のLuaDoc要素の定義にも対応
- `global` タイプのノードはスキップされる（グローバル名前空間自体への移動を防止）
- 結果が複数の場合、エディタがピークビューで選択肢を表示

---

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

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

### 推奨読解順序

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

定義移動で扱うデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | parser/guide.lua | `script/parser/guide.lua` | ASTノードの種類と構造 |
| 1-2 | vm/init.lua | `script/vm/init.lua` | `getDefs` 関数の動作 |

**読解のコツ**: `accept` テーブルで処理対象のノード種類を確認する。

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

処理の起点となるプロバイダーファイルを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | provider.lua | `script/provider/provider.lua` | LSPメソッドの登録とリクエスト処理 |

**主要処理フロー**:
1. **420-443行目**: `textDocument/definition` ハンドラの定義
2. **428行目**: `workspace.awaitReady` でワークスペース準備待ち
3. **434行目**: `core.definition` モジュールの呼び出し
4. **436行目**: 定義検索実行
5. **440行目**: `convertDefinitionResult` で結果変換
6. **387-418行目**: `convertDefinitionResult` 関数の定義

#### Step 3: コア定義検索ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | definition.lua | `script/core/definition.lua` | 定義検索のメインロジック |

**主要処理フロー（definition.lua）**:
- **10-34行目**: `sortResults` - 結果のソートとフィルタリング
- **36-60行目**: `accept` テーブル - 処理対象ノード種類の定義
- **62-87行目**: `checkRequire` - require文字列の解決
- **89-108行目**: `convertIndex` - インデックスアクセスの変換
- **110-127行目**: `checkSee` - @seeタグの処理
- **130-238行目**: メイン関数 - 定義検索のエントリーポイント

#### Step 4: 補助モジュールを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | find-source.lua | `script/core/find-source.lua` | ソースオブジェクト検索 |
| 4-2 | jump-source.lua | `script/core/jump-source.lua` | ジャンプ先調整 |
| 4-3 | require-path.lua | `script/workspace/require-path.lua` | requireパス解決 |

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

```
textDocument/definition (provider.lua:420)
    │
    ├─ workspace.awaitReady(uri)
    │
    ├─ files.getState(uri)
    │
    ├─ converter.unpackPosition()
    │
    └─ core.definition(uri, pos)
           │
           ├─ findSource(ast, offset, accept)
           │
           ├─ convertIndex(source)
           │
           ├─ checkRequire(source)
           │      └─ rpath.findUrisByRequireName()
           │
           ├─ checkSee(source, results)
           │      └─ wssymbol()
           │
           ├─ vm.getDefs(source)
           │
           ├─ sortResults(results)
           │
           └─ jumpSource(results)
```

### データフロー図

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

textDocument.uri    ───▶ files.getState(uri)     ───▶  AST State
position            ───▶ converter.unpackPosition ───▶  内部位置
                         │
                         ▼
                    findSource()                  ───▶  Source Object
                         │
                         ├──▶ checkRequire()     ───▶  Module URIs
                         │
                         └──▶ vm.getDefs()       ───▶  Definition List
                                   │
                                   ▼
                              sortResults()       ───▶  Sorted List
                                   │
                                   ▼
                              jumpSource()        ───▶  Adjusted List
                                   │
                                   ▼
                         convertDefinitionResult() ───▶  LSP Response
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| provider.lua | `script/provider/provider.lua` | ソース | LSPプロバイダー・エントリーポイント |
| definition.lua | `script/core/definition.lua` | ソース | 定義検索のメインロジック |
| find-source.lua | `script/core/find-source.lua` | ソース | ソースオブジェクト検索 |
| jump-source.lua | `script/core/jump-source.lua` | ソース | ジャンプ先調整 |
| require-path.lua | `script/workspace/require-path.lua` | ソース | requireパス解決 |
| workspace-symbol.lua | `script/core/workspace-symbol.lua` | ソース | ワークスペースシンボル検索 |
| vm/init.lua | `script/vm/init.lua` | ソース | 型推論・定義検索エンジン |
| converter.lua | `script/proto/converter.lua` | ソース | LSP位置変換 |
