# 機能設計書 45-未使用パブリック変数検出

## 概要

本ドキュメントは、clojure-lspの「未使用パブリック変数検出」機能の設計を詳細に記載する。この機能は、プロジェクト全体で使用されていないパブリック変数（関数、def、キーワード定義等）を検出し、診断として表示する独自リンター機能である。

### 本機能の処理概要

**業務上の目的・背景**：大規模なClojureプロジェクトでは、リファクタリングやコード削除の過程で未使用のパブリック関数や変数が残留することがある。これらのデッドコードはプロジェクトの可読性を低下させ、メンテナンスコストを増加させる。この機能により、プロジェクト全体を横断して未使用のパブリックシンボルを検出し、クリーンなコードベースの維持を支援する。

**機能の利用シーン**：ファイル保存時やプロジェクト読み込み時に自動実行され、未使用のパブリック変数に対して情報レベル（デフォルト）の診断を表示する。開発者は診断パネルで確認し、不要な関数の削除やプライベート化を検討できる。

**主要な処理内容**：
1. プロジェクト内の全パブリック変数定義を収集
2. 全名前空間の使用状況（var-usages, symbols）を解析
3. 使用されていない定義を特定
4. 除外条件（メタデータ、正規表現等）をチェック
5. 診断として出力

**関連システム・外部連携**：clj-kondoの解析結果（analysis）を使用。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | エディタ | 主画面 | 診断結果の表示（波線、問題パネル等） |

## 機能種別

静的解析 / 診断 / カスタムリンター

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uris | Array[String] | Yes | 解析対象ファイルURIの配列 | 有効なファイルURI |

### 入力データソース

- clj-kondo解析結果（:analysis）
- 設定（:linters :clojure-lsp/unused-public-var）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| diagnostics | Array | LSP診断オブジェクトの配列 |
| diagnostics[].range | Range | 問題箇所の範囲 |
| diagnostics[].severity | Number | 重大度（デフォルト: 3=Information） |
| diagnostics[].code | String | "clojure-lsp/unused-public-var" |
| diagnostics[].source | String | "clojure-lsp" |
| diagnostics[].message | String | "Unused public var 'ns/name'" |
| diagnostics[].tags | Array | [1]（Unnecessary） |

### 出力先

- LSP textDocument/publishDiagnostics 通知

## 処理フロー

### 処理シーケンス

```
1. 対象URIの全パブリック変数定義を取得
   └─ q/find-all-var-definitions (include-private? = false)
2. 除外条件でフィルタ
   └─ exclude-public-diagnostic-definition? でチェック
   └─ メタデータ、正規表現、定義元、comment内等
3. テストファイル参照の考慮（オプション）
   └─ ignore-test-references? 設定
4. プロジェクト全体の使用状況を取得
   └─ nses-and-dependents-analysis
5. 未使用変数を特定
   └─ orphans 関数で使用されていない定義を抽出
6. キーワード定義も同様に処理
7. 診断に変換
   └─ element->diagnostic
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{レベル:off?}
    B -->|はい| Z[空配列返却]
    B -->|いいえ| C[パブリック変数収集]
    C --> D[除外条件フィルタ]
    D --> E{ignore-test-references?}
    E -->|はい| F[テスト参照を分離]
    E -->|いいえ| G[全参照で判定]
    F --> H[orphans計算]
    G --> H
    H --> I[キーワード定義処理]
    I --> J[診断変換]
    J --> K[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | メタデータ除外 | :arglists, :style/indent, カスタム指定メタを持つ変数は除外 | 常時 |
| BR-02 | 正規表現除外 | :exclude-regex にマッチする完全修飾名は除外 | 設定時 |
| BR-03 | 定義元除外 | :exclude-when-defined-by-regex にマッチする定義元は除外 | 設定時 |
| BR-04 | comment除外 | (comment ...) 内の定義は除外 | 常時 |
| BR-05 | export除外 | :export メタデータを持つ変数は除外 | 常時 |
| BR-06 | gen-class考慮 | 名前空間が:gen-classを持ち、名前が"-"で始まる変数は除外 | 常時 |
| BR-07 | テスト分離 | ignore-test-references?でテストからの参照を無視可能 | 設定時 |

### 計算ロジック

```clojure
;; 使用判定の疑似コード
(defn orphans [var-definitions nses-and-dependents]
  (let [usages (collect-all-usages nses-and-dependents)
        var-used? (fn [var-def]
                    (some usages (var-definition-signatures var-def)))]
    (remove var-used? var-definitions)))
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 診断格納 | :diagnostics :built-in | UPDATE | URI毎の診断配列を格納 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | N/A | 例外発生時 | エラーログ出力、空の結果返却 |

