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 2018/02/17 15:36:49 UTC

groovy git commit: Refine constructor reference to support generics

Repository: groovy
Updated Branches:
  refs/heads/master e2f4ceb50 -> 2ac5b4852


Refine constructor reference to support generics


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

Branch: refs/heads/master
Commit: 2ac5b48520cd404157ab09c586d329a6afa0f366
Parents: e2f4ceb
Author: Daniel Sun <re...@hotmail.com>
Authored: Sat Feb 17 23:36:42 2018 +0800
Committer: Daniel Sun <re...@hotmail.com>
Committed: Sat Feb 17 23:36:42 2018 +0800

----------------------------------------------------------------------
 src/antlr/GroovyParser.g4                       | 40 ++++++++++----------
 .../apache/groovy/parser/antlr4/AstBuilder.java | 30 ++++++++++-----
 .../resources/core/MethodReference_01x.groovy   |  8 ++++
 3 files changed, 49 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/2ac5b485/src/antlr/GroovyParser.g4
----------------------------------------------------------------------
diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index 2db4c7f..df86f3c 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -192,11 +192,11 @@ typeParameter
     ;
 
 typeBound
-    :   type (BITAND nls type)*
+    :   type[false] (BITAND nls type[false])*
     ;
 
 typeList
-    :   type (COMMA nls type)*
+    :   type[false] (COMMA nls type[false])*
     ;
 
 
@@ -223,7 +223,7 @@ locals[ int t ]
                         // Only interface can extend more than one super class
                         {1 == $t}? scs=typeList
                     |
-                        sc=type
+                        sc=type[false]
                     )
                 nls)?
             |
@@ -347,14 +347,13 @@ options { baseContext = type; }
         dimsOpt
     ;
 
