# 機能設計書 43-マクロ解決

## 概要

本ドキュメントは、clojure-lspの「マクロ解決」機能（resolve-macro-as コマンド）の設計を詳細に記載する。この機能は、カスタムマクロを既知のClojureフォーム（defn, let, fn等）として解析するようclj-kondoに登録するコードアクション機能である。

### 本機能の処理概要

**業務上の目的・背景**：Clojureでは多くのライブラリがDSL（ドメイン固有言語）を提供するためにマクロを使用する。clj-kondoは標準的なマクロのみを認識するため、カスタムマクロ内のコードは正しく解析されず、偽陽性の警告が発生することがある。この機能により、カスタムマクロを既知のフォームとして登録し、正確な静的解析を可能にする。

**機能の利用シーン**：独自のマクロ（例：`defroute`、`with-transaction`等）を使用している箇所で、未解決シンボルなどの警告が出る場合に使用する。カーソルをマクロ呼び出しに置き、コードアクションメニューから「Resolve macro 'macro-name' as...」を選択する。

**主要な処理内容**：
1. カーソル位置からマクロシンボルを検出
2. 解決先のフォーム（defn, let, fn等）をユーザーに選択させる
3. 設定ファイルの保存先（プロジェクト or ホーム）をユーザーに選択させる
4. clj-kondoの設定ファイルに `:lint-as` 設定を追加
5. ファイルを再解析して設定を反映

**関連システム・外部連携**：clj-kondo の lint-as 設定機能と連携。

**権限による制御**：特になし。設定ファイル書き込み権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | エディタ | 主画面 | マクロ呼び出し箇所でのコードアクション実行 |

## 機能種別

設定変更 / ファイル操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | String | Yes | 対象ファイルURI | 有効なファイルURI |
| line | Number | Yes | カーソル行（0始まり） | 非負整数 |
| character | Number | Yes | カーソル列（0始まり） | 非負整数 |

### 入力データソース

- エディタからのカーソル位置情報
- ユーザー選択（解決先フォーム、保存先パス）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| no-op? | Boolean | 操作完了を示すフラグ（trueで成功） |

### 出力先

- clj-kondo設定ファイル（`.clj-kondo/config.edn` または `~/.config/clj-kondo/config.edn`）

## 処理フロー

### 処理シーケンス

```
1. カーソル位置からマクロシンボルを検出
   └─ find-full-macro-symbol-to-resolve 関数
   └─ 除外マクロリスト（clojure.core等）をチェック
2. 解決先フォームをユーザーに選択させる
   └─ producer/show-message-request で選択ダイアログ表示
   └─ 選択肢: defn, def, let, fn, for, ->, ->>, as->, deftest, def-catch-all
3. 設定ファイル保存先をユーザーに選択させる
   └─ プロジェクトローカル: .clj-kondo/config.edn
   └─ ユーザーグローバル: ~/.config/clj-kondo/config.edn
4. 設定ファイルを更新
   └─ 既存ファイルがあれば読み込んでマージ
   └─ なければ新規作成
5. ファイルを再解析
   └─ f.file-management/analyze-changes で再解析をトリガー
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{マクロシンボル検出}
    B -->|検出失敗| Z[nil返却]
    B -->|検出成功| C{除外マクロ?}
    C -->|はい| Z
    C -->|いいえ| D[解決先選択ダイアログ]
    D -->|キャンセル| Z
    D -->|選択| E[保存先選択ダイアログ]
    E -->|キャンセル| Z
    E -->|選択| F[設定ファイル更新]
    F --> G[ファイル再解析]
    G --> H[成功返却]
    H --> I[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 除外マクロ | clojure.core, clojure.test等の標準マクロは除外 | マクロ検出時 |
| BR-02 | lint-as設定 | `:lint-as {macro-sym resolved-sym}` 形式で設定 | 常時 |
| BR-03 | 設定ファイル優先順位 | プロジェクトローカル > ユーザーグローバル | clj-kondo仕様 |

### 計算ロジック

除外マクロリスト：
```clojure
{clojure.core *
 clojure.core.async *
 clojure.test [deftest is testing]
 clojure.test.check.generators [let]
 cljs.core.async *
 cljs.core.async.macros *
 cats.core [->= ->>=]
 schema.core [defschema]
 compojure.core [defroutes let-routes]}
