You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/04/11 01:37:42 UTC

[06/50] groovy git commit: Breaking change: allow lower case type names except return type name of method declaration

Breaking change: allow lower case type names except return type name of method declaration


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/d3c68531
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/d3c68531
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/d3c68531

Branch: refs/heads/master
Commit: d3c68531e36908680b7ac60b9cbf1a01601e10ae
Parents: c9fbf95
Author: sunlan <su...@apache.org>
Authored: Sat Jan 21 11:57:07 2017 +0800
Committer: sunlan <su...@apache.org>
Committed: Sat Jan 21 11:57:07 2017 +0800

----------------------------------------------------------------------
 .../apache/groovy/parser/antlr4/GroovyParser.g4 | 37 +++++++++-----
 .../apache/groovy/parser/antlr4/AstBuilder.java | 30 +++++------
 .../parser/antlr4/SemanticPredicates.java       | 52 ++++++++++++++++++--
 .../parser/antlr4/GroovyParserTest.groovy       |  6 +++
 .../resources/core/BreakingChange_01x.groovy    | 24 +++++++++
 .../resources/core/BreakingChange_02x.groovy    |  9 ++++
 .../resources/core/BreakingChange_03x.groovy    | 16 ++++++
 .../resources/core/BreakingChange_04x.groovy    | 26 ++++++++++
 .../resources/core/ClassDeclaration_01.groovy   | 10 +++-
 .../src/test/resources/core/Command_01.groovy   |  6 ++-
 10 files changed, 184 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4 b/subprojects/groovy-parser-antlr4/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4
index 5cefb90..6f94ec6 100644
--- a/subprojects/groovy-parser-antlr4/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4
+++ b/subprojects/groovy-parser-antlr4/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4
@@ -310,11 +310,10 @@ methodDeclaration[int t, int ct]
     :   { 3 == $ct }?
         returnType[$ct] methodName LPAREN rparen (DEFAULT nls elementValue)?
     |
