# 画面設計書 27-ワークスペース診断

## 概要

本ドキュメントは、Lua Language Serverにおける「ワークスペース診断」機能の画面設計書です。LSPプロトコルの `workspace/diagnostic` リクエストに対応し、ワークスペース全体の診断情報を取得します。

### 本画面の処理概要

ワークスペース診断機能は、ワークスペースに含まれる全てのLuaファイルに対して診断処理を実行し、プロジェクト全体の問題を一括して検出する機能です。

**業務上の目的・背景**：個々のファイルの診断（No.26）だけでなく、プロジェクト全体を対象とした診断を行うことで、ファイル間の依存関係に起因する問題や、プロジェクト全体の品質を把握できます。CIパイプラインでの品質チェックや、リリース前の最終確認などに活用されます。大規模プロジェクトでは、開いていないファイルの問題も検出できるため、潜在的なバグの早期発見に貢献します。

**画面へのアクセス方法**：ワークスペース診断は以下のタイミングで自動的に実行されます：
- ワークスペースの初期ロード完了後（`Lua.diagnostics.workspaceDelay` 設定に従って遅延実行）
- ファイルの保存時または変更時（`Lua.diagnostics.workspaceEvent` 設定に依存）
- ステータスバーからの手動実行（No.44 ステータスクリック連携）

**主要な操作・処理内容**：
1. ワークスペース内の全Luaファイルを列挙
2. 各ファイルに対して診断処理を順次実行
3. 進捗状況をプログレスバーで表示
4. 各ファイルの診断結果をpublishDiagnosticsまたは部分結果として通知
5. 全ファイルの診断完了後、処理を終了

**画面遷移**：診断結果はエディタの問題パネルに集約表示されます。問題をクリックすると該当ファイルの該当箇所にジャンプします。

**権限による表示制御**：`Lua.diagnostics.enable` 設定がfalseの場合、ワークスペース診断は実行されません。また、`Lua.diagnostics.workspaceDelay` が負の値の場合もスキップされます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 30 | 構文診断 | 主機能 | ワークスペース全体の診断情報を取得する主処理 |

## 画面種別

LSP機能（ワークスペース診断）

## URL/ルーティング

LSPメソッド: `workspace/diagnostic`

## 入出力項目

### 入力パラメータ

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| previousResultIds | PreviousResultId[] | いいえ | 以前の結果ID（キャッシュ判定用） |
| partialResultToken | string | いいえ | 部分結果の通知用トークン |

### 出力パラメータ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| items | WorkspaceDocumentDiagnosticReport[] | 各ファイルの診断結果リスト |

### WorkspaceDocumentDiagnosticReport構造

| 項目名 | 型 | 説明 |
|--------|-----|------|
| kind | string | 'full'（全結果）または 'unchanged'（変更なし） |
| resultId | string | 結果ID（キャッシュ用） |
| uri | uri | ファイルURI |
| version | number | ファイルバージョン |
| items | Diagnostic[] | 診断結果のリスト |

## 表示項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| プログレスバー | ProgressBar | 処理進捗（現在ファイル数/全ファイル数） |
| 問題パネル | Panel | 全ファイルの診断結果を一覧表示 |

## イベント仕様

### 1-ワークスペース診断要求

1. エディタが `workspace/diagnostic` リクエストを送信
2. サーバーがワークスペース内の全ファイルを列挙
3. 各ファイルに対して診断処理を実行
4. 部分結果を `$/progress` 通知で送信
5. 全ファイル処理完了後、空のitemsを返却

### 2-スコープ診断（内部処理）

1. ワークスペースのリロード時または設定変更時にトリガー
2. `diagnosticsScope` 関数を呼び出し
3. 進捗表示とともに全ファイルを診断
4. 結果を `publishDiagnostics` で通知

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ワークスペース診断要求 | - | - | データベース操作なし（読み取り専用） |

## メッセージ仕様

| メッセージID | 種別 | 表示内容 | 発生条件 |
|-------------|------|----------|----------|
| WORKSPACE_DIAGNOSTIC | 進捗 | "Diagnosing workspace files..." | ワークスペース診断実行中 |
| WINDOW_SETTING_WS_DIAGNOSTIC | 確認 | 診断設定の確認ダイアログ | 診断がキャンセルされた場合 |
| WINDOW_DISABLE_DIAGNOSTIC | 選択肢 | 診断を無効化するか | 設定変更の提案 |
| WINDOW_DELAY_WS_DIAGNOSTIC | 選択肢 | 診断を遅延させるか | 遅延設定の提案 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| Lua.diagnostics.enable が false | 診断をスキップ、キャッシュをクリア |
| Lua.diagnostics.workspaceDelay < 0 | ワークスペース診断をスキップ |
| ユーザーによるキャンセル | 診断を中断、設定変更を提案 |
| ワークスペースの読み込み中 | 読み込み完了まで待機 |

