Copilot commented on code in PR #2944:
URL: https://github.com/apache/groovy/pull/2944#discussion_r4220037277


##########
src/antlr/GroovyLexer.g4:
##########
@@ -289,13 +304,24 @@ options {
 
 
 // ยง3.10.5 String Literals
+// A quote that never closes is UNEXPECTED_CHAR: nothing else matches it.
+// `/` is also DIV, so an unclosed `/.../` is an EOF alternative of this rule.
+// isUnclosedSlashy() is the first edge of that alternative, before any body
+// character is read. `*` is safe because the follower is EOF, not `/`:
+// `//` is not an empty slashy. EOF stays here so a second rule cannot
+// swallow source after a real closer.

Review Comment:
   This comment reads as if unclosed quoted strings are handled purely as 
`UNEXPECTED_CHAR`, while the PR adds/extends tests expecting `Unclosed string 
literal` messaging. If unclosed quotes are intentionally diagnosed via 
`UNEXPECTED_CHAR` (but mapped to `Unclosed string literal` elsewhere), consider 
clarifying that mapping here to avoid misleading future maintainers.



##########
src/antlr/GroovyLexer.g4:
##########
@@ -48,6 +48,8 @@ options {
     private boolean errorIgnored;
     private long tokenIndex;
     private int  lastTokenType;
+    /** Last default-channel token whose type is not {@code NL}. */
+    private int  lastRealTokenType;

Review Comment:
   `lastRealTokenType` is used to make lexing decisions but is not initialized 
here. That makes behavior depend on the Java default (0 / `Token.INVALID_TYPE`) 
or any prior state if the lexer instance is reused. Initializing (and resetting 
alongside `lastTokenType`) to a well-defined value like `Token.EOF` would make 
`isUnclosedSlashy()` deterministic in leading-newline / fresh-input scenarios.



##########
src/antlr/GroovyLexer.g4:
##########
@@ -109,6 +114,16 @@ options {
         return !REGEX_CHECK_SET.get(this.lastTokenType);
     }
 
+    /**
+     * A {@code /} that reaches EOF is an unclosed slashy string only when the
+     * previous real token (ignoring {@code NL}) could not be the left operand
+     * of division. {@code 9 \n / \n 3} stays division; {@code s = /hello} 
does not.
+     */
+    private boolean isUnclosedSlashy() {
+        int decision = this.lastTokenType == NL ? this.lastRealTokenType : 
this.lastTokenType;
+        return !REGEX_CHECK_SET.get(decision);
+    }

Review Comment:
   `lastRealTokenType` is used to make lexing decisions but is not initialized 
here. That makes behavior depend on the Java default (0 / `Token.INVALID_TYPE`) 
or any prior state if the lexer instance is reused. Initializing (and resetting 
alongside `lastTokenType`) to a well-defined value like `Token.EOF` would make 
`isUnclosedSlashy()` deterministic in leading-newline / fresh-input scenarios.



##########
src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java:
##########
@@ -2594,11 +2594,13 @@ public Expression visitCommandExpression(final 
CommandExpressionContext ctx) {
                 && baseExpr instanceof BinaryExpression bin
                 && !"[".equals(bin.getOperation().getText())) {
             // `List<Integer name` is parsed as the comparison `List < 
Integer` plus a
-            // command argument. javac: `'>' expected`.
+            // following argument list. javac: `'>' expected`. Unmatched `>` 
in the
+            // error strategy keeps ANTLR's offender; point at that list, not 
at `List`.
+            // An identifier after `T < U` is argumentList, not 
commandArgument.
             if ("<".equals(bin.getOperation().getText())
                     && looksLikeTypeName(bin.getLeftExpression())
                     && looksLikeTypeName(bin.getRightExpression())) {
-                throw createParsingFailedException("Missing '>'", bin);
+                throw createParsingFailedException("Missing '>'", 
ctx.enhancedArgumentListInPar());

Review Comment:
   `ctx.enhancedArgumentListInPar()` may be null for some command-expression 
shapes, which would risk an NPE (or a mis-positioned error) inside 
`createParsingFailedException`. Consider guarding and falling back to a 
non-null anchor (e.g., `ctx.expression()` or `bin`) when 
`enhancedArgumentListInPar()` is absent, while still preferring the 
argument-list node when it exists.



-- 
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