# 機能設計書 33-コードナビゲーション

## 概要

本ドキュメントは、OpenCodeにおけるLSPを使用したコードナビゲーション機能について記載する。この機能により、AIアシスタントはシンボルの定義位置へのジャンプ、参照検索、実装検索、コールヒエラルキー取得などを実行でき、コードベースの深い理解が可能となる。

### 本機能の処理概要

**業務上の目的・背景**：大規模なコードベースを理解・修正する際、関数やクラスの定義場所、どこから呼び出されているか、どのインターフェースを実装しているかといった情報が不可欠である。LSPを活用したコードナビゲーション機能により、AIアシスタントはコードベース全体の構造を把握し、適切な修正箇所の特定や影響範囲の分析が可能となる。

**機能の利用シーン**：
- 関数の実装を確認するために定義位置へジャンプする
- 特定の関数がどこから呼び出されているかを参照検索で確認する
- インターフェースを実装している全クラスを実装検索で特定する
- 関数のコールヒエラルキーを取得して呼び出し関係を可視化する
- シンボル上でホバー情報を取得して型情報やドキュメントを確認する

**主要な処理内容**：
1. 定義ジャンプ（goToDefinition）: シンボルの定義位置を取得
2. 参照検索（findReferences）: シンボルが参照されている全箇所を取得
3. 実装検索（goToImplementation）: インターフェース/抽象クラスの実装を取得
4. ホバー情報取得（hover）: シンボルの型情報やドキュメントを取得
5. コールヒエラルキー準備（prepareCallHierarchy）: コールヒエラルキーの起点を取得
6. 着信呼び出し（incomingCalls）: このシンボルを呼び出している関数一覧
7. 発信呼び出し（outgoingCalls）: このシンボルから呼び出している関数一覧

**関連システム・外部連携**：
- 各言語のLSPサーバー（コードナビゲーション情報の提供元）
- LSPツール（エージェントからの利用インターフェース）

**権限による制御**：LSPツール使用時には`lsp`権限の確認が行われる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | セッション | 補助機能 | LSPツールの実行結果表示 |

## 機能種別

データ取得 / コード解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| operation | string | Yes | 実行する操作種別 | goToDefinition, findReferences等 |
| filePath | string | Yes | 対象ファイルの絶対または相対パス | ファイルが存在すること |
| line | number | Yes | 行番号（1-based） | 1以上の整数 |
| character | number | Yes | 文字位置（1-based） | 1以上の整数 |

### 入力データソース

- ファイルシステム: 対象ファイルの存在確認
- LSPサーバー: コードナビゲーション情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Location | object | 位置情報 |
| Location.uri | string | ファイルURI |
| Location.range | Range | 開始・終了位置 |
| Range.start | Position | 開始位置 |
| Range.end | Position | 終了位置 |
| HoverResult | object | ホバー情報 |
| CallHierarchyItem | object | コールヒエラルキー項目 |

### 出力先

- ツール実行結果: JSON形式で結果を返却

## 処理フロー

### 処理シーケンス

```
1. 入力検証
   └─ ファイルパスの絶対パス変換
   └─ 外部ディレクトリアクセスチェック
   └─ ファイル存在確認

2. 権限確認
   └─ lsp権限の確認

3. LSPクライアント準備
   └─ 対応クライアントの有無確認
   └─ ファイルのタッチ（診断待機付き）

4. LSPリクエスト送信
   └─ 操作種別に応じたメソッド呼び出し
   └─ 位置情報の0-based変換

5. 結果処理
   └─ 空結果の場合はメッセージ生成
   └─ 結果をJSON形式で返却
```

### フローチャート

