GROOVY-12169: Improve syntax error messages and caret positions for missing ')', ']', and '}'#2718
Conversation
There was a problem hiding this comment.
⚠️ Performance Alert ⚠️
Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.
| Benchmark suite | Current: 1f18b8a | Previous: 2d57704 | Ratio |
|---|---|---|---|
org.apache.groovy.bench.GeneratedHashCodeBench.generated_hashcode_on_instance_with_null_properties |
205941.4328302444 ops/ms |
131692.1645815392 ops/ms |
1.56 |
org.apache.groovy.bench.NonCapturingLambdaBench.capturingLambdaApply |
114645.36234527593 ops/ms |
74918.8989046163 ops/ms |
1.53 |
org.apache.groovy.bench.NonCapturingLambdaBench.streamMapNonCapturing |
26926.346940213174 ops/ms |
16198.983030455269 ops/ms |
1.66 |
org.apache.groovy.bench.StaticMethodCallIndyBench.instanceChain_groovy |
184.39943806614167 ops/ms |
113.37893198200717 ops/ms |
1.63 |
org.apache.groovy.bench.StaticMethodCallIndyBench.instanceFib_groovy |
2.0494772002017547 ops/ms |
1.2369449950715008 ops/ms |
1.66 |
org.apache.groovy.bench.StaticMethodCallIndyBench.instanceSum_groovy |
246.6410632977486 ops/ms |
144.6242693431618 ops/ms |
1.71 |
org.apache.groovy.bench.StaticMethodCallIndyBench.staticChain_groovy |
1105.3171503771462 ops/ms |
720.8843282126909 ops/ms |
1.53 |
org.apache.groovy.bench.StaticMethodCallIndyBench.staticFib_groovy |
4.774938319086619 ops/ms |
2.6040608472851217 ops/ms |
1.83 |
org.apache.groovy.bench.StaticMethodCallIndyBench.staticSum_groovy |
1415.173333355066 ops/ms |
723.089090154398 ops/ms |
1.96 |
org.apache.groovy.bench.dispatch.CallsiteBench.dispatch_1_monomorphic_groovy |
7352.034281553356 ops/ms |
4570.034697549628 ops/ms |
1.61 |
org.apache.groovy.bench.dispatch.CallsiteBench.dispatch_1_monomorphic_groovyColdReflect |
7356.6867454913545 ops/ms |
4567.336211382841 ops/ms |
1.61 |
org.apache.groovy.bench.dispatch.CallsiteBench.dispatch_1_monomorphic_java |
73394.11449588262 ops/ms |
45902.69843927495 ops/ms |
1.60 |
org.apache.groovy.bench.dispatch.CallsiteBench.dispatch_3_polymorphic_java |
8514.09000642501 ops/ms |
2737.3048365888867 ops/ms |
3.11 |
org.apache.groovy.bench.dispatch.CallsiteBench.dispatch_8_megamorphic_groovyCS |
25926.473707471458 ops/ms |
16983.073673062565 ops/ms |
1.53 |
org.apache.groovy.bench.dispatch.CallsiteBench.dispatch_8_megamorphic_java |
8638.987861365998 ops/ms |
1885.9895489711587 ops/ms |
4.58 |
This comment was automatically generated by workflow using github-action-benchmark.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #2718 +/- ##
==================================================
+ Coverage 69.1438% 69.1956% +0.0518%
- Complexity 34327 34454 +127
==================================================
Files 1538 1539 +1
Lines 129611 129832 +221
Branches 23580 23650 +70
==================================================
+ Hits 89618 89838 +220
+ Misses 31950 31944 -6
- Partials 8043 8050 +7
🚀 New features to boost your workflow:
|
JMH summary — classic (commit
|
| Group | Speedup | Calibrated | n |
|---|---|---|---|
| bench | 1.235 × | 0.989 × | 84 |
| core | 1.071 × | 1.102 × | 77 |
| grails | 0.993 × | 0.945 × | 80 |
⚠️ Runner speed differs ≥15% from the historical baseline hardware for: bench. Raw speedups are not meaningful for those parts — use the calibrated column.
Runner calibration (this run vs baseline hardware): bench 1.25× (26 rulers) · core-ag 0.94× (3 rulers) · core-hz 1.01× (3 rulers) · grails-ad 1.11× (3 rulers) · grails-ez 1.00× (3 rulers)
Baseline: dev/bench/jmh/<part>/classic/data.js on gh-pages, trailing 90 days. Daily dashboard · Per-suite raw data
JMH summary — indy (commit
|
| Group | Speedup | Calibrated | n |
|---|---|---|---|
| bench | 1.784 × | 0.902 × | 84 |
| core | 3.670 × | 3.487 × | 77 |
| grails | 2.229 × | 2.428 × | 80 |
⚠️ Runner speed differs ≥15% from the historical baseline hardware for: bench. Raw speedups are not meaningful for those parts — use the calibrated column.
Runner calibration (this run vs baseline hardware): bench 1.90× (26 rulers) · core-ag 0.98× (3 rulers) · core-hz 1.14× (3 rulers) · grails-ad 0.95× (3 rulers) · grails-ez 0.89× (3 rulers)
Baseline: dev/bench/jmh/<part>/indy/data.js on gh-pages, trailing 90 days. Daily dashboard · Per-suite raw data
2ae01a3 to
e8b9ffd
Compare
…issing ')', ']', and '}'
e8b9ffd to
04791b2
Compare
There was a problem hiding this comment.
Pull request overview
Improves Groovy’s ANTLR4 parse error reporting for missing closing delimiters (), ], }) by adding a post-failure token-stream diagnostic that computes a more accurate “Missing …” message and caret position, and wiring it into the existing DescriptiveErrorStrategy.
Changes:
- Add
MissingDelimiterDiagnosticto detect likely missing closers using expected-token hints, cast-pattern heuristics, and a delimiter stack scan. - Integrate the diagnostic into
DescriptiveErrorStrategyso missing-delimiter messages are preferred over generic “Unexpected input” when confidently detected. - Expand end-to-end and branch-level tests covering missing delimiter messages and caret positioning.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/main/java/org/apache/groovy/parser/antlr4/internal/MissingDelimiterDiagnostic.java | New internal diagnostic that scans tokens after recognition failure to locate missing ), ], } with better caret placement. |
| src/main/java/org/apache/groovy/parser/antlr4/internal/DescriptiveErrorStrategy.java | Routes NoViableAlt/InputMismatch reports through the new missing-delimiter diagnostic before falling back to generic messages. |
| src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy | Enables and adds end-to-end syntax error expectations for missing delimiters and caret positions. |
| src/test/groovy/org/apache/groovy/parser/antlr4/internal/MissingDelimiterDiagnosticTest.groovy | New focused unit tests for MissingDelimiterDiagnostic, including defensive/edge branches. |
| src/test/java/org/apache/groovy/parser/antlr4/internal/ThrowingTokenStream.java | Test helper token stream intended to force error paths during token collection. |
| @Override | ||
| public String getText(Object start, Object stop) { | ||
| return ""; | ||
| } |
paulk-asert
left a comment
There was a problem hiding this comment.
Non-blocking nits (optional follow-ups, worth a PR comment)
- insertionPointAfter adds the token's codepoint length to its start column — a multi-line anchor token (triple-quoted string/GString before a missing }) overshoots the caret. Message stays correct; caret only. Rare.
- fromCastPattern reports the earliest high-confidence cast site independent of where ANTLR actually failed — intentional and well-guarded, but in a multi-error file the location could point at a different construct.
- The broad catch (IndexOutOfBounds | IllegalArgumentException) in collectDefaultChannelTokens silently proceeds with partial tokens — reasonable for non-buffered streams (and there's a ThrowingTokenStream test), already commented.
Thanks for the careful review and the approval — notes below on each optional nit.
|
|
✅ All tests passed ✅🏷️ Commit: 1f18b8a Learn more about TestLens at testlens.app. |



https://issues.apache.org/jira/browse/GROOVY-12169