You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/02/04 00:48:35 UTC

[groovy] branch master updated (5f05b8e -> 81fbbb4)

This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git.


    from 5f05b8e  minor refactoring
     new bc84072  Tweak `variableDeclaration` rule
     new 81fbbb4  Tweak unbalanced parens

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/antlr/GroovyLexer.g4                           | 37 +++++++++++------
 src/antlr/GroovyParser.g4                          |  2 -
 .../org/apache/groovy/groovysh/Groovysh.groovy     | 18 +++++++--
 .../org/apache/groovy/groovysh/GroovyshTest.groovy | 14 +++++++
 .../groovy/parser/antlr4/SyntaxErrorTest.groovy    | 47 ++++++++++++++++++++++
 5 files changed, 99 insertions(+), 19 deletions(-)


[groovy] 01/02: Tweak `variableDeclaration` rule

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit bc84072f29d48977b5951d9777f47201ece834b1
Author: Sam Harwell <sa...@tunnelvisionlabs.com>
AuthorDate: Tue Feb 4 05:01:43 2020 +0800

    Tweak `variableDeclaration` rule
    
    ```
    classifiedModifiers[$t]? type variableDeclarators
    ```
    
    can be written as:
    
    ```
    ( classifiedModifiers[$t] type variableDeclarators
    | type variableDeclarators
    )
    ```
---
 src/antlr/GroovyParser.g4 | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index 93d4662..d77c581 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -592,13 +592,11 @@ classifiedModifiers[int t]
  *  t   0: local variable declaration; 1: field declaration
  */
 variableDeclaration[int t]
-@leftfactor { classifiedModifiers }
     :   classifiedModifiers[$t]
         (   type? variableDeclarators
         |   typeNamePairs nls ASSIGN nls variableInitializer
         )
     |
-        classifiedModifiers[$t]?
         type variableDeclarators
     ;
 


[groovy] 02/02: Tweak unbalanced parens

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 81fbbb45d9fd59f2d2ba8b00fdf26c30031175d0
Author: Daniel Sun <su...@apache.org>
AuthorDate: Tue Feb 4 08:28:49 2020 +0800

    Tweak unbalanced parens
---
 src/antlr/GroovyLexer.g4                           | 37 +++++++++++------
 .../org/apache/groovy/groovysh/Groovysh.groovy     | 18 +++++++--
 .../org/apache/groovy/groovysh/GroovyshTest.groovy | 14 +++++++
 .../groovy/parser/antlr4/SyntaxErrorTest.groovy    | 47 ++++++++++++++++++++++
 4 files changed, 99 insertions(+), 17 deletions(-)

diff --git a/src/antlr/GroovyLexer.g4 b/src/antlr/GroovyLexer.g4
index 016824f..6456af1 100644
--- a/src/antlr/GroovyLexer.g4
+++ b/src/antlr/GroovyLexer.g4
@@ -47,11 +47,15 @@ options {
     import java.util.Collections;
     import java.util.Arrays;
     import java.util.stream.IntStream;
+    import java.util.logging.Logger;
+    import java.util.logging.Level;
+    import java.util.EmptyStackException;
     import org.apache.groovy.util.Maps;
     import static org.apache.groovy.parser.antlr4.SemanticPredicates.*;
 }
 
 @members {
+    private static final Logger LOGGER = Logger.getLogger(GroovyLexer.class.getName());
     private long tokenIndex     = 0;
     private int  lastTokenType  = 0;
     private int  invalidDigitCount = 0;
@@ -140,13 +144,6 @@ options {
         }
     }
 
-    private static final Map<String, String> PAREN_MAP =
-        Maps.of(
-            "(", ")",
-            "[", "]",
-            "{", "}"
-        );
-
     protected void enterParenCallback(String text) {}
 
     protected void exitParenCallback(String text) {}
