# 通知設計書 12-clojure/cursorInfo/log

## 概要

本ドキュメントは、clojure-lspにおける`clojure/cursorInfo/log`通知の設計仕様を記載したものです。この通知はクライアントからサーバーへ送信される通知であり、カーソル位置にある要素のデバッグ情報をログとして出力することを要求します。

### 本通知の処理概要

`clojure/cursorInfo/log`通知は、エディタ上のカーソル位置にあるClojureコード要素の詳細情報をデバッグ目的でログ出力するための機能です。開発者がコード解析の結果や要素の定義情報を確認し、LSPの動作を診断するために使用されます。

**業務上の目的・背景**：この通知はclojure-lsp独自の拡張機能であり、コード解析結果の詳細を確認する必要がある場合に使用されます。例えば、定義ジャンプが期待通りに動作しない場合や、セマンティックトークンの分類を確認したい場合など、LSPの内部動作を理解するために役立ちます。

**通知の送信タイミング**：クライアント（エディタ）からユーザーの明示的なアクション（コマンド実行など）によって送信されます。通常、カーソルを特定の位置に置いた状態で「Cursor Info Log」などのコマンドを実行した際にトリガーされます。

**通知の受信者**：clojure-lspサーバーがこの通知を受信します。サーバーは受信後、カーソル位置の要素情報を`window/showMessage`通知を使用してクライアントに返送します。

**通知内容の概要**：通知にはテキストドキュメントのURIとカーソル位置（行・列）が含まれます。サーバーはこの情報を基に、該当位置にあるノード情報、要素情報（変数定義、変数使用など）、定義情報、セマンティックトークンタイプなどを収集します。

**期待されるアクション**：ユーザーは表示されたカーソル位置の情報を確認し、コード解析の動作確認やサポートへの情報提供に利用することが期待されます。

## 通知種別

LSP通知（クライアント→サーバー）+ ユーザーへのメッセージ表示（サーバー→クライアント）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（future） |
| 優先度 | 低 |
| リトライ | なし |

### 送信先決定ロジック

クライアントからサーバーへの一方向通知のため、送信先はclojure-lspサーバーに固定されます。サーバーからの応答は`window/showMessage`通知を通じてクライアントへ返送されます。

## 通知テンプレート

### LSP通知の場合

| 項目 | 内容 |
|-----|------|
| メソッド名 | `clojure/cursorInfo/log` |
| パラメータ | TextDocumentPositionParams |
| レスポンス | なし（通知のため） |

### 本文テンプレート

カーソル情報はpretty-print形式でフォーマットされ、`window/showMessage`経由で表示されます。