-        (   modifiersOpt  typeParameters? returnType[$ct]
-        |   modifiers  typeParameters? returnType[$ct]?
-        |
-            { 0 == $t }?
+        (   { 0 == $t }?
             modifiersOpt typeParameters?
+        |   modifiersOpt  typeParameters? returnType[$ct]
+        |   modifiers  typeParameters? returnType[$ct]?
         )
         methodName formalParameters (nls THROWS nls qualifiedClassNameList)?
         (
@@ -333,7 +332,7 @@ methodName
 
 returnType[int ct]
     :
-        type
+        standardType
     |
         // annotation method can not have void return type
         { 3 != $ct }? VOID
@@ -365,12 +364,25 @@ arrayInitializer
     :   LBRACK (variableInitializer (COMMA variableInitializer)* (COMMA)? )? RBRACK
     ;
 
+standardType
+options { baseContext = type; }
+    :   primitiveType (LBRACK RBRACK)*
+    |   standardClassOrInterfaceType (LBRACK RBRACK)*
+    ;
+
 type
     :   primitiveType (LBRACK RBRACK)*
     |   classOrInterfaceType (LBRACK RBRACK)*
     ;
 
 classOrInterfaceType
+    :   (   qualifiedClassName
+        |   qualifiedStandardClassName
+        ) typeArguments?
+    ;
+
+standardClassOrInterfaceType
+options { baseContext = classOrInterfaceType; }
     :   qualifiedStandardClassName typeArguments?
     ;
 
@@ -559,23 +571,24 @@ blockStatement
     ;
 
 localVariableDeclaration
-    :   variableDeclaration[0]
+    :   { !SemanticPredicates.isInvalidLocalVariableDeclaration(_input) }?
+        variableDeclaration[0]
     ;
 
 /**
  *  t   0: local variable declaration; 1: field declaration
  */
 variableDeclaration[int t]
-    :   (   { 0 == $t }? variableModifiersOpt
-        |   { 1 == $t }? modifiersOpt
-        )
-        type variableDeclarators
-    |
-        (   { 0 == $t }? variableModifiers
+    :   (   { 0 == $t }? variableModifiers
         |   { 1 == $t }? modifiers
         )
         type? variableDeclarators
     |
+        (   { 0 == $t }? variableModifiersOpt
+        |   { 1 == $t }? modifiersOpt
+        )
+        type variableDeclarators
+    |
         (   { 0 == $t }? variableModifiers
         |   { 1 == $t }? modifiers
         )

http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index c61a2c0..8ab5578 100644
--- a/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -3239,8 +3239,14 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
 
     @Override
     public ClassNode visitClassOrInterfaceType(ClassOrInterfaceTypeContext ctx) {
-        ctx.qualifiedStandardClassName().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, ctx.getNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR));
-        ClassNode classNode = this.visitQualifiedStandardClassName(ctx.qualifiedStandardClassName());
+        ClassNode classNode;
+        if (asBoolean(ctx.qualifiedClassName())) {
+            ctx.qualifiedClassName().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, ctx.getNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR));
+            classNode = this.visitQualifiedClassName(ctx.qualifiedClassName());
+        } else {
+            ctx.qualifiedStandardClassName().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, ctx.getNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR));
+            classNode = this.visitQualifiedStandardClassName(ctx.qualifiedStandardClassName());
+        }
 
         if (asBoolean(ctx.typeArguments())) {
             classNode.setGenericsTypes(
@@ -3496,19 +3502,15 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
 
     @Override
     public ClassNode visitQualifiedClassName(QualifiedClassNameContext ctx) {
-        ClassNode result = ClassHelper.make(ctx.getText());
-
-        /*
-        if (!isTrue(ctx, IS_INSIDE_INSTANCEOF_EXPR)) { // type in the "instanceof" expression should not have proxy to redirect to it
-            result = this.proxyClassNode(result);
-        }
-        */
-
-        return this.configureAST(result, ctx);
+        return this.createClassNode(ctx);
     }
 
     @Override
     public ClassNode visitQualifiedStandardClassName(QualifiedStandardClassNameContext ctx) {
+        return this.createClassNode(ctx);
+    }
+
+    private ClassNode createClassNode(GroovyParserRuleContext ctx) {
         ClassNode result = ClassHelper.make(ctx.getText());
 
         if (!isTrue(ctx, IS_INSIDE_INSTANCEOF_EXPR)) { // type in the "instanceof" expression should not have proxy to redirect to it
@@ -4257,7 +4259,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
      * <p>
      * Created by Daniel.Sun on 2016/08/23.
      */
-    private static class ModifierNode extends ASTNode {
+    public static class ModifierNode extends ASTNode {
         private Integer type;
         private Integer opCode; // ASM opcode
         private String text;
@@ -4265,7 +4267,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
         private boolean repeatable;
 
         public static final int ANNOTATION_TYPE = -999;
-        private static final Map<Integer, Integer> MAP = new HashMap<Integer, Integer>() {
+        public static final Map<Integer, Integer> MODIFIER_OPCODE_MAP = new HashMap<Integer, Integer>() {
             {
                 put(ANNOTATION_TYPE, 0);
                 put(DEF, 0);
@@ -4288,7 +4290,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
 
         public ModifierNode(Integer type) {
             this.type = type;
-            this.opCode = MAP.get(type);
+            this.opCode = MODIFIER_OPCODE_MAP.get(type);
             this.repeatable = ANNOTATION_TYPE == type; // Only annotations are repeatable
 
             if (!asBoolean((Object) this.opCode)) {

http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java b/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
index e306e89..811276f 100644
--- a/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
+++ b/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
@@ -19,11 +19,13 @@
 package org.apache.groovy.parser.antlr4;
 
 import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.Token;
 import org.antlr.v4.runtime.TokenStream;
 
-import static org.apache.groovy.parser.antlr4.GroovyParser.CapitalizedIdentifier;
-import static org.apache.groovy.parser.antlr4.GroovyParser.Identifier;
-import static org.apache.groovy.parser.antlr4.GroovyParser.StringLiteral;
+import java.util.Collections;
+import java.util.Set;
+
+import static org.apache.groovy.parser.antlr4.GroovyParser.*;
 
 /**
  * Some semantic predicates for altering the behaviour of the lexer and parser
@@ -103,6 +105,48 @@ public class SemanticPredicates {
         int tokenType = ts.LT(1).getType();
 
         return (Identifier == tokenType || CapitalizedIdentifier == tokenType || StringLiteral == tokenType)
-                && GroovyLangParser.LPAREN == (ts.LT(2).getType());
+                && LPAREN == (ts.LT(2).getType());
     }
+
+    private static final Set<Integer> MODIFIER_SET =
+            Collections.unmodifiableSet(AstBuilder.ModifierNode.MODIFIER_OPCODE_MAP.keySet());
+    /**
+     * Distinguish between local variable declaration and method call, e.g. `a b`
+     */
+    public static boolean isInvalidLocalVariableDeclaration(TokenStream ts) {
+        int index = 2;
+        Token token;
+        int tokenType;
+        int tokenType2 = ts.LT(index).getType();
+        int tokenType3;
+
+        if (DOT == tokenType2) {
+            int tokeTypeN = tokenType2;
+
+            do {
+                index = index + 2;
+                tokeTypeN = ts.LT(index).getType();
+            } while (DOT == tokeTypeN);
+
+            if (LT == tokeTypeN || LBRACK == tokeTypeN) {
+                return false;
+            }
+
+            index = index - 1;
+            tokenType2 = ts.LT(index + 1).getType();
+        } else {
+            index = 1;
+        }
+
+        token = ts.LT(index);
+        tokenType = token.getType();
+        tokenType3 = ts.LT(index + 2).getType();
+
+        return VOID == tokenType
+                ||  !(BuiltInPrimitiveType == tokenType || MODIFIER_SET.contains(tokenType))
+                    && Character.isLowerCase(token.getText().codePointAt(0))
+                    && !(ASSIGN == tokenType3 || (LT == tokenType2 || LBRACK == tokenType2));
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy b/subprojects/groovy-parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
index 003a34b..98d434c 100644
--- a/subprojects/groovy-parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
+++ b/subprojects/groovy-parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
@@ -333,4 +333,10 @@ class GroovyParserTest extends GroovyTestCase {
         doRunAndTest('bugs/BUG-GROOVY-4762.groovy');
     }
 
+    void "test groovy core - BreakingChanges"() {
+        doRunAndTest('core/BreakingChange_01x.groovy');
+        doRunAndTest('core/BreakingChange_02x.groovy');
+        doRunAndTest('core/BreakingChange_03x.groovy');
+        doRunAndTest('core/BreakingChange_04x.groovy');
+    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_01x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_01x.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_01x.groovy
new file mode 100644
index 0000000..3f3b856
--- /dev/null
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_01x.groovy
@@ -0,0 +1,24 @@
+package core
+
+class a<T> {
+    int x = 1;
+}
+
+a b = new a()
+assert b.x == 1
+
+a<String> b2 = new a<String>()
+assert b2.x == 1
+
+a<String>[] b3 = new a<String>[0]
+assert b3.length == 0
+
+core.a b4 = new a()
+assert b4.x == 1
+
+core.a<String> b5 = new a<String>()
+assert b5.x == 1
+
+core.a<String>[] b6 = new a<String>[0]
+assert b6.length == 0
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_02x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_02x.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_02x.groovy
new file mode 100644
index 0000000..62e90ed
--- /dev/null
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_02x.groovy
@@ -0,0 +1,9 @@
+package core
+
+import java.util.concurrent.atomic.AtomicInteger
+
+def inc(AtomicInteger x) { x.incrementAndGet() }
+def a = new AtomicInteger(0)
+
+inc a
+assert 1 == a.get()

http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_03x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_03x.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_03x.groovy
new file mode 100644
index 0000000..b78abf5
--- /dev/null
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_03x.groovy
@@ -0,0 +1,16 @@
+package core
+
+class a {}
+a[] b
+b = new a[0]
+assert 0 == b.length
+
+a[] b2 = new a[0]
+assert 0 == b2.length
+
+core.a[] b3
+b3 = new a[0]
+assert 0 == b3.length
+
+core.a[] b4 = new a[0]
+assert 0 == b4.length
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_04x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_04x.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_04x.groovy
new file mode 100644
index 0000000..10cfcac
--- /dev/null
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_04x.groovy
@@ -0,0 +1,26 @@
+package core
+
+class B<T> {}
+B b
+b = new B()
+assert b instanceof B
+
+B<String> b2
+b2 = new B<String>()
+assert b2 instanceof B
+
+B<String>[] b3
+b3 = new B<String>[0]
+assert b3 instanceof B[]
+
+core.B b4
+b4 = new B()
+assert b4 instanceof B
+
+core.B<String> b5
+b5 = new B<String>()
+assert b5 instanceof B
+
+core.B<String>[] b6
+b6 = new B<String>[0]
+assert b6 instanceof B[]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
index 13d0b8e..8260899 100644
--- a/subprojects/groovy-parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
@@ -44,4 +44,12 @@ C
 
 }
 
-class a {}
\ No newline at end of file
+class a {}
+
+class OutputTransforms {
+        final  static localTransforms = loadOutputTransforms()
+}
+
+class OutputTransforms2 {
+        @Lazy  static localTransforms = loadOutputTransforms()
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/Command_01.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/Command_01.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/Command_01.groovy
index a6188c4..78b7682 100644
--- a/subprojects/groovy-parser-antlr4/src/test/resources/core/Command_01.groovy
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/Command_01.groovy
@@ -11,4 +11,8 @@ z.a x: b(1, 3), y: c(2, 4)
 a b(1, 3), c(2, 4)
 obj.<Integer, Double>a b(1, 3), c(2, 4), d(3, 5)
 println a
-println a = 1
\ No newline at end of file
+// println a = 1  // breaking change
+println a == 1
+
+result.addAll allElements()
+task someTask() {}
\ No newline at end of file