# 帳票設計書 3-check.json

## 概要

本ドキュメントは、Lua Language ServerのCLI診断機能によって出力される`check.json`ファイルの帳票設計を定義する。この帳票は、Luaソースコードの静的解析（診断）結果をJSON形式で構造化して出力し、エラー・警告・情報・ヒントレベルの問題を報告する。

### 本帳票の処理概要

本帳票は、Lua Language ServerのCLIコマンド`--check`オプションによって生成される診断レポートであり、プロジェクト全体のコード品質問題を一括で検出・報告する。

**業務上の目的・背景**：Luaプロジェクトにおいて、CIパイプラインでの自動コード検査、コードレビュー前の品質チェック、リリース前の品質ゲート判定に活用される。手動での目視確認では見落としがちな問題を網羅的に検出する。

**帳票の利用シーン**：CI/CDパイプラインでの自動品質チェック時、プルリクエストのマージ前検査時、大規模リファクタリング後の影響確認時、またコードベース全体の品質状況把握時に利用される。

**主要な出力内容**：
1. ファイルごとの診断結果グループ
2. 各診断の位置情報（行・列、範囲）
3. 診断の重大度（Error/Warning/Information/Hint）
4. 診断コード（問題の種類識別子）
5. 診断メッセージ（問題の詳細説明）

**帳票の出力タイミング**：CLIから`--check`オプションを指定して実行した際に出力される。デフォルトでは`LOGPATH/check.json`に出力、`--check_out_path`で任意のパスを指定可能。

**帳票の利用者**：開発者、CI/CDシステム、コードレビュアー、品質管理担当者

## 帳票種別

診断レポート（静的解析結果）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| CLI | コマンドラインインターフェース | `lua-language-server --check=<path>` | --checkオプション指定 |
| CLI | コマンドラインインターフェース | `lua-language-server --check=<path> --check_out_path=<output>` | 出力先指定 |
| CLI | コマンドラインインターフェース | `lua-language-server --check=<path> --check_format=json` | JSON形式指定 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON |
| 用紙サイズ | N/A（データファイル） |
| 向き | N/A |
| ファイル名 | `check.json`（デフォルト）または`--check_out_path`で指定 |
| 出力方法 | ファイル出力 |
| 文字コード | UTF-8 |

### JSON固有設定

| 項目 | 内容 |
|-----|------|
| インデント | スペース4文字（beautify適用） |
| トップレベル構造 | オブジェクト（ファイルURIをキーとする） |
| 配列値 | 診断オブジェクトの配列 |

## 帳票レイアウト

### レイアウト概要

JSONファイルはファイルURIをキーとするオブジェクトで構成される。各キーの値は診断オブジェクトの配列。

```json
{
  "file:///path/to/file1.lua": [
    {
      "range": {
        "start": {"line": 0, "character": 0},
        "end": {"line": 0, "character": 10}
      },
      "severity": 1,
      "code": "undefined-global",
      "source": "Lua Diagnostics.",
      "message": "Undefined global `foo`."
    },
    ...
  ],
  "file:///path/to/file2.lua": [...]
}
```

### ヘッダー部

JSON構造のトップレベルキーがファイルURIとなる。

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ファイルURI | 診断対象ファイルの識別子 | params.uri | file:///形式 |

### 明細部

各診断オブジェクトのフィールド:

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | range.start.line | 問題開始行（0-indexed） | converter.packRange() | 整数 |
| 2 | range.start.character | 問題開始列（0-indexed） | converter.packRange() | 整数 |
| 3 | range.end.line | 問題終了行（0-indexed） | converter.packRange() | 整数 |
| 4 | range.end.character | 問題終了列（0-indexed） | converter.packRange() | 整数 |
| 5 | severity | 重大度 | define.DiagnosticSeverity | 1=Error, 2=Warning, 3=Info, 4=Hint |
| 6 | code | 診断コード | diag.code | 文字列（例: undefined-global） |
| 7 | source | 診断ソース | lang.script.DIAG_DIAGNOSTICS | "Lua Diagnostics." |
| 8 | message | 診断メッセージ | diag.message | 文字列 |
| 9 | tags | 診断タグ | diag.tags | 配列（オプション） |
| 10 | data | 追加データ | diag.data | 任意（オプション） |
| 11 | relatedInformation | 関連情報 | diag.related | 配列（オプション） |

