# 画面設計書 39-診断ワーカー

## 概要

本ドキュメントは、Lua Language ServerのCLI内部コマンド「診断ワーカー（--check_worker）」の画面設計書です。

### 本画面の処理概要

この画面（CLI内部コマンド）は、診断チェック（--check）から起動される並列ワーカープロセスで、実際の診断処理を実行します。

**業務上の目的・背景**：
大規模なLuaプロジェクトでは、全ファイルの診断に時間がかかります。--checkコマンドは複数のワーカープロセスを起動して並列処理を行い、診断時間を短縮します。本コマンドは各ワーカープロセスが実行する内部コマンドで、割り当てられたファイルの診断を実行し、結果を出力します。通常、ユーザーが直接このコマンドを実行することはありません。

**画面へのアクセス方法**：
本コマンドは、以下の方法でトリガーされます：
- --checkコマンドから自動的に起動される内部コマンド
- 直接実行: `lua-language-server --check_worker=<workspace_path>`（通常は使用しない）

**主要な操作・処理内容**：
1. ワークスペースパスとスレッドIDを受け取る
2. LSPクライアントエミュレータを初期化
3. ワークスペースの準備完了を待機
4. 診断レベルに応じてフィルタリング設定
5. 担当ファイルを順次診断
6. 結果をJSON/Pretty形式で出力
7. 診断結果に応じた終了コードを返す

**画面遷移**：
- 入力元：--checkコマンド（メインプロセス）
- 出力先：標準出力（stdout）および/またはJSONファイル

**権限による表示制御**：
特別な権限制御はありません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 74 | コマンドラインチェック | 主機能 | 診断チェックの並列ワーカープロセス |

## 画面種別

CLI（コマンドライン出力 - 内部使用）

## URL/ルーティング

- CLIオプション: `--check_worker=<workspace_path>`（内部使用）
- ハンドラファイル: `script/cli/check_worker.lua`
- 関連オプション:
  - `--thread_id`: ワーカーのスレッドID
  - `--checklevel`: 診断レベルの最小値
  - `--check_format`: 出力形式（json, pretty）
  - `--check_out_path`: JSON出力ファイルパス
  - `--quiet`: 進捗表示を抑制

## 入出力項目

### 入力パラメータ

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| --check_worker | string | Yes | チェック対象ワークスペースのパス |
| --thread_id | number | No | ワーカーのスレッドID（デフォルト: 1） |
| --checklevel | string | No | 診断レベルの最小値（デフォルト: Warning） |
| --check_format | string | No | 出力形式 json/pretty（デフォルト: pretty） |
| --check_out_path | string | No | JSON出力ファイルパス |
| --quiet | flag | No | 進捗表示を抑制 |

### 出力

| 項目名 | 型 | 説明 |
|--------|-----|------|
| stdout | text | Pretty形式の診断結果（quiet=false時） |
| file | JSON | JSON形式の診断結果（--check_out_path指定時） |
| exit code | number | 0: 診断パス、1: 診断エラーあり |

## 表示項目

### Pretty形式出力

| 項目名 | 表示内容 |
|--------|---------|
| ファイルパス | 相対パス:行番号:列番号（青色） |
| 重大度 | [Error]（赤）, [Warning]（黄）, [Information/Hint]（白） |
| メッセージ | 診断メッセージ |
| コード | (diagnostic_code)（マゼンタ） |
| 該当行 | ソースコードの該当行 |
| キャレット | 問題箇所を示す^記号（グレー） |

## イベント仕様

### 1-診断ワーカー実行

1. **パラメータ検証**: CHECK_WORKERの型確認
2. **パス正規化**: fs.canonical()でパスを正規化
3. **URI変換**: furi.encode()でURIに変換
4. **checklevel検証**: 有効な診断レベルか確認
5. **LSPクライアント初期化**: lclient():start()
6. **診断ハンドラ登録**: publishDiagnosticsハンドラを登録
7. **ワークスペース準備待機**: ws.awaitReady()
8. **診断レベル適用**: apply_check_level()
9. **ステータスダウングレード**: downgrade_checks_to_opened()
10. **ファイルリスト取得**: files.getChildFiles()
11. **ファイルリストソート**: ワーカー間で一貫した分散のため
12. **担当ファイル診断**: threadId条件でフィルタリング
13. **進捗表示**: 定期的に進捗を更新
14. **結果出力**: JSON/Pretty形式で出力
15. **終了コード返却**: エラーの有無に応じて0または1

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

本機能はデータの更新を行いません。

## メッセージ仕様

| メッセージID | 種別 | 表示条件 | メッセージ内容 |
|-------------|------|---------|--------------|
| CLI_CHECK_INITING | Info | 初期化中 | 初期化中メッセージ |
| CLI_CHECK_SUCCESS | Info | 診断成功（エラーなし） | 成功メッセージ |
| CLI_CHECK_RESULTS_OUTPATH | Info | JSON出力時 | 結果ファイルパス |
| CLI_CHECK_RESULTS_PRETTY | Info | Pretty出力時 | 結果サマリー |
| CLI_CHECK_ERROR_TYPE | Error | パラメータ型エラー | 型エラーメッセージ |
| CLI_CHECK_ERROR_URI | Error | URI解決失敗 | URIエラーメッセージ |
| CLI_CHECK_ERROR_LEVEL | Error | 不正なchecklevel | レベルエラーメッセージ |
| CLI_CHECK_PROGRESS | Info | 進捗表示 | エラー数とファイル数 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| CHECK_WORKERが文字列でない | エラーメッセージを表示して終了 |
| 不正な診断レベル | エラーメッセージを表示して終了 |
| URI解決失敗 | エラーメッセージを表示して終了 |
| ファイル読み込み失敗 | pcallで保護、処理継続 |