```mermaid
flowchart TD
    A[LSPツール呼び出し] --> B[ファイルパス解決]
    B --> C[外部ディレクトリチェック]
    C --> D{許可?}
    D -->|No| E[エラー]
    D -->|Yes| F[lsp権限確認]
    F --> G[ファイル存在確認]
    G --> H{存在?}
    H -->|No| I[File not foundエラー]
    H -->|Yes| J[LSPクライアント確認]
    J --> K{クライアントあり?}
    K -->|No| L[No LSP serverエラー]
    K -->|Yes| M[touchFile実行]
    M --> N[operation分岐]
    N --> O[LSPリクエスト送信]
    O --> P{結果あり?}
    P -->|No| Q[No results foundメッセージ]
    P -->|Yes| R[JSON形式で結果返却]
    Q --> S[終了]
    R --> S
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-33-01 | 位置変換 | 入力の1-based位置を0-basedに変換してLSPに送信 | 全操作 |
| BR-33-02 | URI変換 | ファイルパスをfile://形式のURIに変換 | 全操作 |
| BR-33-03 | 結果フィルタリング | 空結果やnull結果を除外 | 全操作 |
| BR-33-04 | コールヒエラルキー2段階 | prepareCallHierarchy後にincoming/outgoingを呼び出す | コールヒエラルキー操作 |

### 計算ロジック

**位置変換**:
- LSP送信時: `line - 1`, `character - 1`（1-basedから0-basedへ）

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| FileNotFound | 入力エラー | 指定ファイルが存在しない | エラーメッセージを返却 |
| NoLSPServer | 環境エラー | 対応するLSPサーバーがない | エラーメッセージを返却 |
| LSPError | 通信エラー | LSPリクエストが失敗 | 空配列またはnullを返却（例外をキャッチ） |

### リトライ仕様

- LSPリクエスト失敗時のリトライは行わない（catch句で空結果を返却）

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

該当なし

## パフォーマンス要件

- 各LSPリクエストは即座に応答を返すことが期待される
- ファイルタッチ時に診断待機を行うため、初回アクセスは遅延する可能性あり

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

- 外部ディレクトリへのアクセスはassertExternalDirectoryでチェック
- lsp権限の確認が必須

## 備考

対応操作一覧：
- `goToDefinition`: 定義ジャンプ
- `findReferences`: 参照検索
- `hover`: ホバー情報
- `documentSymbol`: ドキュメント内シンボル
- `workspaceSymbol`: ワークスペースシンボル検索
- `goToImplementation`: 実装検索
- `prepareCallHierarchy`: コールヒエラルキー準備
- `incomingCalls`: 着信呼び出し
- `outgoingCalls`: 発信呼び出し

---

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

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

### 推奨読解順序

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

位置情報とシンボル情報の型定義を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/opencode/src/lsp/index.ts` | Range型定義（21-35行目） |
| 1-2 | index.ts | `packages/opencode/src/lsp/index.ts` | Symbol型定義（37-49行目） |
| 1-3 | index.ts | `packages/opencode/src/lsp/index.ts` | DocumentSymbol型定義（51-62行目） |

**読解のコツ**: Range、Symbol、DocumentSymbolはLSP仕様に準拠した型。zodスキーマで定義されている。

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

LSPツールの定義とパラメータを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | lsp.ts | `packages/opencode/src/tool/lsp.ts` | operations定義（11-21行目） |
| 2-2 | lsp.ts | `packages/opencode/src/tool/lsp.ts` | LspTool定義（23-97行目） |

**主要処理フロー**:
1. **11-21行目**: 対応操作の列挙型定義
2. **25-30行目**: パラメータスキーマ定義
3. **31-33行目**: ファイルパスの絶対パス変換
4. **35-40行目**: 権限確認
5. **44-47行目**: 位置情報の0-based変換
6. **63-84行目**: 操作別のLSP関数呼び出し

#### Step 3: 各ナビゲーション関数