```clojure
{:node {:tag :token
        :string "my-function"
        :value my-function}
 :elements [{:element {:name my-function
                       :ns user
                       :bucket :var-usages
                       :row 10
                       :col 5
                       ...}
             :definition {:name my-function
                          :ns user
                          :bucket :var-definitions
                          :row 3
                          :col 1
                          ...}
             :semantic-tokens :function}]}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| text-document.uri | ドキュメントURI | クライアントパラメータ | Yes |
| position.line | カーソル行（0-indexed） | クライアントパラメータ | Yes |
| position.character | カーソル列（0-indexed） | クライアントパラメータ | Yes |
| node | カーソル位置のASTノード | parser/to-pos | No |
| elements | カーソル位置の全要素 | q/find-all-elements-under-cursor | No |
| definition | 各要素の定義情報 | q/find-definition | No |
| semantic-tokens | セマンティックトークンタイプ | f.semantic-tokens/element->token-type | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ユーザーコマンド | clojure/cursorInfo/logコマンド実行 | テキストドキュメントが開いていること | ユーザーがエディタからコマンドを実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | この通知に抑止条件はありません |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[クライアントからclojure/cursorInfo/log通知受信] --> B[URIを正規化]
    B --> C[future内で処理開始]
    C --> D[handler/cursor-info-log呼び出し]
    D --> E[f.development-info/cursor-info-log呼び出し]
    E --> F[cursor-info関数でカーソル情報収集]
    F --> G[pprint形式でフォーマット]
    G --> H[producer/show-message呼び出し]
    H --> I[window/showMessage通知をクライアントへ送信]
    I --> J[終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| db（アトム） | コード解析結果の参照 | インメモリ状態管理 |

### テーブル別参照項目詳細

#### db（アトム）

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| :analysis | コード解析結果 | URI指定で該当ファイルの解析結果を取得 |
| :documents | ドキュメントテキスト | パース用 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | この通知では状態更新は行いません |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 例外発生 | カーソル情報収集中にエラー | logger/errorでログ出力後、例外を再スロー |
| パース失敗 | ドキュメントのパース失敗 | nilが返却される |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0回 |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし

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

カーソル情報にはコードの内部構造が含まれますが、ユーザーが明示的に要求した情報のみが表示されるため、特別なセキュリティ考慮は不要です。

## 備考

- この機能はclojure-lsp独自の拡張であり、標準LSP仕様には含まれません
- 位置情報はLSP仕様（0-indexed）からclojure-lsp内部（1-indexed）に変換されます
- ノードに子要素がある場合、`:children`は省略され`:children-count`として数のみ表示されます

---

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

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

### 推奨読解順序

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

カーソル情報として収集されるデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | development_info.clj | `lib/src/clojure_lsp/feature/development_info.clj` | cursor-info関数（41-56行目）でカーソル情報のマップ構造を確認 |

**読解のコツ**: `:node`と`:elements`の2つの主要キーがあり、`:elements`は各要素の`:element`、`:definition`、`:semantic-tokens`を含む配列です。

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

通知受信からハンドラー呼び出しまでの流れを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | receive-notification "clojure/cursorInfo/log"（230-236行目）でエントリーポイントを確認 |

**主要処理フロー**:
1. **230行目**: defmethod jsonrpc.server/receive-notificationでメソッド定義
2. **231行目**: future内で非同期処理開始
3. **233行目**: handler/cursor-info-log呼び出し、normalize-doc-uriでURI正規化

#### Step 3: ハンドラー層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | cursor-info-log関数（357-360行目）でハンドラー実装を確認 |

**主要処理フロー**:
- **358行目**: shared/logging-taskでタスクロギング
- **360行目**: f.development-info/cursor-info-log呼び出し、positionから行・列を抽出して1-indexedに変換

#### Step 4: 機能実装層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | development_info.clj | `lib/src/clojure_lsp/feature/development_info.clj` | cursor-info-log関数（58-65行目）で実際のメッセージ送信を確認 |
| 4-2 | development_info.clj | `lib/src/clojure_lsp/feature/development_info.clj` | cursor-info関数（41-56行目）で情報収集ロジックを確認 |

**主要処理フロー**:
- **58-59行目**: cursor-info関数を呼び出して情報収集
- **60-64行目**: producer/show-message呼び出しでpprint形式のカーソル情報を送信
- **42行目**: q/find-all-elements-under-cursorで該当位置の全要素を取得
- **43-45行目**: パーサーでノード情報を取得
- **51-55行目**: 各要素に対して定義情報とセマンティックトークンタイプを付加

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

```
jsonrpc.server/receive-notification "clojure/cursorInfo/log"
    │
    ├─ normalize-doc-uri
    │
    └─ handler/cursor-info-log
           │
           └─ f.development-info/cursor-info-log
                  │
                  ├─ cursor-info (内部関数)
                  │      │
                  │      ├─ q/find-all-elements-under-cursor
                  │      ├─ parser/safe-zloc-of-file
                  │      ├─ parser/to-pos
                  │      ├─ z/node
                  │      ├─ q/find-definition
                  │      └─ f.semantic-tokens/element->token-type
                  │
                  └─ producer/show-message
                         │
                         └─ jsonrpc.server/send-notification "window/showMessage"
```

### データフロー図

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

TextDocumentPositionParams   カーソル情報収集                   メッセージ表示
    │                             │
    ├─ uri ─────────────▶ ファイル解析結果参照
    │                             │
    ├─ line ────────────▶ 位置からノード取得 ───────▶ window/showMessage通知
    │                             │                        │
    └─ character ───────▶ 位置から要素取得                  │
                                  │                        │
                                  ├─ node情報               │
                                  ├─ element情報            │
                                  ├─ definition情報         │
                                  └─ semantic-tokens ──────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSP通知のエントリーポイント |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | ハンドラー関数の定義 |
| development_info.clj | `lib/src/clojure_lsp/feature/development_info.clj` | ソース | カーソル情報収集・表示の実装 |
| producer.clj | `lib/src/clojure_lsp/producer.clj` | ソース | IProducerプロトコル定義 |
| queries.clj | `lib/src/clojure_lsp/queries.clj` | ソース | find-all-elements-under-cursor等のクエリ |
| parser.clj | `lib/src/clojure_lsp/parser.clj` | ソース | ASTパース機能 |
| semantic_tokens.clj | `lib/src/clojure_lsp/feature/semantic_tokens.clj` | ソース | セマンティックトークン分類 |