### リトライ仕様

リトライなし

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

アトム操作による排他制御（swap!）。

## パフォーマンス要件

- プロジェクト全体解析: 数秒以内（プロジェクトサイズ依存）
- 正規表現マッチングのメモ化による高速化

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

特になし

## 備考

- clj-kondoの:clojure-lsp/unused-public-var設定と連携
- EDNファイルからの参照もチェック対象

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | built_in.clj | `lib/src/clojure_lsp/feature/diagnostics/built_in.clj` | orphans関数の入出力を理解 |

**読解のコツ**: var-definition-signaturesがどのようにマッチングに使われるかを把握する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | built_in.clj | `lib/src/clojure_lsp/feature/diagnostics/built_in.clj` | analyze-uris!, analyze-paths! |

**主要処理フロー**:
- **314-340行目**: `analyze-uris!` - メイン処理
- **342-343行目**: `analyze-uri!` - 単一ファイル解析

#### Step 3: 未使用変数検出ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | built_in.clj | `lib/src/clojure_lsp/feature/diagnostics/built_in.clj` | unused-public-vars, orphans, exclude-public-diagnostic-definition? |

**主要処理フロー**:
- **179-241行目**: `unused-public-vars` - メインロジック
- **162-177行目**: `orphans` - 未使用判定
- **137-160行目**: `exclude-public-diagnostic-definition?` - 除外条件チェック
- **127-135行目**: `setting-for-ns` - 名前空間別設定適用

#### Step 4: 診断変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | built_in.clj | `lib/src/clojure_lsp/feature/diagnostics/built_in.clj` | element->diagnostic |

**主要処理フロー**:
- **69-80行目**: `element->diagnostic` - LSP形式への変換

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

```
startup/initialize-project
    │
    └─ built-in/analyze-paths!
           │
           └─ analyze-uris!
                  │
                  ├─ find-ignore-comments (並列)
                  ├─ unused-public-vars (並列)
                  │      │
                  │      ├─ q/find-all-var-definitions
                  │      ├─ exclude-public-diagnostic-definition?
                  │      │      ├─ q/exclude-public-definition?
                  │      │      └─ inside-comment?
                  │      ├─ orphans
                  │      │      └─ q/xf-all-var-usages-and-symbols
                  │      └─ q/find-all-keyword-definitions
                  │
                  ├─ different-aliases (並列)
                  └─ cyclic-dependencies (並列)

f.diagnostic/find-diagnostics
    │
    └─ built-in-diagnostics (取得のみ)
```

### データフロー図

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

URIs ─────────────▶ find-all-var-definitions
                           │
                           ▼
                  exclude-public-diagnostic-definition?
                           │
                           ▼
                    var-definitions (filtered)
                           │
                           ▼
          nses-and-dependents-analysis ───▶ usages
                           │
                           ▼
                       orphans
                           │
                           ▼
                    unused-vars
                           │
                           ▼
                element->diagnostic
                           │
                           ▼
                  LSP Diagnostics ───▶ :diagnostics :built-in
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| built_in.clj | `lib/src/clojure_lsp/feature/diagnostics/built_in.clj` | ソース | 未使用変数検出のメインロジック |
| diagnostics.clj | `lib/src/clojure_lsp/feature/diagnostics.clj` | ソース | 診断統合と発行 |
| queries.clj | `lib/src/clojure_lsp/queries.clj` | ソース | 解析データのクエリ |
| settings.clj | `lib/src/clojure_lsp/settings.clj` | ソース | 設定管理 |
| kondo.clj | `lib/src/clojure_lsp/kondo.clj` | ソース | var-definition-metasの設定 |
