# 機能設計書 20-LSP ツール

## 概要

本ドキュメントは、OpenCodeのLSP ツール機能の設計仕様を定義する。LSP ツールは、Language Server Protocol（LSP）を通じてコード解析機能を提供し、定義ジャンプ、参照検索、ホバー情報取得などの機能を担う。

### 本機能の処理概要

LSP ツールは、指定されたファイルの特定位置に対してLSP操作（定義へ移動、参照検索、ホバー情報等）を実行し、その結果をエージェントに返却する機能である。TypeScript、Python、Go等の複数の言語サーバーに対応する。

**業務上の目的・背景**：AIエージェントがコードベースを深く理解し、より正確な支援を提供するために、IDE相当のコードインテリジェンス機能が必要である。本ツールにより、エージェントはシンボルの定義場所、使用箇所、型情報などを取得できる。

**機能の利用シーン**：
- 関数やクラスの定義場所の特定
- シンボルの参照箇所の検索
- 変数や関数の型情報取得
- ドキュメント内のシンボル一覧取得
- 呼び出し階層の分析

**主要な処理内容**：
1. ファイルパスの正規化と検証
2. 外部ディレクトリチェック
3. LSP権限の確認
4. ファイル存在とLSPサーバー確認
5. LSP操作の実行
6. 結果の返却

**関連システム・外部連携**：
- LSPサーバー（TypeScript、Python、Go等）
- LSPClient：LSPサーバーとの通信

**権限による制御**：
- `lsp`権限が必要
- 外部ディレクトリへのアクセスは別途権限確認

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 直接的な画面関連なし |

## 機能種別

コード解析 / IDE機能

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| operation | enum | Yes | LSP操作の種類 | 有効な操作名 |
| filePath | string | Yes | 対象ファイルの絶対または相対パス | 有効なファイルパス |
| line | number | Yes | 行番号（1-based、エディタ表示と同じ） | 1以上の整数 |
| character | number | Yes | 文字位置（1-based、エディタ表示と同じ） | 1以上の整数 |

### 対応する操作（operation）

| 操作名 | 説明 |
|--------|------|
| goToDefinition | シンボルの定義場所を検索 |
| findReferences | シンボルの参照箇所を検索 |
| hover | ホバー情報（ドキュメント、型情報）を取得 |
| documentSymbol | ドキュメント内の全シンボルを取得 |
| workspaceSymbol | ワークスペース全体でシンボルを検索 |
| goToImplementation | インターフェースや抽象メソッドの実装を検索 |
| prepareCallHierarchy | 指定位置の呼び出し階層アイテムを取得 |
| incomingCalls | 指定位置の関数を呼び出している関数を検索 |
| outgoingCalls | 指定位置の関数から呼び出されている関数を検索 |

### 入力データソース

- ユーザー入力（ファイルパス、行番号、文字位置）
- 実行コンテキスト（セッションID、メッセージID等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| title | string | "{操作名} {相対パス}:{行}:{列}" |
| output | string | 操作結果のJSON文字列、または"No results found" |
| metadata.result | array | 操作結果の配列 |

### 出力先

- エージェントへのレスポンス（ツール実行結果）

## 処理フロー

### 処理シーケンス

