codeconsole opened a new pull request, #3215:
URL: https://github.com/apache/groovy/pull/3215

   Fixes GROOVY-12694.
   
   What changed
   
   The "unclosed cast" heuristic in MissingDelimiterDiagnostic (strategy 2, 
fromCastPattern) now ignores a `(` whose matching `)` comes before the point 
where the parser failed. That point is the offending token, or, for a 
NoViableAltException, the start token of the failed decision when that is 
earlier. When the exception carries no position (null exception or unindexed 
tokens) the scan is unchanged. The bookkeeping is one linear pass over the 
default-channel tokens up to the failure point with a stack of open parens, so 
the error path stays linear.
   
   Why
   
   The scan looked at the whole token stream for `( type <literal | identifier 
| (>` and reported the earliest match as a cast missing its `)`, without asking 
whether that group had already been closed. Groups the parser had long accepted 
match that shape: a record or method header with a primitive-typed parameter 
(`record Circle(double radius)`, `def foo(int x)`), a classic `for (int i = 0; 
...)` header, or a parenthesised call such as `(Math.max(1, 2))`. Any syntax 
error later in the file was then reported as `Missing ')'` on that earlier 
line. The reported case is an unsupported type pattern in a switch case label 
(`case Circle c ->`) after a record declaration: `Missing ')' @ line 1, column 
22` inside the well-formed record header instead of `Unexpected input: 'String 
s = switch (o) { case Circle c' @ line 3, column 37`, which is what the same 
switch gets after a plain class.
   
   Real unclosed casts keep their diagnostics because a group that still 
contains the failure point, or has no closer at all, is still scanned: `println 
((int 123)` keeps `Missing ')'` at `123`, and the existing `for (int i=0; ...)` 
call-argument case in ParserNegativeSyntaxTest (where the offending token is 
the `(` of the group itself) keeps its caret.
   
   Testing
   
   - ParserNegativeSyntaxTest: two new end-to-end cases (record declaration 
followed by `case Circle c ->`; a for header, a primitive-typed parameter and a 
parenthesised call followed by a later syntax error).
   - MissingDelimiterDiagnosticTest: cases for a group closed before the 
failure (with and without another unclosed delimiter), a group holding the 
offending token, the NoViableAltException start token, and a failure without a 
position. The existing reflection tests for fromCastPattern pass the new second 
argument.
   - The new end-to-end cases and the two "closed before the failure" unit 
cases fail on master without the main change and pass with it.
   - `./gradlew :test --tests 
org.apache.groovy.parser.antlr4.internal.MissingDelimiterDiagnosticTest --tests 
org.apache.groovy.parser.antlr4.ParserNegativeSyntaxTest` on JDK 21: 82 + 235 
tests, 0 failures. Without the main change the same run fails the four 
behavioural cases named above (plus the reflection tests, which then see the 
old one-argument signature).
   - `./gradlew :test --tests 'org.apache.groovy.parser.antlr4.*'`: 14 classes, 
828 tests, 0 failures, 1 skipped.
   - `./gradlew :checkstyleMain`: no new findings in 
MissingDelimiterDiagnostic.java; the only entry for the file is the 
pre-existing cyclomatic-complexity warning on fromCastPattern (15, unchanged 
from master because the candidate filtering lives in the new helper).
   - The installed `groovyc --check` from this branch reports the reproducer at 
`3:37: Unexpected input: 'String s = switch (o) { case Circle c'`; 6.0.0, 
6.0.1-SNAPSHOT and master before the change report `1:22: Missing ')'`.
   
   Backport
   
   The affected code is identical on GROOVY_6_0_X; the change applies cleanly 
there and is suggested for 6.0.1.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to