メインコンテンツまでスキップ

診断を読む

人向けの check は診断コードを表示しない。出るのは本文だけで、BND04 のようなコードはどこにも現れない。索引や族の頁を引くには、まずコードを手に入れる。

コードを手に入れる

次のファイル (二室が角でしか触れていない) を検査する。

grid X 0 3600 7200
grid Y 0 4000 8000
level L1 0 h:2400 slab:150
space /L1/a room X1..X2 Y1..Y2
space /L1/b room X2..X3 Y2..Y3
boundary /L1/a /L1/b t:120

人向けの出力はこうなる。

✖ <absolute path>/bad.muro:line 6: The spaces do not touch, so no boundary can be derived: /L1/a | /L1/b

行頭の出所は解決済みの絶対パスである (ここでは <absolute path> と省略して示した)。合成したモデルでは、この出所は entry ではなくその診断を生んだ宣言が書かれているレイヤーを指す。

--json を付けると、同じ診断がコードつきで出る。

koyu check bad.muro --json
[
{
"code": "BND04",
"severity": "error",
"message": "The spaces do not touch, so no boundary can be derived: /L1/a | /L1/b",
"line": 6,
"file": "<absolute path>/bad.muro",
"path": [
"/L1/a",
"/L1/b"
]
}
]

コードが手に入ったら索引を引く。

Diagnostic の構造

--json が吐くのは Diagnostic の配列である。

interface Diagnostic {
code: DiagnosticCode;
severity: "error" | "warning";
message: string;
line?: number;
file?: string;
path?: string[];
related?: Array<{ line: number; file?: string }>;
}
フィールド必ずあるか中身
code必ず台帳の 65 コードのいずれか。領域2〜3字 + 2桁の連番
severity必ず"error""warning"コードの不変属性であって、場合によって変わらない
message必ず本文だけ。位置接頭辞 (ファイル:line N: ) を含まない
line位置を持つ診断のみ出所の行番号 (1始まり)。既定境界の導出のように、書かれた行を持たない診断では省略される
fileline があり、出所のレイヤーが分かるときそのレイヤーの解決済み絶対パス
path対象がパスを持つとき対象の空間・ゾーン・polygon のパス。境界に対する診断は両側のパスが入る
related関連位置があるとき重複の既出側、重なりの相手、影を作った先の宣言などの位置

message に位置が入らないのは、位置を別のフィールドが持つからである。エディタや CI は line / file を機械的に読み、人向けの check<file>:line <N>: を組み立てて本文の前に貼る。この二つは同じ本文を共有している。

related が付く例。重複した境界 (BND02) では、後から書いた側が診断の出所になり、既出側が related に入る。

[
{
"code": "BND02",
"severity": "error",
"message": "Duplicate boundary: /L1/a | /L1/b (first seen at <absolute path>/bad.muro:line 6)",
"line": 7,
"file": "<absolute path>/bad.muro",
"path": [
"/L1/a",
"/L1/b"
],
"related": [
{
"line": 6,
"file": "<absolute path>/bad.muro"
}
]
}
]

出所を持たない診断は無い。集合に対する診断 (「同じ空間対に二種類の境界が併存している」) でも、その集合を作った宣言のうち一本を line が指し、残りが related に入る。「どこかで矛盾している」とだけ言われても直す場所が無いからである。

severity と終了コード

severity意味checkcheck --jsoncheck --strict
error構成が成立していない111
warning疑わしい (成立はしている)001
(診断なし)000

警告も落としたいときは --strict を付ける。CI の門番に置くのはこちらである。--json--strict は同時に使える。

エラーが一件も無いとき、人向けの check は件数と、緑が何を意味するかを印字する。

✔ Consistent — 3 spaces / 3 boundaries
  Structural consistency only — architectural validity is what koyu validate says, separately

警告だけがあるときはこうなる (終了コードは 0、--strict を付けると 1)。

⚠ <absolute path>/warn.muro:line 6: The same pair of spaces carries both an edge-restricted and an unrestricted boundary (the segments overlap): /L1/a | /L1/b
✔ Consistent — 2 spaces / 2 boundaries (1 warning)
  Structural consistency only — architectural validity is what koyu validate says, separately

人向けの出力では警告が先、エラーが後に並ぶ。--json は severity で並べ替えず、後述の走査の順のまま返す。

並びは走査の順である

診断の並びは、コードの族ではなく走査した順で決まる。検査は決まった順に並んだ節から成り、節の粒度は走査単位であってコードの族ではない。一つの節が宣言を一周するあいだに複数のコードを出すなら、それらは走査のその場で隣り合って出る。境界の妥当性を見る節は境界を一本ずつ回り、その境界の線分・開口・seg について言うべきことを、そこでまとめて出す。

外壁に扉と seg を置いた二つの境界を検査すると、族ごとにまとまらず、境界ごとにまとまる。

grid X 0 3600 7200
grid Y 0 4000
level L1 0 h:2400 slab:150
space /L1/a room X1..X2 Y1..Y2
space /L1/b room X2..X3 Y1..Y2
space /out exterior
boundary /L1/a /out t:150
  door w:800
  seg w:800 spec:X
boundary /L1/b /out t:150
  door w:800
  seg w:800 spec:X

出るコードと行はこの順である。

OPN05  line 8
SEG05  line 9
OPN05  line 11
SEG05  line 12

この性質は意図されたものである。一つの境界について言うべきことが一箇所に固まるので、上から順に直していける。コードの族でまとめると、同じ境界の話が出力の端と端に分かれる。

母集団は「書かれた宣言」である

診断が数え上げるのは、導出された結果ではなく書かれた宣言である。同じ階の別の柱宣言が一本でも柱を立てたからといって、一本も立たない宣言が黙って通ることはない。属性についても同じで、解釈される属性は値まで検査される — 書いたのに解釈されなかった値が、黙って既定へ落ちることはない。

構文エラーは SYN01 に写る

ファイルがモデルにならなかったときは、意味の検査が一件も走っていない。--json を付けたときだけ、有効な JSON を返すために、その例外が SYN01 一件に写される。

grid X 0 3600
grid Y 0 4000
level L1 0 h:2400 slab:150
space /L1/a room X1..X9 Y1..Y2
koyu check broken.muro --json
[
{
"code": "SYN01",
"severity": "error",
"message": "Undefined grid line name: X9",
"line": 4,
"file": "<absolute path>/broken.muro"
}
]

--json を付けない check と、他のすべてのサブコマンドは、例外をそのまま ✖ <出所>:line N: <本文> として印字し、終了コード1で終わる。構文エラーが一つでもあると、check --json の結果は SYN01 が1件だけになる。

プログラムから読む

checkDiagnostics(model)Diagnostic[] を返す。check(model) は互換層で、{ errors, warnings }文字列の組を返す — こちらの文字列には位置接頭辞が付いている。コードが要るなら checkDiagnostics を使う。

DIAGNOSTIC_CODES は台帳そのもので、コードから規範の severity を引ける。欠番の綴りを引くと undefined が返る。

import { checkDiagnostics, DIAGNOSTIC_CODES } from "koyu";

for (const d of checkDiagnostics(model)) {
console.log(d.code, d.severity, d.line, d.message);
}

DIAGNOSTIC_CODES["BND04"]; // "error"
DIAGNOSTIC_CODES["BND07"]; // undefined — 欠番

欠番の一覧は欠番の診断コードにある。