1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Per-language `kind_id`-set and alias macros.
//
// Split out of `macros.rs` (now `macros/mod.rs`) so that file is no
// longer dominated, by line count, by these ~20 near-identical
// match-pattern bundles (which sank its maintainability index). These
// macros MUST stay `macro_rules!`: each expands to a `|`-separated
// list of per-language `kind_id` enum variants consumed inside
// `matches!()` at the call site, where a `use <Lang>::*` glob brings
// the variants into scope. They carry no logic -- only the variant
// membership -- and every per-call grammar rationale comment travels
// with its macro (see `.claude/rules/macro-comments.md`).
//
// Re-exported below via `pub use` and again from
// `macros/mod.rs`, so every existing `crate::macros::<name>` import in
// `checker.rs`, `metrics/npa.rs`, and `metrics/abc.rs` keeps resolving
// unchanged.
// Aliased C# `kind_id` unions. The C# tree-sitter grammar emits multiple
// numbered variants for several rules (lesson #2 in
// `docs/development/lessons_learned.md`); centralizing the alias sets
// here keeps every match site in lockstep, so a future grammar bump that
// adds another numbered variant is a one-line edit instead of a scatter
// of 4-5 sites.
// Terminal-bool operand kinds for the Phase-2 unary-conditional walker
// (issue #403). Each `<lang>_bool_terminal_kinds!()` macro lists the
// expression kinds whose evaluated value is implicitly boolean in an
// `if` / `while` / `&&` / `||` operand slot for that language.
//
// Only Go still pays a slot through such a list. Every other language's
// slot pays one condition unless an arm inside the predicate already did
// (`count_boolean_slot` in `src/metrics/abc.rs`, #1526; Kotlin #1533),
// because each list kept missing kinds — `-x`, `x + 1`, `this`, `*p` —
// that scored 0 against a cyclomatic decision of 1.
//
// **These sets hold operands, never operators** (#1461). Membership is
// slot-scoped by construction — a kind here scores only where a walker
// consults the set, which is inside a boolean slot — and that is the
// right scope for a *value*, whose truthiness is interesting only
// because the slot reads it. It is the wrong scope for a **relational
// operator**, which Fitzpatrick Rule 5 scores by use: `a == b` counts
// wherever it is written, so `a is String` must too. The type-test and
// membership productions a grammar spells as their own node sat here
// until #1461 and so scored one inside a predicate and zero outside
// it, while the comparison token beside them scored in both. Each now
// has an unconditional arm in its language's ABC `compute` and is
// listed in neither place twice — which would score it twice
// (`.claude/rules/grammar-dispatch.md` §5).
//
// The line is the construct's *value*, not its type. A cast, a type
// assertion and an `@available` query all yield something the slot
// then reads as a boolean, so they stay; a type test yields the
// comparison's own result, so it does not.