# 画面設計書 34-DScannerリント（served/doDscanner）

## 概要

本ドキュメントは、serve-d LSPサーバーが提供するDScanner静的解析機能の画面設計書である。D言語ソースファイルに対してDScannerによる静的解析を実行し、診断情報（警告・エラー・ヒント）をクライアントに配信する機能を定義する。

### 本画面の処理概要

本機能は、D言語ソースコードに対してDScanner静的解析を実行し、コードの問題点を診断情報としてクライアントに送信する。ドキュメント変更時に自動トリガーされるほか、手動実行も可能である。

**業務上の目的・背景**：D言語の開発において、コンパイル前にコードの問題を検出するために静的解析が不可欠である。DScannerはD言語専用の静的解析ツールであり、未使用パラメータ、ローカルインポートの問題、構文エラー等を検出する。本機能はエディタ上でリアルタイムに診断結果を表示することで、開発効率を向上させる。診断結果には自動修正（autofix）情報も含まれ、ワンクリック修正が可能となる。

**画面へのアクセス方法**：以下のタイミングで自動的に実行される：(1) D言語ファイルのテキスト変更時（`textDocument/didChange`、デバウンス付き）、(2) ファイル保存時。また、`served/doDscanner` リクエストによる手動実行も可能。

**主要な操作・処理内容**：
1. ドキュメント変更またはファイル保存をトリガーとして受信
2. D言語ファイルであることを確認
3. DscannerComponentの利用可能性を確認
4. リント設定（enableLinting, enableStaticLinting）の有効性を確認
5. 除外ファイルリストによるスキップ判定
6. 無視キーリストの取得
7. DScanner INI設定ファイルの特定
8. DscannerComponentの `lint` メソッドでソースコードを解析
9. 結果のDScannerIssueを診断情報（Diagnostic）に変換
10. @suppress アノテーションによるフィルタリング
11. 診断マネージャ経由でクライアントに配信

**画面遷移**：本機能から直接の画面遷移はない。診断結果に対してコードアクションを要求すると、コードアクション画面（No.19）が呼び出される。

**権限による表示制御**：設定値（`d.enableLinting`, `d.enableStaticLinting`）による有効/無効制御。`dscanner.excludedFiles` による除外ファイル設定。`dscanner.ignoredKeys` による特定チェック項目の無視。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 35 | DScanner静的解析 | 主機能 | D-Scannerを使用したソースコードの静的解析を実行し診断結果を返却する |
| 39 | DScanner手動実行 (served/doDscanner) | 補助機能 | served/doScannerリクエストによる手動トリガーでDScanner静的解析を実行する |
| 38 | 診断マネージャ | 補助機能 | DScanner診断結果を診断マネージャ経由でクライアントに配信する |
| 9 | ドキュメント変更 (textDocument/didChange) | 補助機能 | テキスト変更時にデバウンス付きでDScanner静的解析がトリガーされる |

## 画面種別

LSP通知（診断情報配信）/ LSPリクエスト（手動実行）

## URL/ルーティング

- 自動実行：`textDocument/publishDiagnostics` 通知として配信
- 手動実行：`served/doDscanner` リクエスト

## 入出力項目

### 入力

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| document | Document | Yes | 解析対象ドキュメント |

### 出力（診断情報）

| 項目名 | 型 | 説明 |
|--------|------|------|
| range | TextRange | 問題箇所の範囲 |
| severity | DiagnosticSeverity | 重大度（error/warning/hint） |
| source | string | 診断ソース（"DScanner" または "serve-d"） |
| message | string | 診断メッセージ |
| code | string | 診断コード（例: "dscanner.suspicious.unused_parameter"） |
| tags | DiagnosticTag[] | タグ（unnecessary等） |
| relatedInformation | DiagnosticRelatedInformation[] | 関連情報 |
| data | object | 自動修正データ（checkName, autofixes） |

## 表示項目

エディタ上に表示される診断情報。

| 表示項目 | 説明 |
|----------|------|
| 波線マーカー | コードの問題箇所に表示される波線（色は重大度に応じて変化） |
| 問題パネル | Problems パネルに診断一覧として表示 |
| インラインヒント | 未使用パラメータ等のヒント情報 |

## イベント仕様

### 1-DScanner lint実行

1. `lint(Document document)` 関数が呼び出される
2. D言語チェック（`getLanguageId != "d"` で早期リターン）
3. `backend.getBestInstance!DscannerComponent` でインスタンス取得
4. `enableLinting` && `enableStaticLinting` 設定確認
5. 除外ファイルチェック（`isExcludedFile` - globパターンマッチ）
6. `ignoredKeys` リスト取得
7. `getDscannerIniForDocument` でINI設定ファイルパス取得
8. `DscannerComponent.lint` 呼び出し（rawText, INI設定, デフォルト設定を渡す）
9. 結果ループ：ignoredKeysに含まれるissueをスキップ
10. `@suppress` アノテーション処理（行末の抑制指定を確認）
11. `convertFromWorkspaced` で Diagnostic 変換（range, severity, relatedInformation, data）
12. ソース設定：workspacedキーなら "serve-d"、それ以外は "DScanner"
13. `createDiagnosticsFor!DiagnosticSlot` に結果格納
14. `updateDiagnostics` で配信

