feat(parser): add JuliaSyntax -> CSTParser compatibility layer#118
Draft
pfitzseb wants to merge 51 commits into
Draft
feat(parser): add JuliaSyntax -> CSTParser compatibility layer#118pfitzseb wants to merge 51 commits into
pfitzseb wants to merge 51 commits into
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Implements leaf-flattening pass that converts JuliaSyntax GreenNode tree to flat vector of non-trivia tokens with folded trivia spans. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the flat Task 3 build_cst with a recursive assemble/assemble_form pass over the green tree, computing spans from absolute leaf positions. Covers toplevel/file wrapping (incl. semicolon-joined statement sequences, which drop `;` into the preceding statement's fullspan), infix and prefix calls, binary `=`, `begin...end` blocks, and parenthesized expressions. Also folds quoted-literal merging into the recursive walk so string/char oracle parity keeps holding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Adds check_spans (EXPR fullspan/span bookkeeping invariant, layout- independent so it holds even for broken code) and the CSTCorpus test module, which diffs converter output against CSTParser.parse per-file and writes a markdown report grouped by diff signature plus the accumulated UNHANDLED_KINDS. Also fixes the AT_SIGN/ATSIGN mismatch between generic_form's punctuation-trivia list and terminal_expr's actual output, and closes two terminal-completeness gaps found while getting the smoke test green: JuliaSyntax K"error" (zero-width diagnostic markers in broken code, now an :errortoken leaf) and the MacroName/StringMacroName/ CmdMacroName kinds (mapped to :IDENTIFIER, matching CSTParser, which has no separate concept for them). Baseline corpus run over src/ (65 files): 0 passed, 61 failed, 4 errored. Expected at this stage -- the converter only implements file/toplevel/call/=/block/parens + terminals, so every real file falls through generic_form's fallback layout. Full report and top diff signatures in .superpowers/sdd/task-5-report.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds assemble_form branches for function/struct/abstract/primitive/macro/ module definitions, where-clauses, ::/<: declarations, -> and short-form `=` function defs (with implicit block-wrap), const/global/local, and call's parameters/kwarg handling. Includes the rider fix to check_spans (recurse into EXPR-headed x.head). cst-conv filter: 80/80 passing (was 59; +21 new definitions snippets). Corpus (src/, 65 files): 0/65 passed, same as baseline (still >= baseline); UNHANDLED_KINDS shrank 52 -> 41. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
…uble block wrap The `;` width before call kwargs now folds onto the leaf immediately preceding it by position (via new Cursor terminals/kid_ranges) and its parent chain, instead of descending args[end] — which missed trivia leaves like closing parens/brackets. Explicit begin-end bodies of `->` and short-form `=` defs are no longer wrapped in a second block. cst-conv filter: 87/87 (was 80; +7 review repros). Corpus: 0/65, unchanged from baseline. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
…p trivia The K"parameters" branch now folds its own `;` width (generic widen_at_leaf! + Cursor.trim applied by assemble), so the span invariant holds under tuple/dotcall/macrocall/curly parents, not just calls. Sibling `;` groups nest recursively per the oracle (merge_params!, with CSTParser's stored-last-arg span convention). The toplevel `;` fold now widens the preceding statement's rightmost leaf chain, not just its root. Empty parameters groups get trivia === nothing. Adds a src/-wide check_spans sweep to the invariants testitem. cst-conv filter: 157/157. Corpus: 0/65, unchanged from baseline; invariant sweep 0 failures (fixes src/StaticLint/includes.jl hit). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Adds dotcall, getfield (with quotenode), curly, macrocall (with @-name fusion and string/cmd-macro name mangling), do-blocks, splat, and bare-type 2-kid ::. Fixes a pre-existing bug where block's `;` was kept as trivia instead of folded away like toplevel's. Corpus: 0/65 -> 3/65 (first real passes); cst-conv suite: 157 -> 184 passing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
The second of two adjacent `;` folded its width onto the first (already dropped) `;` leaf — an orphan EXPR — losing the width and breaking the childsum invariant in block, toplevel, and parameters folds. New fold_semi! walks back past dropped separators; empty parameters groups from bare extra `;` now collapse away like the oracle's. Suite 189/189; corpus unchanged at 3/65; src/ sweep 0 invariant failures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
if/elseif, ternary, while, for (+ iteration specs and cartesian_iterator), try/catch/finally/else, let, return/break/continue, tuple/vect/hcat/vcat/ ncat/nrow, comprehension/generator/filter, and a paren-block special case. Also fixes a pre-existing K"call" gap (parenless prefix-op calls like `!x` kept empty trivia instead of nothing) found via corpus probing. cst-conv suite: 225/225 (was 189). Corpus: 4/65 (was 3/65). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
…ariant, flatten - K"?" reuses the kind for nested composite ternaries; guard trivia filing with the same leaf check as if/elseif (args === nothing). - New Cursor.grow_span (span-only, clamped at fullspan, same set/apply/reset lifecycle as trim/trim_span): bare return's span reaches fullspan via its synthetic NOTHING arg, and a trivia-less enclosing block is measured to that arg too (grow_span_to_last_arg!). - check_spans: skip the childsum check for childless nodes (bare matrix cells carry width with empty args/trivia); matrix literals added to the invariant testitem. - Multi-for generators: oracle nests them inverted under :flatten wrappers with discontiguous hand-built spans; previous output broke check_spans. cst-conv suite: 236/236 (was 225). Corpus: 4/65 (unchanged). Sweep clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Clears the converter's last crashing inputs (triple-quoted strings, cmd literals/macros) and the biggest remaining oracle-diff bucket (compound assignment, short-circuit, dotted ops, comparison chains, juxtaposition). Test: cst-conv filter 276/276 (was 236 before this task). Corpus: total=65, passed=8 (was 4), errored=0 (was 4) — no more crashing inputs. No gate snippet needed @test_broken; two non-gate corpus findings recorded in cst-converter-divergences.md (cmd $(...) re-scan approximation, pre-existing raw/regex string unescape bug). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Review round-2 fixes: - Macro-wrapped strings (raw""/r""/b"") carry RAW_STRING_FLAG on the K"string" node — gate the escape pipeline on it, applying only CSTParser's unescape_prefixed (backslash-run halving before quote/end), matching the oracle's prefixed path exactly. Fixes val corruption for r"\d+", raw"a\nb", b"\x00", r"[/\\]+" (real corpus hit in compat.jl). - A BARE string literal as the whole $(...) subexpression keeps its :string wrapper in CSTParser (explicit re-wrap in parse_string_or_cmd); undo our single-chunk collapse at both interp sites (string parens path and the cmd $-rescan). Test: cst-conv filter 286/286 (10 new snippets). Corpus: total=65, passed=9 (was 8), errored=0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
…us burn-down Adds branches for using/import/importpath/as/doc/quote(block+colon)/export, tuple/vect/ref/braces/typed_comprehension/typed_hcat/vcat/ncat, var"...", dotted comparison fusion, and fixes: macrocall args keep '=' as assignment, matrix composite cells get empty trivia, nested where, local/global commas, word-operator quotenodes, file-level trailing ';' span, bare-return span growth in short-circuit/'='/toplevel, empty-body elseif span, qualified macrocall span, leading-';' NOTHING placeholder. Corpus: package src/ 65/65 identical to oracle (was 9/65); depot 1037/1161 (was 202/1161, 40 errored). cst-conv suite 371/371. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, vect assignment - prefix operator applied to a single parenthesized arg unwraps to a call (except -/!/~ which keep the bracketed operand) - K"inert" interpolated getfield field names → quotenode - Float32 literals mapped to :FLOAT - word operators (in/isa/where) in selective imports and importpath → OPERATOR - vect elements keep = as assignment (like tuples) Corpus: depot 1086/1161 (was 1037), 1 errored (JuliaSyntax parser overflow). cst-conv suite 384/384. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…macrocall semicolon span - explicit for/while branches (generic_form misfiled keyword-kinded conditions) - begin as an index → BEGIN literal (mirrors end→END); quoted field/symbol stays IDENTIFIER - matrix row span measured to last cell (handles whitespace before ;) - return-type-annotated short function defs wrap body in a block - var"..." quoted as a symbol → quotenode - bare @m macrocall (NOTHING last arg) grows span when a ; folds onto it Corpus: depot 1111/1161, src 65/65. cst-conv suite 400/400. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- :.& etc. fuse the dotted operator to one OPERATOR inside a quotenode - -/!/~ with a directly-parenthesized operand (macro/function defs) keep it as brackets Corpus: depot 1114/1161, src 65/65. cst-conv suite 405/405. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… fresh precompile terminals.jl uses Cursor in method signatures (collect_quoted_pieces/assemble_quoted); it was included before assembly.jl (which defines Cursor), which fails a cold precompile. A stale cache had masked it. Reorder so the type is bound first. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…onst nesting, N-ary juxtaposition Corpus: depot 1120/1161, src 65/65. cst-conv suite 413/413. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Corpus: depot 1128/1161, src 65/65. cst-conv suite 418/418. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…icolon fold Register the trailing chunk at the close leaf's terminal slot so a ;-fold onto an interpolated string keeps childsums balanced (was breaking check_spans). Corpus: depot 1133/1161, src 65/65. cst-conv suite 421/421. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tration for folds Fixes check_spans failures on 'let x=1; y end' (semicolon separator was dropped) and '(Base.@m; x)' (fused qualified macro name not registered for the fold). Corpus: depot 1137/1161, src 65/65, 0 check_spans failures. cst-conv suite 426/426. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ti-row matrix) Corpus: depot 1143/1161, src 65/65. cst-conv suite 429/429. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Corpus: depot 1144/1161, src 65/65. cst-conv suite 432/432. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Corpus: depot 1145/1161, src 65/65. cst-conv suite 435/435. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ion defs Corpus: depot 1147/1161, src 65/65. cst-conv suite 440/440. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ng semicolon Corpus: depot 1148/1161, src 65/65. cst-conv suite 442/442. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Corpus: depot 1150/1161, src 65/65. cst-conv suite 443/443. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n malformed input Corpus: depot 1150/1161, src 65/65. cst-conv suite 445/445. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s-var stays block) Corpus: depot 1152/1161, src 65/65. cst-conv suite 447/447. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Corpus: depot 1153/1161, src 65/65. cst-conv suite 449/449. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Depot corpus 1153/1161 (was 202), package src 65/65 (was 9), 0 check_spans failures; 4 documented parser divergences + 3 context-dependent cases remain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ast arg) Closes inherited deferred items 'begin return; end' and 'f(x) do y; return; end'. Corpus: depot 1153/1161, src 65/65, 0 check_spans failures. cst-conv suite 451/451. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…fix-op call unwrap Round-2 review fixes: - a parenless macrocall with a real last arg grows its span to that arg, so the qualified-macrocall span quirk propagates through nesting (x = @eval M.@m(a)); gated on last(args).fullspan != 0 so bare unqualified macrocalls (@run_package_tests) keep the normal exclusion - .+(x)/.!(x) unwrap a parenthesized operand like +(x) (no -/!/~ exception for dotted ops); .+(a,b) fuses the dotted-op callee to one OPERATOR - divergence log: script.jl reduced to 'struct S\nend;1' statement-group split (accept drift); tokenize_utils StackOverflow flagged as Task 12 backend-flip liability; broadcast.jl reviewer-confirmed context-dependent Corpus: depot 1154/1161 (blas.jl flipped), src 65/65, check_spans sweep clean. cst-conv suite 456/456. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
No oracle equality for broken code; contract is never throw, spans tile, error subtrees stay traversable. Adds the K"error" non-terminal branch to assemble_form, a zero-width-leaf fallback in terminal_expr, and fixes 8 crash/childsum bugs surfaced by prefix-sweeping the converter's own source files: repeated "@"+name macro-fusion crashes on a missing/errored macro name, module/struct catch-all clobbering the real name on a trailing error marker, an under-bounded K"parens" shape, an unbounded interpolation scan, and unbounded merge_quoted/merge_var closing-quote scans that could run past their own node into a sibling's leaves. Adds a general patch_dropped_width! safety net for any remaining childsum shortfall. Gates: 12 brief snippets + 3 degenerate whole-file cases all pass (never-throw, fullspan tiles, check_spans clean, walk-traversable). cst-conv suite 510/510 (was 456). src corpus 65/65, depot corpus 1154/1161 (both unchanged). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Error kids inside a K"string" node (invalid escape, missing-close marker) fell into collect_quoted_pieces' close-quote branch, which never resets have_run — a second visit re-emitted the same content run as an overlapping chunk (children sum > fullspan, found by a reviewer prefix sweep over depot files with triple-quoted docstrings). Error kids now extend the literal content run instead, with a synthesized zero-width close when no closing quote exists; the close branch resets have_run. Also: bare quote leaves under an error node (`x = "`) hit punctuation_head's KeyError — unmapped kinds now map to :errortoken (wrong heads still surface via oracle diffs; a throw killed the file). patch_dropped_width! is now gated on the green subtree containing an error node (checked lazily, only when a gap exists), so childsum bugs on valid code keep failing check_spans instead of being padded over. Gates: suite 534/534 (was 510; 6 new broken snippets). Corpora unchanged (src 65/65, depot 1154/1161). Stride-5 prefix sweep over all 86 CommonMark+BandedMatrices files with triple-quoted docstrings: clean (was 11 failing). Full re-sweep of converter source prefixes: clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Kind/API renames discovered empirically against the vendored 1.0.2 fork: K"true"/K"false" -> K"Bool" (split by literal text); absent-catch-var false-leaf -> K"Placeholder"; K"cartesian_iterator" -> K"iteration" (now also wraps single specs); iteration specs get their own K"in" node kind; short-form defs normalize to K"function" (keyword-child discriminates the long form); compound assignment splits into op+= leaf pairs under K"op=" (dotted variant adds a `.` leaf, same kind + DOTTED flag); operator tokens in value position reclassify to K"Identifier" (Base.isoperator on the text recovers OPERATOR); getfield field names lose their K"quote" wrapper unless colon-prefixed (a.$f also loses K"inert"); do-blocks nest under the call/macrocall node instead of wrapping it; `->` LHS params always arrive as K"tuple" (bare/parened/paren-block spellings mapped back to the oracle's identifier/brackets/paren-block shapes); bare backtick literals lose the core_@cmd wrapper (globalrefcmd macrocall synthesized, except for the cmd-macro body position); struct-field docstrings arrive as K"doc" (unfused back to sibling string+field, oracle only fuses at toplevel/module/begin scope). Suite 534/534; src corpus 65/65; depot corpus 1154/1161 (same six accepted-drift files as under 0.4.10 plus the known StackOverflow file). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
The converter and layer code are 1.x-only after the port; drop the 0.4 compat entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Every Task-10 entry reproduces under the vendored 1.0.2 fork + CSTParser 3.5.1-DEV oracle; none dissolved. Two entries updated: the StackOverflow file still overflows at default stack (but parses AND converts to full oracle equality on an enlarged-stack task — verified Task 12 fix path), and the "context-dependent" StaticArrays broadcast case now reduces to whitespace-before-:: in a macro arg (CSTParser deviates from Meta.parse; accept drift). Final numbers: suite 534/534, src corpus 65/65, depot corpus 1154/1161, stride-5 prefix sweep over 4 triple-quote-heavy files 14740 prefixes / 0 throws / 0 span violations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
derived_julia_legacy_syntax_tree now builds EXPR via CSTConversion from the shared green tree; JW_CST_BACKEND=cstparser restores the old parser. Parse and the recursive tree builders downstream run on an enlarged-stack task so deeply-nested/machine-generated input never StackOverflows the Salsa query; a shallow error-fallback tree covers the never-throw case. Fixes two converter bugs found by the backend-flip regression sweep: a.end/a.begin dot-getfield field names wrongly kept the END/BEGIN index-context literal, and a module missing its closing `end` leaked a 4th :module arg instead of CSTParser's own missing-token convention, which crashed StaticLint/completions code walking the tree via CSTParser's iterate protocol. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Five StaticLint tests relied on CSTParser leniently parsing invalid Julia (unbracketed `=` in if conditions; stray `end` inside comprehensions). JuliaSyntax rejects these at parse time, so the check_if_conds tests now assert syntax-error diagnostics instead of the now-unreachable EqInIfConditional lint hit, and the list-comp iter-spec fixture is corrected to valid syntax with its lint assertions kept. Also note on CST_BACKEND that the env var is read at load time only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
F1: unterminated for/while/try/function/macro/if leaked the missing-`end` error node into args, breaking CSTParser's iterate accessors with a BoundsError (killing get_diagnostics_blocking for the whole workspace). Route it to a trivia :END placeholder instead (guarded by !has_end so a terminated form with an internal parse error keeps its iterable shape); a degenerate unterminated try synthesizes an empty catch for its fixed arity. F7: drop the zero-width error-leaf recovery marker from a plain block's args (begin/quote blocks keep an :END placeholder in trivia). F2: fold the pre-`end` `;` in abstract/primitive type decls. F3: key the short-form def discriminator on a genuine `function` keyword leaf. F4/F5: reclassify isa/in/where word operators in comparison chains and export/public lists to OPERATOR. F6: bare unary-`::` typed def wraps its body block with EXPR[] trivia. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
F9: has_error_descendant re-walked the green subtree at every ancestor of a
dropped-width site (quadratic on broken input like "f("^n). Precompute once
per build a prefix count of error-covered leaves (leaves inside or being any
green error node, since a non-terminal K"error" can wrap ordinary tokens) and
test overlap in O(1), plus the node's own is-error kind for zero-width
childless error non-terminals. Fillers appear identically; timing is now
linear (~2x per input doubling vs the old ~4x).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
F8: it took 1-based bytes while its documented counterpart get_expr1 is 0-based, and byte 0 / out-of-range silently returned the root. Switch to a 0-based offset (converted internally), document it, and throw ArgumentError for offset < 0 or offset >= file size. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
- broken-code invariants: recursive CSTParser-iterate walk applied to every broken snippet (would have caught F1), plus the unterminated for/while/try/ function/macro repros and nested variants. - workspace-level testitem: get_diagnostics_blocking on an unterminated block returns without throwing. - oracle-green regressions for F2-F6; word-operator reclassification testitem. - F8 syntax_node_at: 0-based offset assertions + boundary cases. - F10: direct EqInIfConditional coverage via a lenient CSTParser parse, exercising the JW_CST_BACKEND=cstparser escape-hatch path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
A dropped ternary error marker can carry folded trailing trivia (the newline in "a ? b\n" folds into the zero-width marker); dropping its width left a childsum gap that patch_dropped_width! filled with a width-bearing errortoken ARG, breaking the 3-arg/2-trivia arity CSTParser's ternary iterate expects (and killing whole-workspace diagnostics via the include walker). Fold the width onto the preceding real leaf instead (widen_at_leaf!, skipping earlier markers); an orphaned width rides on the first zero-width pad. Tests cover the repro variants plus trailing-trivia forms of the other crash-class snippets and a workspace-level get_diagnostics_blocking assert. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
A juxtaposition error ("1 x") makes JuliaSyntax close the body block and emit
the leftover tokens as an error sibling between the block and `end`, giving
terminated containers (function/let/module/struct/while/for/macro) an extra
kid that breaks CSTParser's fixed iterate arities; try and if+else variants
left dirty childsums. Absorb width-bearing error kids into the preceding
block centrally in assemble (skipping zero-span recovery markers, which keep
their per-form missing-`end` handling), and make the unterminated-`if` END
placeholder unconditional on a missing `end` since the absorbed kid can no
longer be its trigger. Tests cover all probed container shapes plus a
workspace-level get_diagnostics_blocking assert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k4W3Mkzub3WB2YUcA8L1Z
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is basically just Fable doing its thing. Haven't reviewed any of this in-depth, but generally seems to be sensible. This should allow for a gradual cutover of the static analysis passes to pure JuliaSyntax trees (presumably just the green tree?).