## 備考

- ファイルは `i % numThreads + 1 == threadId` の条件で各ワーカーに分散されます
- 診断結果はpublishDiagnosticsイベントで受信されます
- quietモードでは進捗表示とサマリーが抑制されます
- 空の結果は最終出力から除外されます
- 進捗表示は0.2秒間隔で更新されます

---

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

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

### 推奨読解順序

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

まず、診断結果で使用されるデータ構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | define.lua | `script/proto/define.lua` | DiagnosticSeverityの定義を理解 |
| 1-2 | diagnostic.lua | `script/proto/diagnostic.lua` | DiagnosticDefaultSeverityを理解 |

**読解のコツ**: 診断結果は`{ uri, diagnostics[] }`形式で、各diagnosticは`range`, `severity`, `code`, `message`を持ちます。

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

コマンドの起点を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | check_worker.lua | `script/cli/check_worker.lua` | runCLI関数（178-293行目） |

**主要処理フロー**:
1. **179行目**: 言語設定
2. **181-183行目**: スレッド情報取得
3. **185-188行目**: パラメータ型検証
4. **190-196行目**: パス正規化とURI変換
5. **198-202行目**: checklevel検証
6. **215-265行目**: LSPクライアントでの診断実行

#### Step 3: 診断レベル適用を理解する

apply_check_level()の実装を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | check_worker.lua | `script/cli/check_worker.lua` | apply_check_level関数（146-161行目） |

**主要処理フロー**:
- **149行目**: 現在の無効化設定を取得
- **150行目**: 重大度設定を取得
- **151-158行目**: チェックレベルより低い診断を無効化
- **160行目**: 更新した無効化設定を適用

#### Step 4: ファイル分散ロジックを理解する

ワーカー間のファイル分散を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | check_worker.lua | `script/cli/check_worker.lua` | ファイル処理ループ（249-261行目） |

**主要処理フロー**:
- **248行目**: ファイルリストをソート
- **249行目**: forループで各ファイルを処理
- **250行目**: `i % numThreads + 1 == threadId` で担当ファイルを判定
- **251行目**: 無視ファイルをスキップ
- **252行目**: ファイルを開いて診断実行

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

```
lua-language-server --check_worker=<path> --thread_id=N
    │
    └─ check_worker.lua:runCLI()
           │
           ├─ パラメータ検証
           │
           ├─ fs.canonical() & furi.encode()
           │
           ├─ lclient():start()
           │      │
           │      └─ client:registerFakers()
           │
           ├─ client:initialize()
           │
           ├─ client:register('publishDiagnostics')
           │
           ├─ provider.updateConfig()
           │
           ├─ ws.awaitReady()
           │
           ├─ apply_check_level()
           │      │
           │      └─ config.set('Lua.diagnostics.disable')
           │
           ├─ downgrade_checks_to_opened()
           │      │
           │      └─ config.set('Lua.diagnostics.neededFileStatus')
           │
           ├─ files.getChildFiles()
           │
           └─ [for each assigned file]
                  │
                  ├─ files.open()
                  │
                  ├─ diag.doDiagnostic()
                  │
                  └─ report_progress() [定期的]
```

### データフロー図

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

--check_worker=<path>   ───▶ check_worker.lua ───▶ stdout/file
--thread_id=N                    │
                                 ▼
                          パス正規化
                                 │
                                 ▼
                          lclient初期化
                                 │
                                 ▼
                          診断ハンドラ登録
                                 │
                                 ▼
                          ws.awaitReady()
                                 │
                                 ▼
                          apply_check_level()
                                 │
                                 ▼
                          files.getChildFiles()
                                 │
                                 ▼
                          担当ファイル選別
                          (i % N + 1 == threadId)
                                 │
                                 ▼
                          [for each file]
                                 │
                            ┌────┴────┐
                            ▼         ▼
                      files.open()   diag.doDiagnostic()
                                 │
                                 ▼
                          publishDiagnostics
                                 │
                                 ▼
                          results[uri]
                                 │
                            ┌────┴────┐
                            ▼         ▼
                      Pretty形式   JSON形式
                      (stdout)    (file)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| check_worker.lua | `script/cli/check_worker.lua` | ソース | ワーカーメインロジック |
| lclient.lua | `script/lclient.lua` | ソース | LSPクライアントエミュレータ |
| diagnostic.lua | `script/provider/diagnostic.lua` | ソース | 診断処理 |
| files.lua | `script/files.lua` | ソース | ファイル管理 |
| workspace.lua | `script/workspace/workspace.lua` | ソース | ワークスペース管理 |
| config.lua | `script/config/config.lua` | ソース | 設定管理 |
| define.lua | `script/proto/define.lua` | ソース | 診断重大度定義 |
| json-beautify.lua | `script/json-beautify.lua` | ソース | JSON整形 |
