Skip to content

Commit 89c4e22

Browse files
hyperpolymathclaude
andcommitted
fix(walker): catch Js.Exn in pattern position + exempt phase2c.res fixture
Two bugs blocked Phase 2c parity tests + governance: 1. `walker-phase2c-parity / untyped-exception on lines 19/22/28` failed with missing=[22]. Tree-sitter labels `Js.Exn.Error(_)` in catch-arm pattern position with a different node type than the typed branches ([member_expression]/[value_identifier_path]) the detector matches. Add a leaf-only text fallback ( <=32 chars, no children) so any small leaf carrying `Js.Exn` / `Promise.catch` flags too. Dedupe by (kind, line) collapses same-line duplicates against the parent try_expression hit, so no over-reporting. 2. `governance / Language / package anti-pattern policy` failed with "❌ ReScript files detected" for the new phase2c.res fixture. The walker exists precisely to detect anti-patterns in .res files, so the fixture is intentional. Side-channel exemption in `.hypatia-ignore` (same pattern as the existing `sample.res` line) per `feedback_inline_pragma_vs_snapshot_test`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 5a26b51 commit 89c4e22

2 files changed

Lines changed: 17 additions & 1 deletion

File tree

.hypatia-ignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@
2323
# exemption avoids touching the file content. See feedback memory
2424
# `feedback_inline_pragma_vs_snapshot_test` for the general principle.
2525
cicd_rules/banned_language_file:tools/res-to-affine/test/fixtures/sample.res
26+
cicd_rules/banned_language_file:tools/res-to-affine/test/fixtures/phase2c.res

tools/res-to-affine/walker.ml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,22 @@ let detect_untyped_exception ~source acc node =
421421
in
422422
if hits_js_exn || hits_promise_catch then push acc
423423
else acc
424-
| _ -> acc
424+
| _ ->
425+
(* Tree-sitter labels module paths differently depending on syntactic
426+
position — `Js.Exn.Error(_)` in a catch-arm pattern is not a
427+
[member_expression]/[value_identifier_path], so the typed branches
428+
above miss it. Fall back to a tight leaf-only text match so the
429+
pattern still flags. The master walker's [dedupe] collapses any
430+
same-line duplicate against the [try_expression] hit. *)
431+
if node.children = [] then
432+
let text = node_text ~source node in
433+
if String.length text <= 32
434+
&& (starts_with "Js.Exn" text
435+
|| text = "Promise.catch"
436+
|| ends_with ".Promise.catch" text)
437+
then push acc
438+
else acc
439+
else acc
425440

426441
(* ---- mutable-global: top-level [let x = ref(...)] or top-level [:=] ---- *)
427442

0 commit comments

Comments
 (0)