# 帳票設計書 1-diagnostics

## 概要

本ドキュメントは、clojure-lspのdiagnostics（診断）機能によって出力される帳票の設計仕様を定義する。

### 本帳票の処理概要

diagnostics帳票は、プロジェクト全体のソースコードを静的解析し、警告、エラー、情報などの診断結果を出力する帳票である。clj-kondoのlint結果およびclojure-lsp独自のカスタムlinter（unused-public-var等）の結果を含む包括的な診断レポートを提供する。

**業務上の目的・背景**：Clojureプロジェクトの開発において、コード品質を維持し潜在的なバグを早期に発見することは極めて重要である。本帳票は、プロジェクト全体のコード品質を可視化し、未使用の変数、構文エラー、スタイル違反などの問題を一元的に把握することを目的とする。CI/CDパイプラインでの品質ゲートチェックや、コードレビュー前の自動検証に活用できる。

**帳票の利用シーン**：本帳票は以下の場面で利用される。(1) プルリクエスト作成前のローカル検証、(2) CI/CDパイプラインでの自動品質チェック、(3) コードベース全体の健全性監査、(4) リファクタリング前後の影響確認、(5) チーム間でのコーディング規約遵守確認。

**主要な出力内容**：
1. clj-kondoによるlint結果（構文エラー、未使用変数、非推奨API使用など）
2. clojure-lspカスタムlinter結果（unused-public-var等）
3. clj-dependによる依存関係違反検出結果
4. 各診断項目の重要度（error/warning/info）
5. 問題箇所のファイルパス、行番号、列番号

**帳票の出力タイミング**：CLIコマンド`clojure-lsp diagnostics`の実行時、またはAPI経由での`clojure-lsp.api/diagnostics`関数呼び出し時に出力される。LSPサーバーモードでは、ファイル変更時にリアルタイムで診断が更新される。

**帳票の利用者**：開発者、テックリード、CI/CDシステム、コードレビュアー

## 帳票種別

診断レポート / 一覧表

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| CLI-01 | コマンドライン | `clojure-lsp diagnostics` | コマンド実行 |
| API-01 | Clojure REPL | `(clojure-lsp.api/diagnostics opts)` | 関数呼び出し |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト / EDN / JSON |
| 用紙サイズ | N/A（コンソール出力） |
| 向き | N/A |
| ファイル名 | 標準出力（リダイレクト可能） |
| 出力方法 | 標準出力 / 標準エラー出力 |
| 文字コード | UTF-8 |

### 出力フォーマット詳細

#### テキスト形式（デフォルト）
```
<filepath>:<row>:<col>: <severity>: [<code>] <message>
```

例：
```
src/my_project/core.clj:15:3: warning: [unused-binding] unused binding x
src/my_project/api.clj:42:1: error: [unresolved-symbol] Unresolved symbol: foo
```

#### EDN形式（`--output {:format :edn}`）
```clojure
{"file:///path/to/file.clj"
 [{:range {:start {:line 14 :character 2}
           :end {:line 14 :character 5}}
   :message "unused binding x"
   :code "unused-binding"
   :severity 2
   :source "clj-kondo"}]}
```

#### JSON形式（`--output {:format :json}`）
```json
{
  "file:///path/to/file.clj": [
    {
      "range": {"start": {"line": 14, "character": 2}, "end": {"line": 14, "character": 5}},
      "message": "unused binding x",
      "code": "unused-binding",
      "severity": 2,
      "source": "clj-kondo"
    }
  ]
}
```

## 帳票レイアウト

### レイアウト概要

テキスト出力の場合、1行1診断の形式で出力される。

```
┌─────────────────────────────────────────────────────────────────┐
│  ファイルパス:行:列: 重要度: [コード] メッセージ                    │
│  ファイルパス:行:列: 重要度: [コード] メッセージ                    │
│  ...                                                            │
└─────────────────────────────────────────────────────────────────┘
```

