# 機能設計書 60-発信呼び出し

## 概要

本ドキュメントは、clojure-lspにおける発信呼び出し（Outgoing Calls）機能の設計を記述する。この機能はLSPプロトコルの`callHierarchy/outgoingCalls`リクエストを実装し、指定した関数が呼び出している関数の一覧を返却する。

### 本機能の処理概要

**業務上の目的・背景**：
開発者が関数の依存関係を把握する際、「この関数は何を呼び出しているか」を知ることは重要である。Outgoing Calls機能は、指定した関数の本体内で呼び出されている全ての関数を探索し、その定義情報と共に返却する。これにより、関数の依存関係を階層的に探索できる。

**機能の利用シーン**：
1. 関数の依存関係を調査
2. 関数が使用している他の関数を確認
3. 依存関係の深掘り
4. コードのモジュール性評価

**主要な処理内容**：
1. 指定位置の関数定義を特定
2. 関数本体内のvar-usagesを全て取得
3. 各var-usageの定義を検索
4. 結果をCallHierarchyOutgoingCall形式に変換

**関連システム・外部連携**：
- clj-kondo：var-usages情報と定義情報の提供
- rewrite-clj：関数本体の範囲特定
- LSPクライアント（エディタ）：コールヒエラルキーUIの表示

**権限による制御**：
特に権限による制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | エディタ | 主画面 | 発信呼び出しの表示 |

## 機能種別

検索処理 / 情報取得処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| item.uri | string | Yes | 対象シンボルのファイルURI | 有効なファイルURI形式 |
| item.range | Range | Yes | 対象シンボルの範囲 | 有効なRange |

### 入力データソース

- LSPクライアントからの`callHierarchy/outgoingCalls`リクエスト
- 解析データ（db.analysis）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| to | CallHierarchyItem | 呼び出し先の関数情報 |
| fromRanges | array<Range> | 呼び出し元内での呼び出し位置（現在は空配列） |

### 出力先

LSPクライアントへのレスポンス（CallHierarchyOutgoingCall配列）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ callHierarchy/outgoingCallsを受信
2. ZLoc取得
   └─ 対象URIのZLocを取得
3. 親関数特定
   └─ parent-var-defで指定位置の関数定義を特定
4. var-usages検索
   └─ find-var-usages-under-formで関数本体内の呼び出しを検索
5. 定義解決
   └─ 各var-usageのfind-definitionで定義を検索
6. OutgoingCall生成
   └─ element-by-uri->call-hierarchy-itemで変換
7. レスポンス返却
```

### フローチャート

```mermaid
flowchart TD
    A[outgoingCalls受信] --> B[ZLoc取得]
    B --> C[parent-var-defで関数定義特定]
    C --> D{関数定義あり?}
    D -->|No| E[nil返却]
    D -->|Yes| F[関数範囲取得]
    F --> G[find-var-usages-under-form]
    G --> H[各var-usageを処理]
    H --> I[element->outgoing-usage-by-uri]
    I --> J[find-definition]
    J --> K{定義あり?}
    K -->|No| H
    K -->|Yes| L[element-by-uri->call-hierarchy-item]
    L --> M[CallHierarchyOutgoingCall生成]
    M --> H
    H --> N[結果配列を返却]
    E --> O[終了]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-60-01 | 関数範囲 | name-row/name-col から end-row/end-col の範囲を検索対象 | 常時 |
| BR-60-02 | var-usages限定 | var-usagesのみを呼び出しとして認識 | 常時 |
| BR-60-03 | 定義必須 | 定義が見つからないvar-usageは結果から除外 | 常時 |
| BR-60-04 | fromRanges空 | fromRangesは現在常に空配列 | 常時 |

### 計算ロジック

