# 機能設計書 59-着信呼び出し

## 概要

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

### 本機能の処理概要

**業務上の目的・背景**：
開発者が関数の使用状況を把握する際、「この関数はどこから呼び出されているか」を知ることは重要である。Incoming Calls機能は、指定した関数を呼び出している全ての箇所を階層的に探索し、呼び出し元の関数情報と共に返却する。これにより、関数の変更が影響する範囲を正確に把握できる。

**機能の利用シーン**：
1. 関数のリファクタリング前に影響範囲を確認
2. 関数の使用状況を調査
3. コードの依存関係を理解
4. バグの影響範囲を特定

**主要な処理内容**：
1. 指定位置の関数への参照を全て検索
2. 各参照が含まれる親関数（呼び出し元）を特定
3. 参照と親関数のペアをCallHierarchyIncomingCall形式に変換
4. 結果を配列として返却

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

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

## 関連画面

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

## 機能種別

検索処理 / 情報取得処理

## 入力仕様

### 入力パラメータ

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

### 入力データソース

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

## 出力仕様

### 出力データ

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

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ callHierarchy/incomingCallsを受信
2. 参照検索
   └─ find-references-from-cursorで全参照を取得
3. URI別ZLoc取得
   └─ 各参照のURIに対してZLocを取得
4. 親関数特定
   └─ parent-var-defで各参照を含む関数定義を特定
5. IncomingCall生成
   └─ element-by-uri->call-hierarchy-itemで変換
6. レスポンス返却
```

### フローチャート

```mermaid
flowchart TD
    A[incomingCalls受信] --> B[range.startから位置取得]
    B --> C[find-references-from-cursor]
    C --> D[参照URIリストを取得]
    D --> E[各URIのZLocを取得]
    E --> F[各参照を処理]
    F --> G[parent-var-defで親関数特定]
    G --> H{親関数あり?}
    H -->|No| F
    H -->|Yes| I[element->incoming-usage-by-uri]
    I --> J[element-by-uri->call-hierarchy-item]
    J --> K[CallHierarchyIncomingCall生成]
    K --> F
    F --> L[結果配列を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-59-01 | 親関数限定 | var-definitionsまたはdefmethodのみを親関数として認識 | 常時 |
| BR-59-02 | 親なし除外 | 親関数が特定できない参照は結果から除外 | 常時 |
| BR-59-03 | fromRanges空 | fromRangesは現在常に空配列 | 常時 |
| BR-59-04 | 定義除外 | 定義自体は参照に含めない（false引数） | 常時 |

### 計算ロジック

**親関数の特定**:
```clojure
(defn parent-var-def [root-zloc db uri row col]
  ;; ZLocを使用してvar定義名の位置に移動
  ;; その位置の要素を取得
  ;; var-definitionsまたはdefmethodの場合のみ返却
  )
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 参照検索 | db.analysis | SELECT | 対象シンボルへの参照を検索 |
| 定義検索 | db.analysis | SELECT | 親関数の定義を検索 |

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

#### db.analysis

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | var-usages | 参照対象 = 指定シンボル | 参照元を検索 |
| SELECT | var-definitions | uri, row, col | 親関数の特定 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 参照なし | 参照が見つからない | 空配列返却 |
| - | パース失敗 | ファイルの構文エラー | その参照をスキップ |

### リトライ仕様

リトライは行わない。

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

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

## パフォーマンス要件

- 参照数に依存するが、通常数百ミリ秒以内

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

- 特になし

## 備考

- 複数のファイルをまたがって検索するため、各ファイルのZLocを取得する処理がある

---

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

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

### 推奨読解順序

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

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

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

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | **410-414行目**: incomingCallsハンドラ |
| 2-2 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | **486-491行目**: call-hierarchy-incoming関数 |

**主要処理フロー**:
1. **410-414行目**: `callHierarchy/incomingCalls`リクエストを受信
2. **489行目**: `f.call-hierarchy/incoming`を呼び出し

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

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

**主要処理フロー**:
- **70行目**: `q/find-references-from-cursor`で参照を検索
- **71行目**: 参照のURIリストを取得
- **72-73行目**: 各URIのZLocを取得してzipmap
- **76-77行目**: 各参照について`element->incoming-usage-by-uri`を呼び出し
- **78-80行目**: 結果をCallHierarchyIncomingCallに変換

#### Step 4: 親関数特定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | call_hierarchy.clj | `lib/src/clojure_lsp/feature/call_hierarchy.clj` | **39-52行目**: `parent-var-def`関数 |
| 4-2 | call_hierarchy.clj | `lib/src/clojure_lsp/feature/call_hierarchy.clj` | **54-59行目**: `element->incoming-usage-by-uri`関数 |

**主要処理フロー**:
- **43-47行目**: ZLocを使用してvar定義名の位置に移動
- **48-52行目**: var-definitionsまたはdefmethodの場合のみ返却
- **54-59行目**: 親関数情報と参照情報をマップにまとめる

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

```
callHierarchy/incomingCalls (server.clj:410-414)
    │
    ├─ handler/call-hierarchy-incoming (handlers.clj:486-491)
    │      │
    │      └─ f.call-hierarchy/incoming (call_hierarchy.clj:68-80)
    │             │
    │             ├─ q/find-references-from-cursor
    │             │
    │             ├─ safe-zloc-of-forced-uri (call_hierarchy.clj:13-15)
    │             │      └─ f.file-management/force-get-document-text
    │             │
    │             ├─ element->incoming-usage-by-uri (call_hierarchy.clj:54-59)
    │             │      │
    │             │      └─ parent-var-def (call_hierarchy.clj:39-52)
    │             │             ├─ parser/to-pos
    │             │             ├─ edit/find-var-definition-name-loc
    │             │             └─ q/find-element-under-cursor
    │             │
    │             └─ element-by-uri->call-hierarchy-item (call_hierarchy.clj:17-30)
    │
    └─ conform-or-log
```

### データフロー図

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

incomingCalls              ┌──────────────────────────────────┐
Request                    │                                  │
  └─ item                  │  incoming                        │
       ├─ uri ────────────►│                                  │
       └─ range ──────────►│    ├─ find-references-from-cursor│
                           │    │                             │
db.analysis                │    │    参照リスト               │
  └─ var-usages ──────────►│    │        │                    │
                           │    │        ▼                    │
                           │    ├─ 各URIのZLoc取得           │
各ファイルテキスト ────────►│    │                             │
                           │    │        │                    │
                           │    │        ▼                    │
                           │    ├─ parent-var-def             │
                           │    │    各参照の親関数特定       │         IncomingCall[]
                           │    │        │                    │────────►  ├─ from
                           │    │        ▼                    │           │    ├─ name
                           │    └─ element-by-uri->...        │           │    ├─ 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` | ソース | コールヒエラルキーの実装 |
| edit.clj | `lib/src/clojure_lsp/refactor/edit.clj` | ソース | find-var-definition-name-loc |
| call_hierarchy_test.clj | `lib/test/clojure_lsp/feature/call_hierarchy_test.clj` | テスト | コールヒエラルキーのテスト |