### 出力項目

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ファイルパス | 診断対象ファイル | URI変換 | 相対パス/絶対パス |
| 2 | 行番号 | 問題箇所の行 | finding.row | 1始まり整数 |
| 3 | 列番号 | 問題箇所の列 | finding.col | 1始まり整数 |
| 4 | 重要度 | error/warning/info | finding.level | 文字列 |
| 5 | コード | 診断ルールコード | finding.type | 文字列 |
| 6 | メッセージ | 診断内容説明 | finding.message | 文字列 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| project-root | プロジェクトルートディレクトリ | No（デフォルト: カレントディレクトリ） |
| namespace | 対象名前空間（複数指定可） | No（デフォルト: 全名前空間） |
| filenames | 対象ファイル（複数指定可） | No |
| ns-exclude-regex | 除外名前空間の正規表現 | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ファイルパス | 昇順 |
| 2 | 行番号 | 昇順 |
| 3 | 列番号 | 昇順 |

### 改ページ条件

N/A（コンソール出力のため）

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| db.diagnostics.clj-kondo | clj-kondo診断結果 | URI |
| db.diagnostics.clj-depend | clj-depend違反結果 | namespace |
| db.diagnostics.built-in | 組み込み診断結果 | URI |
| db.diagnostics.custom | カスタム診断結果 | URI |

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

#### db.diagnostics.clj-kondo