LSPモジュールのナビゲーション関数群。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/opencode/src/lsp/index.ts` | hover関数（303-317行目） |
| 3-2 | index.ts | `packages/opencode/src/lsp/index.ts` | definition関数（386-395行目） |
| 3-3 | index.ts | `packages/opencode/src/lsp/index.ts` | references関数（397-407行目） |
| 3-4 | index.ts | `packages/opencode/src/lsp/index.ts` | implementation関数（409-418行目） |

**主要処理フロー**:
- **303-317行目**: hover - textDocument/hoverリクエスト
- **386-395行目**: definition - textDocument/definitionリクエスト
- **397-407行目**: references - textDocument/referencesリクエスト（includeDeclaration: true）
- **409-418行目**: implementation - textDocument/implementationリクエスト

#### Step 4: コールヒエラルキー処理

2段階のコールヒエラルキー取得。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.ts | `packages/opencode/src/lsp/index.ts` | prepareCallHierarchy関数（420-429行目） |
| 4-2 | index.ts | `packages/opencode/src/lsp/index.ts` | incomingCalls関数（431-442行目） |
| 4-3 | index.ts | `packages/opencode/src/lsp/index.ts` | outgoingCalls関数（444-455行目） |

**主要処理フロー**:
- **420-429行目**: prepareCallHierarchy - コールヒエラルキーの起点を取得
- **431-442行目**: incomingCalls - prepareを呼び出し、その結果でcallHierarchy/incomingCallsを呼び出す
- **444-455行目**: outgoingCalls - prepareを呼び出し、その結果でcallHierarchy/outgoingCallsを呼び出す

#### Step 5: 内部ヘルパー関数

複数クライアントへの並列リクエスト。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | index.ts | `packages/opencode/src/lsp/index.ts` | run関数（463-467行目） |
| 5-2 | index.ts | `packages/opencode/src/lsp/index.ts` | runAll関数（457-461行目） |

**主要処理フロー**:
- **457-461行目**: runAll - 全クライアントで並列実行
- **463-467行目**: run - 特定ファイル対応クライアントで並列実行

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

```
LspTool.execute(args, ctx)
    │
    ├─ path.isAbsolute / path.join - ファイルパス解決
    │
    ├─ assertExternalDirectory - 外部ディレクトリチェック
    │
    ├─ ctx.ask({permission: "lsp"}) - 権限確認
    │
    ├─ Filesystem.exists(file) - ファイル存在確認
    │
    ├─ LSP.hasClients(file) - クライアント存在確認
    │
    ├─ LSP.touchFile(file, true) - ファイルタッチ
    │
    └─ [操作別分岐]
           │
           ├─ LSP.definition(position)
           │      └─ run(file, client => connection.sendRequest("textDocument/definition"))
           │
           ├─ LSP.references(position)
           │      └─ run(file, client => connection.sendRequest("textDocument/references"))
           │
           ├─ LSP.hover(position)
           │      └─ run(file, client => connection.sendRequest("textDocument/hover"))
           │
           ├─ LSP.implementation(position)
           │      └─ run(file, client => connection.sendRequest("textDocument/implementation"))
           │
           └─ LSP.incomingCalls(position) / LSP.outgoingCalls(position)
                  └─ run(file, async client => {
                         items = await connection.sendRequest("textDocument/prepareCallHierarchy")
                         return connection.sendRequest("callHierarchy/incomingCalls", {item: items[0]})
                     })
```

### データフロー図

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

operation ───────────▶ 操作種別判定 ────────────▶ LSPメソッド選択
filePath ────────────▶ 絶対パス変換 ────────────▶ file://URI変換
line (1-based) ──────▶ 0-based変換 ─────────────▶ LSP position
character (1-based) ──▶ 0-based変換 ─────────────▶ LSP position
                            │
                            ▼
                    LSPリクエスト送信
                            │
                            ▼
                    LSPサーバー処理
                            │
                            ▼
                    Location[] / HoverResult ───▶ JSON文字列
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lsp.ts | `packages/opencode/src/tool/lsp.ts` | ソース | LSPツール定義、エージェントからのインターフェース |
| index.ts | `packages/opencode/src/lsp/index.ts` | ソース | ナビゲーション関数群（definition, references, hover等） |
| client.ts | `packages/opencode/src/lsp/client.ts` | ソース | LSP接続管理、リクエスト送信 |
| lsp.txt | `packages/opencode/src/tool/lsp.txt` | テキスト | ツール説明文（DESCRIPTION） |
