Scala: fix parsing fragility around case bodies and try/catch keywords#7665
Merged
Conversation
Several "find next token" lookups used a fixed +50/+200 character substring window. When intervening comments push the target past the window, the parser silently misses the token and produces non-idempotent print output. Replaces those with `positionOfNext` (comment-aware) or captures the explicit token via a marker. - Empty catch case bodies with trailing line comments now round-trip (`case _: Throwable => // comment\n}`). - Explicit `;` separators between same-line cases (`case a => x; case b => y`) are preserved with a Semicolon marker on the wrapping JRightPadded. - `catch` and `finally` keyword searches no longer rely on a fixed lookahead window — works correctly with long comments between try/catch/finally. - Tightens up the parser internals: uses Space.format(source, start, end) instead of Space.format(source.substring(start, end)) throughout, and uses Tree.randomId() instead of UUID.randomUUID() at marker construction sites.
greg-at-moderne
approved these changes
May 12, 2026
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.
Motivation
Several "find next token" lookups in the Scala parser used a fixed
+50/+200character substring window. When intervening commentspush the target past the window, the parser silently misses the token
and produces non-idempotent print output. This surfaced as parse
failures on real Scala files containing things like
case _: Throwable => // comment(where a long line comment pushesthe closing
}past the lookahead window).A
;between cases on the same line (case a => x; case b => y) wasalso being dropped on print because there was no marker preserving the
explicit separator.
Summary
(
case _: Throwable => // comment\n}) — replaced thecursor + 50window with
positionOfNext(\"}\")which skips over comments.;separators between same-linematchcases are preservedvia a
Semicolonmarker on theJRightPaddedwrapping the case.Detected by checking whether the next non-whitespace token after the
body's content end (computed from the AST's
Block.expr/statsspans, not the cursor — which Dotty's case body span often overshoots)
is
;.catchandfinallykeyword searches no longer use a fixed lookaheadwindow — works correctly when long comments sit between the try body
and
catch, or betweencatchandfinally.Space.format(source, start, end)instead of
Space.format(source.substring(start, end))throughout(avoids 70+ intermediate
Stringallocations on the hot path), anduses
Tree.randomId()instead ofUUID.randomUUID()at markerconstruction sites.
Test plan
MatchTestfor;-separated cases andvarious case body shapes (
./gradlew :rewrite-scala:test --tests MatchTest)TryTestfor empty case bodies with linecomments, long block comments before
catch, and long blockcomments before
finally./gradlew :rewrite-scala:test)