# 機能設計書 42-診断抑制

## 概要

本ドキュメントは、clojure-lspの「診断抑制」機能（suppress-diagnostic コマンド）の設計を詳細に記載する。この機能は、特定の診断警告を抑制するコメントを追加するコードアクション機能である。

### 本機能の処理概要

**業務上の目的・背景**：静的解析ツール（clj-kondo、clojure-lsp）が出力する警告の中には、意図的に無視したいものがある。例えば、リフレクション警告を承知の上で使用している場合や、未使用変数が将来使用予定である場合などである。この機能により、特定の警告を抑制するアノテーションを簡単に追加でき、重要な警告に集中できるようになる。

**機能の利用シーン**：診断警告が表示されている箇所で、その警告を意図的に無視したい場合にコードアクションメニューから「Suppress 'diagnostic-code' diagnostic」を選択する。

**主要な処理内容**：
1. 診断コードを取得し、clj-kondo由来かclojure-lsp由来かを判定
2. 対象のフォームを特定
3. フォームの前に `#_{:clj-kondo/ignore [:diagnostic-code]}` または `#_{:clojure-lsp/ignore [:diagnostic-code]}` コメントを挿入

**関連システム・外部連携**：clj-kondo の ignore コメント仕様、clojure-lsp 独自の ignore コメント仕様と連携。

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

## 関連画面

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

## 機能種別

コード編集 / コメント挿入

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | String | Yes | 対象ファイルURI | 有効なファイルURI |
| line | Number | Yes | カーソル行（0始まり） | 非負整数 |
| character | Number | Yes | カーソル列（0始まり） | 非負整数 |
| diagnostic-code | String | Yes | 抑制する診断コード | 非空文字列 |

### 入力データソース

- エディタからの診断情報（diagnostic.code）
- カーソル位置情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| loc | zloc | 編集後のzipper位置 |
| range | Map | 挿入位置の範囲情報 |

### 出力先

- 対象ソースファイル（コメント挿入）

## 処理フロー

### 処理シーケンス

```
1. 診断コードの名前空間を判定
   └─ "clojure-lsp" 名前空間なら :clojure-lsp/ignore
   └─ それ以外なら :clj-kondo/ignore
2. カーソル位置から対象フォームを特定
   └─ edit/find-op でオペレーションを検索
   └─ z/up で親フォームに移動
3. ignoreコメントノードを生成
   └─ n/uneval-node で #_ 形式を生成
   └─ n/map-node で {:clj-kondo/ignore [:code]} を生成
4. フォームの直前にコメントを挿入
   └─ z/insert-left* で挿入
5. 編集結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{診断コードの名前空間}
    B -->|clojure-lsp| C[:clojure-lsp/ignore]
    B -->|その他| D[:clj-kondo/ignore]
    C --> E[対象フォーム特定]
    D --> E
    E --> F[ignoreコメント生成]
    F --> G[フォーム前に挿入]
    G --> H[編集結果返却]
    H --> I[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ignore種別判定 | 診断コードの名前空間が"clojure-lsp"なら:clojure-lsp/ignore、それ以外は:clj-kondo/ignore | 常時 |
| BR-02 | コメント形式 | `#_{:ignore-type [:diagnostic-code]}` 形式 | 常時 |
| BR-03 | インデント保持 | 元のフォームのインデントを維持 | 常時 |

### 計算ロジック

```clojure
(defn determine-ignore-type [diagnostic-code]
  (if (= "clojure-lsp" (namespace (keyword diagnostic-code)))
    :clojure-lsp/ignore
    :clj-kondo/ignore))
```

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | N/A | 対象フォームが見つからない場合は空リスト返却 | カーソル位置を調整 |

### リトライ仕様

リトライ不要

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

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

## パフォーマンス要件

- 応答時間: 100ms以内

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

特になし

## 備考

- clj-kondo と clojure-lsp で異なる ignore キーワードを使用する理由は、診断の出力元が異なるため
- 既存の ignore コメントがある場合の動作は現在サポートされていない（常に新規追加）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | node.clj (rewrite-clj) | 外部ライブラリ | n/uneval-node, n/map-node の構造を理解 |

**読解のコツ**: rewrite-cljのノード構造を把握することで、コメント挿入の仕組みが理解できる。

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

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

**主要処理フロー**:
1. **143-144行目**: `:suppress-diagnostic` コマンドのディスパッチ定義

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | suppress-diagnostic 関数 |

**主要処理フロー**:
- **1450-1466行目**: `suppress-diagnostic` 関数の実装
- **1451-1453行目**: ignore種別の判定ロジック
- **1454-1456行目**: 対象フォームの特定
- **1457-1462行目**: ignoreコメントノードの生成

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

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

**主要処理フロー**:
- **317-326行目**: `suppress-diagnostic-actions` - コードアクションの定義
- **517-519行目**: コードアクション一覧への追加条件

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

```
handlers/code-actions
    │
    └─ f.code-actions/all
           │
           └─ suppress-diagnostic-actions
                  └─ diagnostics から code を抽出

handlers/execute-command
    │
    └─ f.command/call-command
           │
           └─ run-command :suppress-diagnostic
                  │
                  └─ r.transform/suppress-diagnostic
                         │
                         ├─ edit/find-op (フォーム検索)
                         ├─ n/uneval-node (コメント生成)
                         └─ z/insert-left* (挿入)
```

### データフロー図

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

diagnostic-code ───▶ namespace判定 ───▶ ignore-type
                           │
URI, Line, Col ────▶ find-op ───▶ form-zloc
                           │
                    ┌──────┴──────┐
                    │             │
               uneval-node    map-node
                    │             │
                    └──────┬──────┘
                           ▼
                    insert-left* ───▶ 編集済みzloc
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | ソース | 診断抑制のメインロジック |
| command.clj | `lib/src/clojure_lsp/feature/command.clj` | ソース | コマンドディスパッチ |
| code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | ソース | コードアクション定義 |
| edit.clj | `lib/src/clojure_lsp/refactor/edit.clj` | ソース | 編集ユーティリティ |
