# 画面設計書 35-dfmtリント

## 概要

本ドキュメントは、serve-d LSPサーバーが提供するdfmtリント機能の画面設計書である。D言語ソースファイルに対してdfmtのフォーマットルールに基づく診断を実行し、フォーマット指示コメントの問題をクライアントに配信する機能を定義する。

### 本画面の処理概要

本機能は、D言語ソースコード内のdfmtフォーマット指示コメント（`//dfmt on`, `//dfmt off`）を解析し、冗長な指示や不正な指示を診断情報としてクライアントに送信する。

**業務上の目的・背景**：D言語のコードフォーマッタであるdfmtでは、`//dfmt off` と `//dfmt on` コメントでフォーマットの一時無効化/有効化ができる。しかし、冗長なon/off（既にonの状態でのon等）や、不正なdfmtコマンド（スペルミス等）は意図しない動作を引き起こす可能性がある。本機能はこれらの問題をリアルタイムに検出し、コード品質の維持を支援する。

**画面へのアクセス方法**：ドキュメントの変更時（`textDocument/didChange`）にデバウンス付きで自動的にトリガーされる。

**主要な操作・処理内容**：
1. ドキュメント変更をトリガーとして受信
2. フォーマット設定（enableFormatting）の有効性を確認
3. DfmtComponentの利用可能性を確認
4. `findDfmtInstructions` メソッドでdfmt指示コメントを検出
5. 各指示について冗長性（redundant on/off）や不正指示（unknown）を判定
6. 診断情報を生成して診断マネージャ経由で配信

**画面遷移**：本機能から直接の画面遷移はない。

**権限による表示制御**：設定値 `d.enableFormatting` による有効/無効制御。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 37 | dfmtリント | 主機能 | dfmtのフォーマットルールに基づく診断を提供する |
| 38 | 診断マネージャ | 補助機能 | dfmt診断結果を診断マネージャ経由でクライアントに配信する |
| 9 | ドキュメント変更 (textDocument/didChange) | 補助機能 | テキスト変更時にデバウンス付きでdfmtリントがトリガーされる |

## 画面種別

LSP通知（診断情報配信）

## URL/ルーティング

`textDocument/publishDiagnostics` 通知として配信

## 入出力項目

### 入力

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

### 出力（診断情報）

| 項目名 | 型 | 説明 |
|--------|------|------|
| range | TextRange | 問題箇所の範囲 |
| severity | DiagnosticSeverity | 重大度（warning/hint） |
| source | string | "dfmt" 固定 |
| message | string | 診断メッセージ |
| code | string | 診断コード |
| tags | DiagnosticTag[] | タグ（unnecessary等） |

## 表示項目

| 表示項目 | 説明 |
|----------|------|
| 波線マーカー | 冗長なdfmt指示や不正指示に対して波線表示 |
| 問題パネル | Problems パネルに診断一覧として表示 |

## イベント仕様

### 1-dfmt lint実行

1. `lint(Document document)` 関数が呼び出される
2. `enableFormatting` 設定確認
3. `DfmtComponent` 存在確認
4. `findDfmtInstructions` でdfmt指示コメントを検出
5. 各指示について以下を判定：
   - **dfmtOn/dfmtOff**: 現在の状態と同一のon/offは冗長（hint, unnecessary）
   - **unknown**: 不正なdfmtコマンド（warning）
6. 冗長な場合のメッセージ：
   - `"Redundant `dfmt on`"` （コード: "redundant-on"）
   - `"Redundant `dfmt off`"` （コード: "redundant-off"）
7. 不正な場合のメッセージ：
   - `"Not a valid dfmt command (try `//dfmt off` or `//dfmt on` instead)"` （コード: "unknown-comment"）
8. 診断マネージャ（DiagnosticSlot=2）に結果格納・配信

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

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

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

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

## メッセージ仕様

| メッセージ種別 | 条件 | メッセージ内容 |
|---------------|------|---------------|
| hint | 冗長なdfmt on | "Redundant `dfmt on`" |
| hint | 冗長なdfmt off | "Redundant `dfmt off`" |
| warning | 不正なdfmtコマンド | "Not a valid dfmt command (try `//dfmt off` or `//dfmt on` instead)" |

## 例外処理

| 例外条件 | 処理内容 |
|----------|----------|
| enableFormattingが無効 | 早期リターン |
| DfmtComponentが利用不可 | 早期リターン |

## 備考

- DiagnosticSlot = 2（dfmtは診断スロット2を使用）
- 冗長なon/offは severity=hint, tags=[unnecessary] として表示される
- 不正なdfmtコマンドは severity=warning として表示される
- fmtOn/fmtOff のステートマシンで冗長性を判定（初期状態はon）
- バイトオフセットからPositionへの変換には `movePositionBytes` を使用

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dfmt.d | `source/served/linters/dfmt.d` | DiagnosticSlot=2（行22）、DfmtDiagnosticSource定数（行20） |
| 1-2 | dfmt.d (workspaced) | workspacedサブパッケージ | DfmtInstruction型（Type: dfmtOn/dfmtOff/unknown）の定義 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dfmt.d | `source/served/linters/dfmt.d` | `lint` 関数（行24-36）のシンプルなフロー |

**主要処理フロー**:
1. **行26-28**: enableFormatting設定確認
2. **行30-32**: DfmtComponent取得
3. **行34**: `lintDfmt` 呼び出し
4. **行35**: 診断マネージャ配信

#### Step 3: リントロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dfmt.d | `source/served/linters/dfmt.d` | `lintDfmt` 関数（行38-91）。findDfmtInstructionsの結果を元にステートマシンで冗長性判定 |

**主要処理フロー**:
- **行40**: `findDfmtInstructions` でdfmt指示を検出
- **行43**: `fmtOn` 状態変数（初期値=true）
- **行56-87**: 各指示についてswitch判定
- **行68-79**: dfmtOn/Off: 同一状態なら冗長診断
- **行81-86**: unknown: 不正指示診断

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

```
lint (dfmt.d:24)
    |
    +-- config(document.uri) 設定取得
    +-- backend.get!DfmtComponent
    +-- lintDfmt (dfmt.d:38)
    |   +-- dfmt.findDfmtInstructions (workspaced)
    |   +-- [各instruction] ステートマシン判定
    |   +-- document.movePositionBytes (位置変換)
    +-- createDiagnosticsFor!DiagnosticSlot
    +-- updateDiagnostics
```

### データフロー図

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

Document          --->  lint関数                       --->  publishDiagnostics通知
  .rawText               |                                    .diagnostics[]
                         +-- 設定確認                           .range
                         +-- findDfmtInstructions               .severity (hint/warning)
                         +-- ステートマシン判定                  .source ("dfmt")
                         +-- 診断マネージャ配信                 .message
                                                                .code
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dfmt.d | `source/served/linters/dfmt.d` | ソース | dfmtリント本体（134行、テスト含む） |
| diagnosticmanager.d | `source/served/linters/diagnosticmanager.d` | ソース | 診断マネージャ |
| extension.d | `source/served/extension.d` | ソース | グローバル変数 |
| types.d | `source/served/types.d` | ソース | Diagnostic等のLSP型定義 |