@@ -156,18 +153,16 @@ options {
     private void enterParen() {
         String text = getText();
         enterParenCallback(text);
+
         parenStack.push(new Paren(text, this.lastTokenType, getLine(), getCharPositionInLine()));
     }
 
     private void exitParen() {
-        Paren paren = parenStack.peek();
         String text = getText();
-
-        require(null != paren, "Too many '" + text + "'");
-        require(text.equals(PAREN_MAP.get(paren.getText())),
-                "'" + paren.getText() + "'" + new PositionInfo(paren.getLine(), paren.getColumn()) + " can not match '" + text + "'", -1);
-
         exitParenCallback(text);
+
+        Paren paren = parenStack.peek();
+        if (null == paren) return;
         parenStack.pop();
     }
     private boolean isInsideParens() {
@@ -178,6 +173,7 @@ options {
         if (null == paren) {
             return false;
         }
+
         return ("(".equals(paren.getText()) && TRY != paren.getLastTokenType()) // we don't treat try-paren(i.e. try (....)) as parenthesis
                     || "[".equals(paren.getText());
     }
@@ -210,6 +206,19 @@ options {
     public int getErrorColumn() {
         return getCharPositionInLine() + 1;
     }
+
+    @Override
+    public int popMode() {
+        try {
+            return super.popMode();
+        } catch (EmptyStackException ignored) { // raised when parens are unmatched: too many ), ], or }
+            if (LOGGER.isLoggable(Level.FINEST)) {
+                LOGGER.finest(org.codehaus.groovy.runtime.DefaultGroovyMethods.asString(ignored));
+            }
+        }
+
+        return Integer.MIN_VALUE;
+    }
 }
 
 
@@ -806,8 +815,10 @@ NOT_IN              : '!in'         { isFollowedBy(_input, ' ', '\t', '\r', '\n'
 
 LPAREN          : '('  { this.enterParen();     } -> pushMode(DEFAULT_MODE);
 RPAREN          : ')'  { this.exitParen();      } -> popMode;
+
 LBRACE          : '{'  { this.enterParen();     } -> pushMode(DEFAULT_MODE);
 RBRACE          : '}'  { this.exitParen();      } -> popMode;
+
 LBRACK          : '['  { this.enterParen();     } -> pushMode(DEFAULT_MODE);
 RBRACK          : ']'  { this.exitParen();      } -> popMode;
 
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/Groovysh.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/Groovysh.groovy
index 414a092..77c7fcf 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/Groovysh.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/Groovysh.groovy
@@ -202,8 +202,7 @@ class Groovysh extends Shell {
                     try {
                         setLastResult(result = interp.evaluate(buff))
                     } catch(MultipleCompilationErrorsException t) {
-                        // TODO antlr4 parser errors pop out here - can we rework to be like antlr2?
-                        if (t.message.contains('Unexpected input:') || t.message.contains("Missing ')'")) {
+                        if (isIncompleteCaseOfAntlr4(t)) {
                             // treat like INCOMPLETE case
                             buffers.updateSelected(current)
                             break
@@ -215,8 +214,7 @@ class Groovysh extends Shell {
                     try {
                         result = evaluateWithStoredBoundVars(importsSpec, current)
                     } catch(MultipleCompilationErrorsException t) {
-                        // TODO antlr4 parser errors pop out here - can we rework to be like antlr2?
-                        if (t.message.contains('Unexpected input:') || t.message.contains("Missing ')'")) {
+                        if (isIncompleteCaseOfAntlr4(t)) {
                             // treat like INCOMPLETE case
                             buffers.updateSelected(current)
                             break
@@ -244,6 +242,18 @@ class Groovysh extends Shell {
         return result
     }
 
+    @CompileStatic
+    private boolean isIncompleteCaseOfAntlr4(MultipleCompilationErrorsException t) {
+        // TODO antlr4 parser errors pop out here - can we rework to be like antlr2?
+        (
+                t.message.contains('Unexpected input:') && !(
+                            t.message.contains('Unexpected input: \'}\';')
+                        || t.message.contains('Unexpected input: \')\';')
+                        || t.message.contains('Unexpected input: \']\';')
+                )
+        ) || t.message.contains("Missing ')'")
+    }
+
     /**
      * return true if the buffer can be recognized as a type declaration statement
      * @param strings
diff --git a/subprojects/groovy-groovysh/src/test/groovy/org/apache/groovy/groovysh/GroovyshTest.groovy b/subprojects/groovy-groovysh/src/test/groovy/org/apache/groovy/groovysh/GroovyshTest.groovy
index ab9541d..74a5be3 100644
--- a/subprojects/groovy-groovysh/src/test/groovy/org/apache/groovy/groovysh/GroovyshTest.groovy
+++ b/subprojects/groovy-groovysh/src/test/groovy/org/apache/groovy/groovysh/GroovyshTest.groovy
@@ -96,6 +96,20 @@ class GroovyshTest extends GroovyTestCase {
         } catch (MultipleCompilationErrorsException e) {
             assert '' == mockOut.toString()
         }
+
+        try {
+            groovysh.execute('x)')
+            fail('expected MultipleCompilationErrorsException ')
+        } catch (MultipleCompilationErrorsException e) {
+            assert '' == mockOut.toString()
+        }
+
+        try {
+            groovysh.execute('x]')
+            fail('expected MultipleCompilationErrorsException ')
+        } catch (MultipleCompilationErrorsException e) {
+            assert '' == mockOut.toString()
+        }
     }
 
     void testIncompleteBracketMultilineExpr() {
diff --git a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
index 86bc59d..98d2a1c 100644
--- a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
+++ b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
@@ -21,6 +21,8 @@ package org.apache.groovy.parser.antlr4
 import groovy.test.GroovyTestCase
 import groovy.test.NotYetImplemented
 import org.apache.groovy.parser.antlr4.util.ASTComparatorCategory
+import org.codehaus.groovy.control.CompilationUnit
+import org.codehaus.groovy.control.Phases
 
 /**
  * Some syntax error test cases for the new parser.
@@ -249,7 +251,52 @@ final class SyntaxErrorTest extends GroovyTestCase {
         TestUtils.doRunAndShouldFail('fail/Array_02x.groovy')
     }
 
+
+    void "test error alternative - Missing ')' 1"() {
+        def err = expectFail '''\
+println ((int 123)
+        '''
+
+        assert err == '''\
+startup failed:
+test.groovy: 1: Missing ')' @ line 1, column 14.
+   println ((int 123)
+                ^
+
+1 error
+'''
+    }
+
+    void "test error alternative - Missing ')' 2"() {
+        def err = expectFail '''\
+def x() {
+    println((int) 123
+}
+        '''
+
+        assert err == '''\
+startup failed:
+test.groovy: 2: Missing ')' @ line 2, column 22.
+       println((int) 123
+                        ^
+
+1 error
+'''
+    }
+
     //--------------------------------------------------------------------------
+    def expectFail(String code) {
+        try {
+            def ast = new CompilationUnit().tap {
+                addSource 'test.groovy', code
+                compile Phases.CONVERSION
+            }.getAST()
+
+            fail("should fail")
+        } catch (e) {
+            return e.message.replaceAll('\r\n', '\n')
+        }
+    }
 
     private static unzipScriptAndShouldFail(String entryName, List ignoreClazzList, Map<String, String> replacementsMap=[:], boolean toCheckNewParserOnly = false) {
         ignoreClazzList.addAll(TestUtils.COMMON_IGNORE_CLASS_LIST)