## 備考

- ワークスペース診断は大量のファイルを処理するため、パフォーマンスに配慮した実装
- `Lua.diagnostics.workspaceRate` で診断速度を調整可能（CPU使用率の制御）
- オープン中のファイルを優先的に診断（sortedUrisで先頭に配置）
- 診断完了後にノードキャッシュをクリアしてメモリを解放
- キャンセル機能付きのプログレスバーを表示

---

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

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

### 推奨読解順序

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

ワークスペース診断特有のデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | diagnostic.lua | `script/provider/diagnostic.lua` | WorkspaceDocumentDiagnosticReport構造（1524-1540行目付近）を確認 |

**読解のコツ**: ワークスペース診断は部分結果を`$/progress`で通知する方式を採用しています。

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

LSPリクエストハンドラがどのように呼び出されるかを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | provider.lua | `script/provider/provider.lua` | `workspace/diagnostic` ハンドラ（1509-1554行目）を確認 |

**主要処理フロー**:
1. **1509行目**: `m.register 'workspace/diagnostic'` でハンドラを登録
2. **1518行目**: 診断プロバイダーを取得
3. **1519-1522行目**: 以前の結果IDから例外リストを構築
4. **1523行目**: clearCacheExceptでキャッシュをクリア
5. **1524-1550行目**: pullDiagnosticScopeで診断を実行
6. **1552行目**: 空のitemsを返却

#### Step 3: スコープ診断処理を理解する

実際のワークスペース診断処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | diagnostic.lua | `script/provider/diagnostic.lua` | diagnosticsScope関数（581-601行目）を確認 |
| 3-2 | diagnostic.lua | `script/provider/diagnostic.lua` | awaitDiagnosticsScope関数（526-579行目）を確認 |

**主要処理フロー**:
- **581-588行目**: ワークスペース準備完了と設定確認
- **593-601行目**: awaitDiagnosticsScopeを非同期で実行
- **531-533行目**: ワークスペース読み込み完了を待機
- **551-558行目**: ファイルをオープン状態で優先ソート
- **561-575行目**: 各ファイルを診断し、進捗を更新

#### Step 4: プル型診断処理を理解する

workspace/diagnosticリクエストに対応する処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | diagnostic.lua | `script/provider/diagnostic.lua` | pullDiagnosticScope関数（604-645行目）を確認 |

**主要処理フロー**:
- **607-609行目**: 各スコープフォルダの準備確認
- **612-637行目**: 非同期で各スコープの診断を実行
- **626-635行目**: コールバックで部分結果を通知

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

```
workspace/diagnostic (provider.lua:1509-1554)
    │
    └─ pullDiagnosticScope (provider/diagnostic.lua:604-645)
           │
           └─ awaitDiagnosticsScope (provider/diagnostic.lua:526-579)
                  │
                  ├─ files.getAllUris(suri) - ファイル列挙
                  │
                  ├─ sortedUris - オープンファイル優先ソート
                  │
                  └─ pullDiagnostic(fileUri) for each file
                         │
                         └─ callback(result) - 部分結果通知
                                │
                                └─ proto.notify('$/progress', ...)

diagnosticsScope (provider/diagnostic.lua:581-601)
    │
    └─ awaitDiagnosticsScope (provider/diagnostic.lua:526-579)
           │
           └─ doDiagnostic(fileUri) for each file
                  │
                  └─ proto.notify('textDocument/publishDiagnostics', ...)
```

### データフロー図

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

WorkspaceDiagnosticRequest {   1. ワークスペース準備確認        $/progress通知 {
  previousResultIds,           2. ファイル列挙                    [部分結果1],
  partialResultToken           3. オープンファイル優先ソート       [部分結果2],
}                              4. 各ファイルを診断                 ...
                               5. 部分結果を通知               }
    │                          6. 完了時メモリ解放              │
    │                                                         ▼
    │                                                      items: []
    └───────────────────────────────────────────────────────▶
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| provider.lua | `script/provider/provider.lua` | ソース | LSPリクエストハンドラの登録・処理 |
| diagnostic.lua | `script/provider/diagnostic.lua` | ソース | 診断処理のメイン制御 |
| init.lua | `script/core/diagnostics/init.lua` | ソース | 診断チェックの実行制御 |
| progress.lua | `script/progress.lua` | ソース | プログレスバー表示 |
| files.lua | `script/files.lua` | ソース | ファイル列挙・状態管理 |
| scope.lua | `script/workspace/scope.lua` | ソース | ワークスペーススコープ管理 |
| config.lua | `script/config.lua` | ソース | 設定値の管理 |
