Summary
Nine languages still spell their wrapper kind set twice — once in the
peel that unwraps it, once restated in <lang>_count_condition. Three
languages had exactly that shape and all three produced a real bug; the
remaining nine have the same hazard with no present defect.
Where
ruby, go, rust, python, php, perl, cpp, lua, java — each
restates the wrapper list in src/metrics/abc/<lang>.rs's
<lang>_count_condition rather than asking its peel.
The fixed three, and what the duplication cost
| Language |
Issue |
What the two lists disagreeing produced |
| Kotlin |
#1459 |
unary_expression routed to the slot while the peel handled only half of it |
| Groovy |
#1466 |
the slot claimed every UnaryExpression; the peel descended only !-prefixed ones |
| C# |
#1463 |
postfix_unary_expression in neither list — silently scored nothing |
Three for three. The pattern is:
if matches!(kind, <lang>_bool_terminal_kinds!()) { +1 }
else if matches!(kind, Paren | Unary) { recurse } // <- restated
// anything else -> silently nothing
The third outcome is the defect, and the restated list is what lets the two
halves drift into it.
The fix shape
kotlin_count_condition (src/metrics/abc/kotlin.rs) is the model: it asks
the peel whether it handles the node —
kotlin_wrapper_operand(condition).is_some() — instead of restating kinds,
so the caller's "is this mine" predicate and the helper cannot disagree.
groovy_wrapper_operand and csharp_wrapper_operand now follow it.
Scope note
No present defect is known in the nine — their lists agree today. This is
a drift-hazard removal, so it is worth doing as one mechanical pass with
per-language measurement rather than piecemeal. Measure each language's
wrapper spellings (b, (b), !b, !!b, (b!), language-specific forms)
in both the if predicate and the && chain before and after; a construct
whose score changes means the two lists already disagreed and you have
found a latent bug rather than a refactor.
Per #1466's recorded decision, do not extract a shared cross-language
helper: the three fixed languages share the Option<(Node, bool)> shape
and nothing else, and a common function would need the wrapper kind set,
operand accessor, proves-boolean flag and parent seed all as parameters.
Related
Summary
Nine languages still spell their wrapper kind set twice — once in the
peel that unwraps it, once restated in
<lang>_count_condition. Threelanguages had exactly that shape and all three produced a real bug; the
remaining nine have the same hazard with no present defect.
Where
ruby,go,rust,python,php,perl,cpp,lua,java— eachrestates the wrapper list in
src/metrics/abc/<lang>.rs's<lang>_count_conditionrather than asking its peel.The fixed three, and what the duplication cost
unary_expressionrouted to the slot while the peel handled only half of itUnaryExpression; the peel descended only!-prefixed onespostfix_unary_expressionin neither list — silently scored nothingThree for three. The pattern is:
The third outcome is the defect, and the restated list is what lets the two
halves drift into it.
The fix shape
kotlin_count_condition(src/metrics/abc/kotlin.rs) is the model: it asksthe peel whether it handles the node —
kotlin_wrapper_operand(condition).is_some()— instead of restating kinds,so the caller's "is this mine" predicate and the helper cannot disagree.
groovy_wrapper_operandandcsharp_wrapper_operandnow follow it.Scope note
No present defect is known in the nine — their lists agree today. This is
a drift-hazard removal, so it is worth doing as one mechanical pass with
per-language measurement rather than piecemeal. Measure each language's
wrapper spellings (
b,(b),!b,!!b,(b!), language-specific forms)in both the
ifpredicate and the&&chain before and after; a constructwhose score changes means the two lists already disagreed and you have
found a latent bug rather than a refactor.
Per #1466's recorded decision, do not extract a shared cross-language
helper: the three fixed languages share the
Option<(Node, bool)>shapeand nothing else, and a common function would need the wrapper kind set,
operand accessor, proves-boolean flag and parent seed all as parameters.
Related
b!scores no condition #1463 — the three landed instances.