| 参照項目（キー名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| type | コード | - | キーワード→文字列変換 |
| message | メッセージ | - | - |
| level | 重要度 | level != :off | severity変換 |
| row | 行番号 | - | - |
| col | 列番号 | - | - |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| result-code | errors? -> 3, warnings? -> 2, else 0 | - | 終了コード |
| severity | level->severity関数 | - | :error->1, :warning->2, :info->3 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[diagnosticsコマンド実行] --> B[オプション解析]
    B --> C[プロジェクト解析初期化]
    C --> D[clj-kondo解析実行]
    D --> E[カスタムlinter実行]
    E --> F[clj-depend検証]
    F --> G[診断結果集約]
    G --> H{出力形式判定}
    H -->|テキスト| I[テキスト形式出力]
    H -->|EDN| J[EDN形式出力]
    H -->|JSON| K[JSON形式出力]
    I --> L[終了コード設定]
    J --> L
    K --> L
    L --> M[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| プロジェクト解析失敗 | 不正なプロジェクト構成 | Error during project analysis | プロジェクト設定確認 |
| 名前空間未発見 | 指定名前空間が存在しない | Namespace X not found | 名前空間名確認 |
| 診断なし | 問題が検出されない | No diagnostics found! | 正常終了 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数百〜数千ファイル |
| 目標出力時間 | 初回解析: 30秒以内、キャッシュ有: 5秒以内 |
| 同時出力数上限 | 1（シングルスレッド処理） |

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

- ファイルパスの出力時、絶対パス/相対パスをオプションで制御可能
- 診断結果に機密情報が含まれる可能性があるため、出力先の管理に注意

## 備考

- `--dry`オプションは本コマンドでは使用されない
- result-codeによりCI/CDでの条件分岐が可能（0:問題なし、2:警告あり、3:エラーあり）
- カスタムlinterは設定ファイルで有効化/無効化が可能

---

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

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

### 推奨読解順序

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

diagnostics機能で扱われる主要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | db.clj | `lib/src/clojure_lsp/db.clj` | `:diagnostics`キーの構造（`:clj-kondo`, `:clj-depend`, `:built-in`, `:custom`） |
| 1-2 | shared.clj | `lib/src/clojure_lsp/shared.clj` | severity変換関数`level->severity`, `severity->level` |

**読解のコツ**: Clojureのマップ構造に注目。`db`アトムの`:diagnostics`配下にURI単位で診断結果が格納される。

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

CLIからの呼び出しフローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | main.clj | `cli/src/clojure_lsp/main.clj` | **176行目**: `"diagnostics"`アクション分岐 |
| 2-2 | main.clj | `cli/src/clojure_lsp/main.clj` | **203行目**: `internal-api/diagnostics`呼び出し |

**主要処理フロー**:
1. **156-180行目**: `parse`関数でコマンドライン引数を解析
2. **194-215行目**: `handle-action!`関数でアクション実行
3. **203行目**: diagnosticsの場合`internal-api/diagnostics`を呼び出し

#### Step 3: 内部API層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | internal_api.clj | `lib/src/clojure_lsp/internal_api.clj` | **355-372行目**: `diagnostics*`関数の実装 |
| 3-2 | internal_api.clj | `lib/src/clojure_lsp/internal_api.clj` | **344-353行目**: `diagnostics-by-uri`関数 |
| 3-3 | internal_api.clj | `lib/src/clojure_lsp/internal_api.clj` | **325-342行目**: 出力フォーマット変換 |

**主要処理フロー**:
- **357行目**: `setup-project-and-clojure-only-deps-analysis!`でプロジェクト解析
- **360行目**: `diagnostics-by-uri`で全URIの診断取得
- **366-370行目**: 出力形式に応じたフォーマット

#### Step 4: 診断機能コア層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | diagnostics.clj | `lib/src/clojure_lsp/feature/diagnostics.clj` | **115-129行目**: `find-diagnostics`関数 |
| 4-2 | diagnostics.clj | `lib/src/clojure_lsp/feature/diagnostics.clj` | **78-87行目**: clj-kondo診断変換 |
| 4-3 | diagnostics.clj | `lib/src/clojure_lsp/feature/diagnostics.clj` | **36-64行目**: 診断構造体生成 |

**主要処理フロー**:
- **115行目**: `find-diagnostics`が各診断ソースを集約
- **122行目**: clj-kondo診断を取得
- **125行目**: clj-depend診断を取得
- **128行目**: built-in/custom診断を追加

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

```
clojure-lsp.main/-main
    |
    +-- parse (コマンド解析)
    |
    +-- handle-action!
           |
           +-- clojure-lsp.internal-api/diagnostics
                  |
                  +-- build-components (コンポーネント初期化)
                  |
                  +-- diagnostics*
                         |
                         +-- setup-api!
                         |
                         +-- setup-project-and-clojure-only-deps-analysis!
                         |      |
                         |      +-- startup/initialize-project
                         |
                         +-- diagnostics-by-uri
                         |      |
                         |      +-- options->uris
                         |      |
                         |      +-- f.diagnostic/find-diagnostics
                         |             |
                         |             +-- kondo-findings->diagnostics
                         |             +-- clj-depend-violations->diagnostics
                         |             +-- built-in-diagnostics
                         |             +-- custom-diagnostics->diagnostics
                         |
                         +-- diagnostics->diagnostic-messages (テキスト変換)
```

### データフロー図

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

CLIオプション ────────▶ parse ────────────────────────▶ options map
     |                                                      |
     v                                                      v
project-root ─────────▶ analyze! ─────────────────────▶ db (analysis)
     |                                                      |
     v                                                      v
namespace/filenames ──▶ options->uris ────────────────▶ [uri ...]
     |                                                      |
     v                                                      v
db.diagnostics ───────▶ find-diagnostics ─────────────▶ [{:range :message :code ...}]
     |                                                      |
     v                                                      v
出力オプション ────────▶ format (edn/json/text) ───────▶ stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| main.clj | `cli/src/clojure_lsp/main.clj` | ソース | CLIエントリーポイント |
| api.clj | `lib/src/clojure_lsp/api.clj` | ソース | 公開API定義 |
| internal_api.clj | `lib/src/clojure_lsp/internal_api.clj` | ソース | 内部API実装 |
| diagnostics.clj | `lib/src/clojure_lsp/feature/diagnostics.clj` | ソース | 診断機能コア |
| built_in.clj | `lib/src/clojure_lsp/feature/diagnostics/built_in.clj` | ソース | 組み込み診断 |
| custom.clj | `lib/src/clojure_lsp/feature/diagnostics/custom.clj` | ソース | カスタム診断 |
| db.clj | `lib/src/clojure_lsp/db.clj` | ソース | データベース定義 |
| shared.clj | `lib/src/clojure_lsp/shared.clj` | ソース | 共通ユーティリティ |
| kondo.clj | `lib/src/clojure_lsp/kondo.clj` | ソース | clj-kondo連携 |
| clj_depend.clj | `lib/src/clojure_lsp/clj_depend.clj` | ソース | clj-depend連携 |