```
1. ファイルパス正規化
   └─ 相対パスの場合、Instance.directoryを基準に絶対パスに変換

2. 外部ディレクトリチェック
   └─ プロジェクト外へのアクセス時は権限確認

3. LSP権限確認
   └─ ctx.askでlsp権限を要求

4. URIとポジション生成
   └─ file://形式のURIと0-basedポジションを生成

5. ファイル存在確認
   └─ ファイルが存在しない場合はエラー

6. LSPサーバー確認
   └─ 対象ファイルタイプに対応するLSPサーバーがあるか確認

7. ファイルタッチ
   └─ LSPサーバーにファイルを通知

8. LSP操作実行
   └─ 指定された操作を実行

9. 結果返却
   └─ JSONフォーマットで結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[ファイルパス正規化]
    B --> C{外部ディレクトリ?}
    C -->|Yes| D[外部ディレクトリ権限確認]
    C -->|No| E[LSP権限確認]
    D --> E
    E --> F[URI・ポジション生成]
    F --> G{ファイル存在?}
    G -->|No| ERROR1[エラー: File not found]
    G -->|Yes| H{LSPサーバー利用可能?}
    H -->|No| ERROR2[エラー: No LSP server available]
    H -->|Yes| I[ファイルタッチ]
    I --> J[LSP操作実行]
    J --> K{結果あり?}
    K -->|No| L[No results found返却]
    K -->|Yes| M[JSON結果返却]
    L --> OUTPUT[結果返却]
    M --> OUTPUT
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 1-basedインデックス | line/characterは1-based（エディタ表示と同じ） | 入力時 |
| BR-02 | 0-basedインデックス | LSPプロトコル内部では0-basedに変換 | LSP通信時 |
| BR-03 | 診断待機 | ファイルタッチ時に診断情報を待機 | touchFile実行時 |
| BR-04 | シンボル種別フィルタ | workspaceSymbolは特定のシンボル種別のみ返却 | workspaceSymbol操作時 |

### 計算ロジック

**ポジション変換**：
```javascript
const position = {
  file,
  line: args.line - 1,      // 1-based → 0-based
  character: args.character - 1,  // 1-based → 0-based
}
```

**workspaceSymbolのフィルタ対象**：
- Class
- Function
- Method
- Interface
- Variable
- Constant
- Struct
- Enum

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

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

本機能はLSPサーバーとの通信のみを行い、データベースへの直接的な操作は行わない。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | FileNotFoundError | ファイルが存在しない | 正しいパスを指定 |
| - | NoLSPServerError | 対象ファイルタイプに対応するLSPサーバーがない | LSPサーバーを設定 |
| - | PermissionError | lsp権限がない | 適切な権限を付与 |

### リトライ仕様

本機能はリトライ処理を行わない。LSP操作自体は内部でcatch処理されている。

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

LSPプロトコル通信のため、トランザクション管理は行わない。

## パフォーマンス要件

- LSPサーバーの起動・初期化に時間がかかる場合がある
- 初回アクセス時はLSPサーバーのスポーンが発生

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

- lsp権限による実行制御
- 外部ディレクトリへのアクセスは別途権限確認

## 備考

- LSPサーバーはファイル拡張子に基づいて自動選択される
- 設定ファイル（opencode.json）でLSPサーバーをカスタマイズ可能
- 一部のLSPサーバーは実験的機能としてフラグで制御される

---

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

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

### 推奨読解順序

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

ツールの入出力パラメータとLSP関連の型定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lsp.ts (tool) | `packages/opencode/src/tool/lsp.ts` | パラメータスキーマ（25-30行目）とoperations定数（11-21行目）を確認 |
| 1-2 | index.ts (lsp) | `packages/opencode/src/lsp/index.ts` | LSP.Range、LSP.Symbol、LSP.DocumentSymbol型を確認 |

**読解のコツ**: operationsは9種類のLSP操作を定義。line/characterは1-basedで受け取り、内部で0-basedに変換。

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

LSP ツールの本体実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | lsp.ts (tool) | `packages/opencode/src/tool/lsp.ts` | execute関数の全体フロー（31-97行目） |

**主要処理フロー**:
1. **32-33行目**: パス正規化と外部ディレクトリチェック
2. **35-40行目**: 権限確認
3. **41-46行目**: URI・ポジション生成
4. **51-54行目**: ファイル存在確認
5. **56-59行目**: LSPサーバー確認
6. **61行目**: ファイルタッチ（診断待機）
7. **63-84行目**: LSP操作の実行（switch文）
8. **86-94行目**: 結果フォーマット

#### Step 3: LSPモジュールを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts (lsp) | `packages/opencode/src/lsp/index.ts` | 各LSP操作関数（definition, references, hover等） |

**主要処理フロー**:
- **303-317行目**: hover関数
- **359-368行目**: workspaceSymbol関数
- **386-395行目**: definition関数
- **397-406行目**: references関数
- **420-429行目**: prepareCallHierarchy関数
- **431-441行目**: incomingCalls関数
- **444-454行目**: outgoingCalls関数

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

```
LspTool.execute
    │
    ├─ assertExternalDirectory (外部ディレクトリチェック)
    │
    ├─ ctx.ask (lsp権限要求)
    │
    ├─ Filesystem.exists (ファイル存在確認)
    │
    ├─ LSP.hasClients (LSPサーバー確認)
    │
    ├─ LSP.touchFile (ファイルタッチ)
    │
    └─ LSP操作関数
           ├─ LSP.definition
           ├─ LSP.references
           ├─ LSP.hover
           ├─ LSP.documentSymbol
           ├─ LSP.workspaceSymbol
           ├─ LSP.implementation
           ├─ LSP.prepareCallHierarchy
           ├─ LSP.incomingCalls
           └─ LSP.outgoingCalls
```

### データフロー図

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

operation ────────────────▶ 操作種別判定
                                │
filePath ─────────────────────▶ パス正規化
                                │
line ─────────────────────────▶│ ポジション変換
                                │ (1-based → 0-based)
character ────────────────────▶│
                                │
                                ▼
                           LSPサーバー確認
                                │
                                ▼
                           ファイルタッチ
                                │
                                ▼
                           LSP操作実行
                           (LSPClient経由)
                                │
                                ▼
                           結果返却 ─────────▶ title
                                              output
                                              metadata.result
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lsp.ts | `packages/opencode/src/tool/lsp.ts` | ソース | LSP ツール本体 |
| lsp.txt | `packages/opencode/src/tool/lsp.txt` | テンプレート | ツール説明文 |
| tool.ts | `packages/opencode/src/tool/tool.ts` | ソース | ツール基盤定義 |
| index.ts | `packages/opencode/src/lsp/index.ts` | ソース | LSPモジュール本体 |
| client.ts | `packages/opencode/src/lsp/client.ts` | ソース | LSPクライアント |
| server.ts | `packages/opencode/src/lsp/server.ts` | ソース | LSPサーバー定義 |
| external-directory.ts | `packages/opencode/src/tool/external-directory.ts` | ソース | 外部ディレクトリアクセス制御 |
| filesystem.ts | `packages/opencode/src/util/filesystem.ts` | ソース | ファイルシステムユーティリティ |
