Repository: groovy
Updated Branches:
  refs/heads/master d033d1ce5 -> bc254b19f


Support creating instances of non-static inner classes of Java style


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

Branch: refs/heads/master
Commit: bc254b19f2d585da5430ea5fa81b72e0761efd31
Parents: d033d1c
Author: sunlan <sun...@apache.org>
Authored: Thu Apr 12 08:40:48 2018 +0800
Committer: sunlan <sun...@apache.org>
Committed: Thu Apr 12 08:40:48 2018 +0800

----------------------------------------------------------------------
 src/antlr/GroovyParser.g4                       | 21 ++++---
 .../apache/groovy/parser/antlr4/AstBuilder.java | 20 ++++++-
 .../parser/antlr4/GroovyParserTest.groovy       |  4 ++
 .../groovy/parser/antlr4/SyntaxErrorTest.groovy |  4 ++
 .../resources/core/NonStaticClass_01x.groovy    | 59 ++++++++++++++++++++
 .../resources/fail/NonStaticClass_01x.groovy    | 33 +++++++++++
 6 files changed, 132 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/bc254b19/src/antlr/GroovyParser.g4
----------------------------------------------------------------------
diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index 385fd11..aef9289 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -816,7 +816,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     
             #relationalExprAlt
     |   left=expression nls op=(LE | GE | GT | LT | IN | NOT_IN)  nls 
right=expression      #relationalExprAlt
 
     // equality/inequality (==/!=) (level 8)
@@ -927,7 +927,7 @@ commandArgument
  *  (Compare to a C lvalue, or LeftHandSide in the JLS section 15.26.)
  *  General expressions are built up from path expressions, using operators 
like '+' and '='.
  *
- *  t   0: primary, 1: namePart, 2: arguments, 3: closure, 4: 
indexPropertyArgs, 5: namedPropertyArgs
+ *  t   0: primary, 1: namePart, 2: arguments, 3: closure, 4: 
indexPropertyArgs, 5: namedPropertyArgs, 6: non-static inner class creator
  */
 pathExpression returns [int t]
     :   primary (pathElement { $t = $pathElement.t; })*
@@ -950,7 +950,9 @@ pathElement returns [int t]
         )
         namePart
         { $t = 1; }
-
+    |
+        DOT nls NEW creator[1]
+        { $t = 6; }
     |   arguments
         { $t = 2; }
 
@@ -1021,7 +1023,7 @@ primary
         identifier typeArguments?                                              
             #identifierPrmrAlt
     |   literal                                                                
             #literalPrmrAlt
     |   gstring                                                                
             #gstringPrmrAlt
-    |   NEW nls creator                                                        
             #newPrmrAlt
+    |   NEW nls creator[0]                                                     
             #newPrmrAlt
     |   THIS                                                                   
             #thisPrmrAlt
     |   SUPER                                                                  
             #superPrmrAlt
     |   parExpression                                                          
             #parenPrmrAlt
@@ -1058,11 +1060,14 @@ mapEntryLabel
     |   primary
     ;
 
-creator
+/**
+ *  t 0: general creation; 1: non-static inner class creation
+ */
+creator[int t]
     :   createdName
-        (   nls arguments anonymousInnerClassDeclaration[0]?
-        |   (annotationsOpt LBRACK expression RBRACK)+ dimsOpt
-        |   dims nls arrayInitializer
+        (   {0 == $t || 1 == $t}? nls arguments 
anonymousInnerClassDeclaration[0]?
+        |   {0 == $t}?            (annotationsOpt LBRACK expression RBRACK)+ 
dimsOpt
+        |   {0 == $t}?            dims nls arrayInitializer
         )
     ;
 

http://git-wip-us.apache.org/repos/asf/groovy/blob/bc254b19/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 0776856..2372d44 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
@@ -2293,6 +2293,13 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> implements Groov
             }
         }
 