-type
+type[boolean allowVoid]
     :   annotationsOpt
         (
             (
                 primitiveType
             |
-                 // !!! ERROR ALTERNATIVE !!!
-                 VOID { require(false, "void is not allowed here", -4); }
+                 VOID
             )
         |
                 generalClassOrInterfaceType
@@ -387,8 +386,8 @@ typeArguments
     ;
 
 typeArgument
-    :   type
-    |   annotationsOpt QUESTION ((EXTENDS | SUPER) nls type)?
+    :   type[false]
+    |   annotationsOpt QUESTION ((EXTENDS | SUPER) nls type[false])?
     ;
 
 annotatedQualifiedClassName
@@ -408,11 +407,11 @@ formalParameterList
     ;
 
 thisFormalParameter
-    :   type THIS
+    :   type[false] THIS
     ;
 
 formalParameter
-    :   variableModifiersOpt type? ELLIPSIS? variableDeclaratorId (nls ASSIGN nls expression)?
+    :   variableModifiersOpt type[false]? ELLIPSIS? variableDeclaratorId (nls ASSIGN nls expression)?
     ;
 
 methodBody
@@ -584,12 +583,12 @@ classifiedModifiers[int t]
 variableDeclaration[int t]
 @leftfactor { classifiedModifiers }
     :   classifiedModifiers[$t]
-        (   type? variableDeclarators
+        (   type[false]? variableDeclarators
         |   typeNamePairs nls ASSIGN nls variableInitializer
         )
     |
         classifiedModifiers[$t]?
-        type variableDeclarators
+        type[false] variableDeclarators
     ;
 
 typeNamePairs
@@ -597,7 +596,7 @@ typeNamePairs
     ;
 
 typeNamePair
-    :   type? variableDeclaratorId
+    :   type[false]? variableDeclaratorId
     ;
 
 variableNames
@@ -720,7 +719,7 @@ forControl
     ;
 
 enhancedForControl
-    :   variableModifiersOpt type? variableDeclaratorId (COLON | IN) expression
+    :   variableModifiersOpt type[false]? variableDeclaratorId (COLON | IN) expression
     ;
 
 classicalForControl
@@ -740,7 +739,7 @@ forUpdate
 // EXPRESSIONS
 
 castParExpression
-    :   LPAREN type rparen
+    :   LPAREN type[false] rparen
     ;
 
 parExpression
@@ -814,7 +813,7 @@ expression
         right=expression                                                                    #shiftExprAlt
 
     // boolean relational expressions (level 7)
-    |   left=expression nls op=(AS | INSTANCEOF | NOT_INSTANCEOF) nls type                  #relationalExprAlt
+    |   left=expression nls op=(AS | INSTANCEOF | NOT_INSTANCEOF) nls type[false]           #relationalExprAlt
     |   left=expression nls op=(LE | GE | GT | LT | IN | NOT_IN)  nls right=expression      #relationalExprAlt
 
     // equality/inequality (==/!=) (level 8)
@@ -1011,7 +1010,10 @@ namedPropertyArgs
     ;
 
 primary
-    :   identifier                                                                          #identifierPrmrAlt
+    :
+        // Append `typeArguments?` to `identifier` to support constructor reference with generics, e.g. HashMap<String, Integer>::new
+        // Though this is not a graceful solution, it is much faster than replacing `builtInType` with `type`
+        identifier typeArguments?                                                           #identifierPrmrAlt
     |   literal                                                                             #literalPrmrAlt
     |   gstring                                                                             #gstringPrmrAlt
     |   NEW nls creator                                                                     #newPrmrAlt
@@ -1022,7 +1024,7 @@ primary
     |   lambdaExpression                                                                    #lambdaPrmrAlt
     |   list                                                                                #listPrmrAlt
     |   map                                                                                 #mapPrmrAlt
-    |   builtInType                                                                         #typePrmrAlt
+    |   builtInType                                                                         #builtInTypePrmrAlt
     ;
 
 list
@@ -1210,5 +1212,3 @@ nls
 sep :   SEMI NL*
     |   NL+ (SEMI NL*)*
     ;
-
-

http://git-wip-us.apache.org/repos/asf/groovy/blob/2ac5b485/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index e1bed5d..6c02297 100644
--- a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -159,6 +159,7 @@ import static org.apache.groovy.parser.antlr4.GroovyLangParser.BooleanLiteralAlt
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.BreakStatementContext;
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.BreakStmtAltContext;
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.BuiltInTypeContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.BuiltInTypePrmrAltContext;
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.CASE;
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.CastExprAltContext;
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.CastParExpressionContext;
@@ -329,7 +330,6 @@ import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeNamePairConte
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeNamePairsContext;
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeParameterContext;
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeParametersContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypePrmrAltContext;
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.UnaryAddExprAltContext;
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.UnaryNotExprAltContext;
 import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclarationContext;
@@ -2348,7 +2348,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
                 return configureAST(methodCallExpression, ctx);
             }
 
-            if (baseExpr instanceof VariableExpression) { // void and primitive type AST node must be an instance of VariableExpression
+            if (baseExpr instanceof ClassExpression) { // void and primitive type AST node must be an instance of ClassExpression
                 String baseExprText = baseExpr.getText();
                 if (VOID_STR.equals(baseExprText)) { // e.g. void()
                     return configureAST(createCallMethodCallExpression(this.createConstantExpression(baseExpr), argumentsExpr), ctx);
@@ -3055,7 +3055,16 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
 
     // primary {       --------------------------------------------------------------------
     @Override
-    public VariableExpression visitIdentifierPrmrAlt(IdentifierPrmrAltContext ctx) {
+    public Expression visitIdentifierPrmrAlt(IdentifierPrmrAltContext ctx) {
+        if (asBoolean(ctx.typeArguments())) {
+            ClassNode classNode = ClassHelper.make(ctx.identifier().getText());
+
+            classNode.setGenericsTypes(
+                    this.visitTypeArguments(ctx.typeArguments()));
+
+            return configureAST(new ClassExpression(classNode), ctx);
+        }
+
         return configureAST(new VariableExpression(this.visitIdentifier(ctx.identifier())), ctx);
     }
 
@@ -3113,10 +3122,8 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
     }
 
     @Override
-    public VariableExpression visitTypePrmrAlt(TypePrmrAltContext ctx) {
-        return configureAST(
-                this.visitBuiltInType(ctx.builtInType()),
-                ctx);
+    public ClassExpression visitBuiltInTypePrmrAlt(BuiltInTypePrmrAltContext ctx) {
+        return configureAST(this.visitBuiltInType(ctx.builtInType()), ctx);
     }
 
 
@@ -3359,7 +3366,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
     */
 
     @Override
-    public VariableExpression visitBuiltInType(BuiltInTypeContext ctx) {
+    public ClassExpression visitBuiltInType(BuiltInTypeContext ctx) {
         String text;
         if (asBoolean(ctx.VOID())) {
             text = ctx.VOID().getText();
@@ -3369,7 +3376,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
             throw createParsingFailedException("Unsupported built-in type: " + ctx, ctx);
         }
 
-        return configureAST(new VariableExpression(text), ctx);
+        return configureAST(new ClassExpression(ClassHelper.make(text)), ctx);
     }
 
 
@@ -3864,9 +3871,14 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
             classNode = this.visitClassOrInterfaceType(ctx.classOrInterfaceType());
         } else if (asBoolean(ctx.primitiveType())) {
             classNode = this.visitPrimitiveType(ctx.primitiveType());
+        } else if (asBoolean(ctx.VOID())) {
+            if (ctx.allowVoid) {
+                classNode = configureAST(ClassHelper.make(ctx.getText()), ctx.VOID());
+            }
         }
 
         if (!asBoolean(classNode)) {
+            // TODO refine error message for `void`
             throw createParsingFailedException("Unsupported type: " + ctx.getText(), ctx);
         }
 

http://git-wip-us.apache.org/repos/asf/groovy/blob/2ac5b485/subprojects/parser-antlr4/src/test/resources/core/MethodReference_01x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/test/resources/core/MethodReference_01x.groovy b/subprojects/parser-antlr4/src/test/resources/core/MethodReference_01x.groovy
index 4816adf..997a7bf 100644
--- a/subprojects/parser-antlr4/src/test/resources/core/MethodReference_01x.groovy
+++ b/subprojects/parser-antlr4/src/test/resources/core/MethodReference_01x.groovy
@@ -77,6 +77,14 @@ def mr = String::toUpperCase
 assert 'ABC' == mr('abc')
 assert 'ABC' == String::toUpperCase('abc')
 
+def m = ['apple', 'banana', 'orange'].stream().collect(Collectors.toMap(e -> e.charAt(0), e -> e, (e1, e2) -> e1, LinkedHashMap<String, String>::new))
+assert m instanceof LinkedHashMap
+assert ['a', 'b', 'o'] as TreeSet == m.keySet() as TreeSet
+assert ['apple', 'banana', 'orange'] as TreeSet == m.values() as TreeSet
+
+assert new HashMap<String, Integer>() == HashMap<String, Integer>::new()
+assert new HashSet<Integer>() == HashSet<Integer>::new()
+
 assert new HashSet() == HashSet::new()
 assert new String() == String::new()
 assert 1 == Integer::new(1)