## データベース更新仕様

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

本機能はデータベースへの更新を行わない。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| lint実行 | なし | SELECT | ドキュメントの読み取りと解析のみ |

## メッセージ仕様

| メッセージ種別 | 条件 | メッセージ内容 |
|---------------|------|---------------|
| 診断情報 | 問題検出時 | DScannerが検出した問題の説明文 |
| 空診断 | 設定無効時・除外ファイル時 | 空の診断配列（問題なしとして表示） |

## 例外処理

| 例外条件 | 処理内容 |
|----------|----------|
| D言語以外のドキュメント | 早期リターン |
| DscannerComponentが利用不可 | 早期リターン |
| enableLinting/enableStaticLintingが無効 | 早期リターン |
| 除外ファイル一致 | 空診断を設定して返却 |

## 備考

- DiagnosticSlot = 0（DScannerは診断スロット0を使用）
- デフォルト設定では `could_be_immutable_check` と `undocumented_declaration_check` が無効化されている
- `@suppress(all)`, `@suppress:all`, `@suppress(キー名)`, `@suppress:キー名` による行単位の抑制に対応
- `stfu` コメント（行末）による抑制にも対応
- 未使用パラメータ・未使用変数は severity=hint, tags=[unnecessary] に自動調整される
- 自動修正データ（autofixes）は CodeReplacement または ResolveContext の2形式がある

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dscanner.d | `source/served/linters/dscanner.d` | DiagnosticSlot定数（行32）、servedDefaultDscannerConfig（行26-29）の定義 |
| 1-2 | diagnosticmanager.d | `source/served/linters/diagnosticmanager.d` | 診断マネージャの仕組み、createDiagnosticsForとupdateDiagnosticsの関係 |

**読解のコツ**: DiagnosticSlotはリンター毎に異なるスロットを使用する。DScanner=0, DUB=1, dfmt=2 の順に割り当てられている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dscanner.d | `source/served/linters/dscanner.d` | `lint` 関数（行34-96）の全体フロー |

**主要処理フロー**:
1. **行36-37**: D言語チェック
2. **行39-41**: DscannerComponentインスタンス取得
3. **行44-46**: リント設定確認
4. **行48-52**: 除外ファイルチェック（globMatch使用）
5. **行54**: ignoredKeys取得
6. **行56**: DScanner INIファイルパス取得
7. **行57-58**: DscannerComponent.lint呼び出し
8. **行61-92**: 結果ループ（フィルタリング・変換）
9. **行94-95**: 診断マネージャへの格納・配信

#### Step 3: 変換ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dscanner.d | `source/served/linters/dscanner.d` | `convertFromWorkspaced` 関数（行135-152）。DScannerIssueからDiagnosticへの変換 |
| 3-2 | dscanner.d | `source/served/linters/dscanner.d` | `adjustSeverityForType` 関数（行237-250）。特定キーの重大度調整 |
| 3-3 | dscanner.d | `source/served/linters/dscanner.d` | `getDscannerDiagnosticRange` 関数（行216-235）。範囲計算ロジック |

#### Step 4: 除外ファイル判定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | dscanner.d | `source/served/linters/dscanner.d` | `isExcludedFile` 関数（行98-113）。ワークスペースルート相対パスでのglobMatch |

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

```
lint (dscanner.d:34)
    |
    +-- document.getLanguageId チェック
    +-- backend.getBestInstance!DscannerComponent
    +-- config(document.uri) 設定取得
    +-- isExcludedFile (dscanner.d:98)
    |   +-- globMatch
    +-- getDscannerIniForDocument (dscanner.d:121)
    +-- DscannerComponent.lint (workspaced)
    +-- [各issue] convertFromWorkspaced (dscanner.d:135)
    |   +-- getDscannerDiagnosticRange (dscanner.d:216)
    |   +-- adjustSeverityForType (dscanner.d:237)
    |   +-- toJson (autofix data)
    +-- createDiagnosticsFor!DiagnosticSlot
    +-- updateDiagnostics
```

### データフロー図

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

Document          --->  lint関数                       --->  publishDiagnostics通知
  .uri                   |                                     .uri
  .rawText               +-- D言語チェック                     .diagnostics[]
                         +-- 設定確認                            .range
                         +-- 除外ファイルチェック                .severity
                         +-- DScanner解析                       .source
                         +-- @suppress フィルタ                 .message
                         +-- Diagnostic変換                     .code
                         +-- 診断マネージャ配信                 .data (autofixes)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dscanner.d | `source/served/linters/dscanner.d` | ソース | DScanner リント本体（499行、テスト含む） |
| diagnosticmanager.d | `source/served/linters/diagnosticmanager.d` | ソース | 診断マネージャ（スロット管理・配信） |
| extension.d | `source/served/extension.d` | ソース | グローバル変数、activeInstance等 |
| types.d | `source/served/types.d` | ソース | Diagnostic等のLSP型定義 |
| code_actions.d | `source/served/commands/code_actions.d` | ソース | DScanner診断に基づくコードアクション |