+        if (asBoolean(ctx.creator())) {
+            CreatorContext creatorContext = ctx.creator();
+            creatorContext.putNodeMetaData(ENCLOSING_INSTANCE_EXPRESSION, 
baseExpr);
+
+            return configureAST(this.visitCreator(creatorContext), ctx);
+        }
+
         if (asBoolean(ctx.indexPropertyArgs())) { // e.g. list[1, 3, 5]
             Tuple2<Token, Expression> tuple = 
this.visitIndexPropertyArgs(ctx.indexPropertyArgs());
             boolean isSafeChain = isTrue(baseExpr, 
PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN);
@@ -3147,9 +3154,19 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> implements Groov
     @Override
     public Expression visitCreator(CreatorContext ctx) {
         ClassNode classNode = this.visitCreatedName(ctx.createdName());
-        Expression arguments = this.visitArguments(ctx.arguments());
 
         if (asBoolean(ctx.arguments())) { // create instance of class
+            Expression arguments = this.visitArguments(ctx.arguments());
+            Expression enclosingInstanceExpression = 
ctx.getNodeMetaData(ENCLOSING_INSTANCE_EXPRESSION);
+
+            if (null != enclosingInstanceExpression) {
+                if (arguments instanceof ArgumentListExpression) {
+                    ((ArgumentListExpression) 
arguments).getExpressions().add(0, enclosingInstanceExpression);
+                } else if (arguments instanceof TupleExpression || arguments 
instanceof NamedArgumentListExpression) {
+                    throw createParsingFailedException("Creating instance of 
non-static class does not support named parameters", arguments);
+                }
+            }
+
             if (asBoolean(ctx.anonymousInnerClassDeclaration())) {
                 
ctx.anonymousInnerClassDeclaration().putNodeMetaData(ANONYMOUS_INNER_CLASS_SUPER_CLASS,
 classNode);
                 InnerClassNode anonymousInnerClassNode = 
this.visitAnonymousInnerClassDeclaration(ctx.anonymousInnerClassDeclaration());
@@ -4754,6 +4771,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> implements Groov
     private static final String ANONYMOUS_INNER_CLASS_SUPER_CLASS = 
"_ANONYMOUS_INNER_CLASS_SUPER_CLASS";
     private static final String INTEGER_LITERAL_TEXT = "_INTEGER_LITERAL_TEXT";
     private static final String FLOATING_POINT_LITERAL_TEXT = 
"_FLOATING_POINT_LITERAL_TEXT";
+    private static final String ENCLOSING_INSTANCE_EXPRESSION = 
"_ENCLOSING_INSTANCE_EXPRESSION";
 
     private static final String CLASS_NAME = "_CLASS_NAME";
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/bc254b19/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
----------------------------------------------------------------------
diff --git 
a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
 
b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
index 4701e77..8dae27e 100644
--- 
a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
+++ 
b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
@@ -383,6 +383,10 @@ class GroovyParserTest extends GroovyTestCase {
         doRunAndTestAntlr4('core/String_01x.groovy');
     }
 
+    void "test groovy core - NonStaticClass"() {
+        doRunAndTestAntlr4('core/NonStaticClass_01x.groovy');
+    }
+
     void "test groovy core - BUG"() {
         doRunAndTestAntlr4('bugs/BUG-GROOVY-4757.groovy')
         doRunAndTestAntlr4('bugs/BUG-GROOVY-5652.groovy')

http://git-wip-us.apache.org/repos/asf/groovy/blob/bc254b19/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
----------------------------------------------------------------------
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 c23e8f4..0fdef50 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
@@ -222,6 +222,10 @@ class SyntaxErrorTest extends GroovyTestCase {
         TestUtils.doRunAndShouldFail('fail/String_02x.groovy');
     }
 
+    void "test groovy core - NonStaticClass"() {
+        TestUtils.doRunAndShouldFail('fail/NonStaticClass_01x.groovy');
+    }
+
     /**************************************/
     static unzipScriptAndShouldFail(String entryName, List ignoreClazzList, 
Map<String, String> replacementsMap=[:], boolean toCheckNewParserOnly = false) {
         ignoreClazzList.addAll(TestUtils.COMMON_IGNORE_CLASS_LIST)

http://git-wip-us.apache.org/repos/asf/groovy/blob/bc254b19/subprojects/parser-antlr4/src/test/resources/core/NonStaticClass_01x.groovy
----------------------------------------------------------------------
diff --git 
a/subprojects/parser-antlr4/src/test/resources/core/NonStaticClass_01x.groovy 
b/subprojects/parser-antlr4/src/test/resources/core/NonStaticClass_01x.groovy
new file mode 100644
index 0000000..007978a
--- /dev/null
+++ 
b/subprojects/parser-antlr4/src/test/resources/core/NonStaticClass_01x.groovy
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+public class Y {
+    public class X {
+        def name
+
+        public X(String name) {
+            this.name = name
+        }
+    }
+
+    public static Y createY() {
+        return new Y()
+    }
+
+    public static X createX(Y y) {
+        return y.new X('Daniel')
+    }
+
+    public static X createX() {
+        return createY().new X('Daniel')
+    }
+
+    public static String getXName() {
+        return createY().new X('Daniel').name
+    }
+
+    public static String getXName2() {
+        return createY().
+                        new X('Daniel')
+                                        .name
+    }
+}
+
+def createY() {
+    return new Y()
+}
+
+assert 'Daniel' == Y.createX(new Y()).name
+assert 'Daniel' == Y.createX().name
+assert 'Daniel' == Y.getXName()
+assert 'Daniel' == Y.getXName2()

http://git-wip-us.apache.org/repos/asf/groovy/blob/bc254b19/subprojects/parser-antlr4/src/test/resources/fail/NonStaticClass_01x.groovy
----------------------------------------------------------------------
diff --git 
a/subprojects/parser-antlr4/src/test/resources/fail/NonStaticClass_01x.groovy 
b/subprojects/parser-antlr4/src/test/resources/fail/NonStaticClass_01x.groovy
new file mode 100644
index 0000000..5774e6e
--- /dev/null
+++ 
b/subprojects/parser-antlr4/src/test/resources/fail/NonStaticClass_01x.groovy
@@ -0,0 +1,33 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+public class Y {
+    public class X {
+        def name
+
+        public X(String name) {
+            this.name = name
+        }
+    }
+
+    public static X createX(Y y) {
+        return y.new X(name:'Daniel')
+    }
+}
+assert 'Daniel' == Y.createX(new Y()).name

Reply via email to