**関数範囲の計算**:
```clojure
{:row (:name-row definition)
 :col (:name-col definition)
 :end-row (:end-row definition)
 :end-col (:end-col definition)}
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 定義検索 | db.analysis | SELECT | 対象関数の定義を取得 |
| var-usages検索 | db.analysis | SELECT | 関数内のvar-usagesを検索 |
| 呼び出し先定義検索 | db.analysis | SELECT | 各var-usageの定義を検索 |

### テーブル別操作詳細

#### db.analysis

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | var-definitions | uri, row, col | 対象関数の定義 |
| SELECT | var-usages | 範囲内 | 関数内の呼び出し |
| SELECT | var-definitions | 各var-usageの参照先 | 呼び出し先の定義 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 関数定義未検出 | 指定位置が関数定義内でない | nil返却 |
| - | 定義なしvar-usage | 定義が見つからない | その呼び出しをスキップ |

### リトライ仕様

リトライは行わない。

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

読み取り専用のため、トランザクション管理は不要。

## パフォーマンス要件

- 関数内のvar-usage数に依存するが、通常数百ミリ秒以内

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

- 特になし

## 備考

- 関数定義のend-row/end-colを使用して関数本体全体を検索範囲とする

---

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

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

### 推奨読解順序

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

CallHierarchyOutgoingCallのデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | call_hierarchy.clj | `lib/src/clojure_lsp/feature/call_hierarchy.clj` | **93-95行目**: OutgoingCall構造 |

**読解のコツ**: OutgoingCallは`{:from-ranges [], :to CallHierarchyItem}`形式。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | **416-420行目**: outgoingCallsハンドラ |
| 2-2 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | **493-498行目**: call-hierarchy-outgoing関数 |

**主要処理フロー**:
1. **416-420行目**: `callHierarchy/outgoingCalls`リクエストを受信
2. **496行目**: `f.call-hierarchy/outgoing`を呼び出し

#### Step 3: 発信呼び出し検索を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | call_hierarchy.clj | `lib/src/clojure_lsp/feature/call_hierarchy.clj` | **82-95行目**: `outgoing`関数 |

**主要処理フロー**:
- **83行目**: `safe-zloc-of-forced-uri`でZLocを取得
- **85行目**: `parent-var-def`で関数定義を特定
- **86-91行目**: `find-var-usages-under-form`で関数内のvar-usagesを取得
- **92行目**: 各var-usageについて`element->outgoing-usage-by-uri`を呼び出し
- **93-95行目**: 結果をCallHierarchyOutgoingCallに変換

#### Step 4: var-usages検索と定義解決を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | call_hierarchy.clj | `lib/src/clojure_lsp/feature/call_hierarchy.clj` | **61-66行目**: `element->outgoing-usage-by-uri`関数 |
| 4-2 | queries.clj | `lib/src/clojure_lsp/queries.clj` | `find-var-usages-under-form`関数 |

**主要処理フロー**:
- **62-63行目**: `q/find-definition`で呼び出し先の定義を検索
- **64-66行目**: 定義があれば参照情報と定義情報をマップにまとめる

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

```
callHierarchy/outgoingCalls (server.clj:416-420)
    │
    ├─ handler/call-hierarchy-outgoing (handlers.clj:493-498)
    │      │
    │      └─ f.call-hierarchy/outgoing (call_hierarchy.clj:82-95)
    │             │
    │             ├─ safe-zloc-of-forced-uri (call_hierarchy.clj:13-15)
    │             │
    │             ├─ parent-var-def (call_hierarchy.clj:39-52)
    │             │
    │             ├─ q/find-var-usages-under-form
    │             │
    │             ├─ element->outgoing-usage-by-uri (call_hierarchy.clj:61-66)
    │             │      │
    │             │      └─ q/find-definition
    │             │
    │             └─ element-by-uri->call-hierarchy-item (call_hierarchy.clj:17-30)
    │
    └─ conform-or-log
```

### データフロー図

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

outgoingCalls              ┌──────────────────────────────────┐
Request                    │                                  │
  └─ item                  │  outgoing                        │
       ├─ uri ────────────►│                                  │
       └─ range ──────────►│    ├─ ZLoc取得                  │
                           │    │                             │
ファイルテキスト ──────────►│    ├─ parent-var-def            │
                           │    │    関数定義特定              │
                           │    │        │                    │
db.analysis                │    │        ▼                    │
  ├─ var-definitions ─────►│    ├─ 関数範囲取得              │
  │                        │    │    {row, col,               │
  │                        │    │     end-row, end-col}       │
  │                        │    │        │                    │
  │                        │    │        ▼                    │
  └─ var-usages ──────────►│    ├─ find-var-usages-under-form│
                           │    │    関数内のvar-usages       │
                           │    │        │                    │         OutgoingCall[]
                           │    │        ▼                    │────────►  ├─ to
                           │    └─ element->outgoing-...     │           │    ├─ name
                           │         各var-usageの定義検索   │           │    ├─ kind
                           │                                  │           │    └─ ...
                           │                                  │           └─ fromRanges []
                           └──────────────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSPサーバーハンドラ定義 |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | 各機能のハンドラ実装 |
| call_hierarchy.clj | `lib/src/clojure_lsp/feature/call_hierarchy.clj` | ソース | コールヒエラルキーの実装 |
| queries.clj | `lib/src/clojure_lsp/queries.clj` | ソース | find-var-usages-under-form等 |
| call_hierarchy_test.clj | `lib/test/clojure_lsp/feature/call_hierarchy_test.clj` | テスト | コールヒエラルキーのテスト |