```

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | ユーザーキャンセル | 選択ダイアログでキャンセル | 処理中断、no-op?返却 |
| N/A | ファイル書き込みエラー | 設定ファイル書き込み失敗 | エラーログ出力 |

### リトライ仕様

リトライ不要（ユーザー操作起点のため）

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

ファイル操作のみのため、トランザクション管理なし。

## パフォーマンス要件

- ユーザー選択後の応答時間: 1秒以内

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

- 設定ファイルへの任意コード注入防止（rewrite-ednによる安全な書き込み）

## 備考

- clj-kondo 2021.09.25以降で `def-catch-all` オプションが使用可能
- 設定変更後、エディタを再起動せずに反映される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | resolve_macro.clj | `lib/src/clojure_lsp/feature/resolve_macro.clj` | excluded-macros, known-full-symbol-resolve の定義を理解 |

**読解のコツ**: 除外マクロリストと解決先候補リストの構造を把握する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | command.clj | `lib/src/clojure_lsp/feature/command.clj` | run-command :resolve-macro-as メソッド |

**主要処理フロー**:
1. **125-126行目**: `:resolve-macro-as` コマンドのディスパッチ定義

#### Step 3: メイン処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | resolve_macro.clj | `lib/src/clojure_lsp/feature/resolve_macro.clj` | resolve-macro-as!, find-full-macro-symbol-to-resolve 関数 |

**主要処理フロー**:
- **35-42行目**: `find-full-macro-symbol-to-resolve` - マクロシンボル検出
- **60-70行目**: `known-full-symbol-resolve` - 解決先候補リスト
- **79-105行目**: `resolve-macro-as!` - メイン処理フロー
- **44-58行目**: `resolve-macro-as` (private) - 設定ファイル更新ロジック

#### Step 4: コードアクション表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | resolve-macro-as-action 関数 |

**主要処理フロー**:
- **351-356行目**: `resolve-macro-as-action` - コードアクションの定義
- **406行目**: `macro-sym*` - マクロシンボル検出のフューチャー
- **444-445行目**: コードアクション一覧への追加条件

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

```
handlers/code-actions
    │
    └─ f.code-actions/all
           │
           ├─ f.resolve-macro/find-full-macro-symbol-to-resolve
           │      ├─ edit/find-function-usage-name-loc
           │      └─ q/find-element-under-cursor
           │
           └─ resolve-macro-as-action

handlers/execute-command
    │
    └─ f.command/call-command
           │
           └─ run-command :resolve-macro-as
                  │
                  └─ f.resolve-macro/resolve-macro-as!
                         │
                         ├─ producer/show-message-request (2回)
                         ├─ resolve-macro-as (設定更新)
                         │      └─ borkdude.rewrite-edn/assoc-in
                         ├─ spit (ファイル書き込み)
                         └─ f.file-management/analyze-changes
```

### データフロー図

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

zloc, URI ─────────▶ find-full-macro-symbol-to-resolve ───▶ macro-sym
                           │
                           ▼
              show-message-request ───▶ resolved-full-symbol-str
                           │
                           ▼
              show-message-request ───▶ kondo-config-path
                           │
                           ▼
              resolve-macro-as ───▶ new-kondo-config (string)
                           │
                           ▼
                        spit ───▶ config.edn ファイル
                           │
                           ▼
              analyze-changes ───▶ 再解析トリガー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| resolve_macro.clj | `lib/src/clojure_lsp/feature/resolve_macro.clj` | ソース | マクロ解決のメインロジック |
| command.clj | `lib/src/clojure_lsp/feature/command.clj` | ソース | コマンドディスパッチ |
| code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | ソース | コードアクション定義 |
| kondo.clj | `lib/src/clojure_lsp/kondo.clj` | ソース | clj-kondo設定パス取得 |
| file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | ソース | ファイル再解析 |
| producer.clj | `lib/src/clojure_lsp/producer.clj` | ソース | クライアント通信 |