### フッター部

JSON形式のためフッター部は存在しない。

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| CHECKパス | 診断対象ディレクトリ | Yes |
| 診断有効 | Lua.diagnostics.enable = true | Yes |
| ファイル対象 | ws.isIgnored(uri) = false | Yes |
| 重大度レベル | CHECKLEVEL以下の重大度 | No（デフォルト: Warning） |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ファイルパス | 昇順（ファイル処理順） |
| 2 | 診断出現順 | 出現順 |

### 改ページ条件

N/A（データファイルのため改ページなし）

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを使用せず、診断エンジンの解析結果を参照する。

| データソース | 用途 | 取得方法 |
|-------------|------|---------|
| files | ファイル一覧 | files.getChildFiles(rootUri) |
| diag.doDiagnostic() | 診断実行 | provider.diagnostic |
| publishDiagnostics | 診断結果受信 | client:register() |

### テーブル別参照項目詳細

#### 診断結果

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| params.uri | ファイルキー | なし | file:///形式 |
| params.diagnostics | 診断配列 | なし | LSP診断形式 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 位置変換 | converter.packRange(state, start, finish) | N/A | 内部位置からLSP位置へ変換 |
| 重大度判定 | define.DiagnosticSeverity[severity] | N/A | 文字列から数値へ変換 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[CLI実行 --check=path] --> B{NUM_THREADS > 1?}
    B -->|Yes| C[複数ワーカープロセス起動]
    B -->|No| D[単一ワーカーで実行]
    C --> E[各ワーカーがcheck_worker.runCLI実行]
    D --> E
    E --> F[lclient初期化]
    F --> G[workspace準備待機]
    G --> H[publishDiagnosticsハンドラ登録]
    H --> I[ファイル一覧取得]
    I --> J{各ファイルをループ}
    J --> K[files.open(uri)]
    K --> L[diag.doDiagnostic(uri)]
    L --> M[publishDiagnosticsで結果受信]
    M --> N[results[uri]に格納]
    N --> J
    J -->|完了| O{複数スレッド?}
    O -->|Yes| P[部分結果をJSONで保存]
    O -->|No| Q[結果をマージ]
    P --> R[親プロセスで全結果マージ]
    R --> Q
    Q --> S[jsonb.beautifyでJSON整形]
    S --> T[util.saveFileで書き込み]
    T --> U[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| パス不正 | CHECK_WORKERが文字列でない | CLI_CHECK_ERROR_TYPE | 正しいパスを指定 |
| URI変換失敗 | furi.encodeが失敗 | CLI_CHECK_ERROR_URI | 有効なパスを指定 |
| チェックレベル不正 | CHECKLEVELが不正 | CLI_CHECK_ERROR_LEVEL | Error/Warning/Information/Hintを指定 |
| ファイル読み込み失敗 | ファイルオープン失敗 | （内部エラー） | ファイル権限確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | プロジェクト規模依存（数十〜数万診断） |
| 目標出力時間 | プログレスバー表示あり、並列実行対応 |
| 同時出力数上限 | NUM_THREADSで指定（デフォルト1） |

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

- 診断メッセージにはソースコードの一部が含まれる可能性があるため、機密コードの漏洩に注意
- 出力ファイルパスの検証により、意図しないディレクトリへの書き込みを防止

## 備考

- `--check_format=pretty`でコンソールに整形出力も可能
- `--quiet`オプションで進捗表示を抑制可能
- 複数スレッド実行時は各スレッドが部分結果を出力し、親プロセスでマージ
- 終了コードは診断結果により0（成功）または1（問題あり）

---

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

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

### 推奨読解順序

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

出力されるJSONの構造（LSP診断形式）を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | define.lua | `script/proto/define.lua` | DiagnosticSeverity定義 |
| 1-2 | diagnostic.lua | `script/provider/diagnostic.lua` | buildDiagnostic関数（86-123行目）で出力構造を理解 |

**読解のコツ**: LSP仕様のDiagnostic構造に準拠。range, severity, code, message, tagsが主要フィールド。

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

CLIからの処理フローを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | init.lua | `script/cli/init.lua` | CHECK/CHECK_WORKERの分岐（11-19行目） |
| 2-2 | check.lua | `script/cli/check.lua` | runCLI関数（50-118行目）が親プロセス処理 |
| 2-3 | check_worker.lua | `script/cli/check_worker.lua` | runCLI関数（178-293行目）がワーカー処理 |

**主要処理フロー**:
1. **check.lua 50-79行目**: 複数スレッド起動処理
2. **check.lua 85-116行目**: 結果マージ処理
3. **check_worker.lua 215-265行目**: 診断実行ループ
4. **check_worker.lua 223-229行目**: publishDiagnosticsハンドラ登録

#### Step 3: 診断実行処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | check_worker.lua | `script/cli/check_worker.lua` | ファイルループ（246-261行目） |
| 3-2 | diagnostic.lua | `script/provider/diagnostic.lua` | doDiagnostic関数（281-358行目） |

**主要処理フロー**:
- **251行目**: `files.open(uri)`でファイルオープン
- **252行目**: `diag.doDiagnostic(uri, true)`で診断実行
- **325-330行目**: `proto.notify('textDocument/publishDiagnostics', ...)`で結果通知

#### Step 4: 結果出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | check_worker.lua | `script/cli/check_worker.lua` | 結果保存（275-281行目） |
| 4-2 | check.lua | `script/cli/check.lua` | マージ・保存（85-116行目） |

**主要処理フロー**:
- **check_worker.lua 280行目**: `util.saveFile(outpath, jsonb.beautify(results))`
- **check.lua 104行目**: `util.saveFile(outpath, jsonb.beautify(mergedResults))`

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

```
script/cli/init.lua
    │
    ├─ CHECK分岐
    │      └─ require 'cli.check'.runCLI()
    │             │
    │             ├─ subprocess.spawn() × NUM_THREADS
    │             │      └─ check_worker.runCLI()
    │             │
    │             └─ 結果マージ・保存
    │
    └─ CHECK_WORKER分岐
           └─ require 'cli.check_worker'.runCLI()
                  │
                  ├─ lclient():start()
                  │      │
                  │      ├─ client:initialize()
                  │      │
                  │      ├─ client:register('publishDiagnostics')
                  │      │      └─ results[uri] = diagnostics
                  │      │
                  │      ├─ ws.awaitReady()
                  │      │
                  │      └─ for uri in uris do
                  │             ├─ files.open(uri)
                  │             └─ diag.doDiagnostic(uri)
                  │                    │
                  │                    └─ script/provider/diagnostic.lua
                  │                           │
                  │                           ├─ syntaxErrors()
                  │                           ├─ core.diagnostics()
                  │                           └─ proto.notify('publishDiagnostics')
                  │
                  └─ util.saveFile(jsonb.beautify(results))
```

### データフロー図

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

Luaソースファイル群 ──▶ parser解析
                              │
                              ▼
                        構文エラー検出
                              │
                              ▼
                      意味解析・診断実行
                              │
                              ▼
                    publishDiagnostics通知
                              │
                              ▼
                      results[uri]に格納
                              │
                              ▼
                      jsonb.beautify()
                              │
                              ▼
                    ────────────────────▶ check.json
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| check.lua | `script/cli/check.lua` | ソース | 複数スレッド管理、結果マージ |
| check_worker.lua | `script/cli/check_worker.lua` | ソース | 診断実行、結果収集 |
| init.lua | `script/cli/init.lua` | ソース | CLIオプション分岐 |
| diagnostic.lua | `script/provider/diagnostic.lua` | ソース | 診断エンジン統合 |
| init.lua | `script/core/diagnostics/init.lua` | ソース | 各診断モジュール呼び出し |
| define.lua | `script/proto/define.lua` | ソース | DiagnosticSeverity定義 |
| converter.lua | `script/proto/converter.lua` | ソース | 位置変換 |
| json-beautify.lua | `script/json-beautify.lua` | ソース | JSON整形 |
| utility.lua | `script/utility.lua` | ソース | ファイル保存 |
