groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pa...@apache.org
Subject [groovy] branch master updated: GROOVY-9203: anonymous inners start at "$1" for each enclosing class (closes #981)
Date Thu, 25 Jul 2019 07:54:17 GMT
This is an automated email from the ASF dual-hosted git repository.

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


The following commit(s) were added to refs/heads/master by this push:
     new de3ac29  GROOVY-9203: anonymous inners start at "$1" for each enclosing class (closes
#981)
de3ac29 is described below

commit de3ac293ca0f120ac917579d624117d2e801a291
Author: Eric Milles <eric.milles@thomsonreuters.com>
AuthorDate: Tue Jul 23 13:13:14 2019 -0500

    GROOVY-9203: anonymous inners start at "$1" for each enclosing class (closes #981)
---
 .../codehaus/groovy/antlr/AntlrParserPlugin.java   | 29 +++++++++--------
 .../{Groovy7973Bug.groovy => Groovy7973.groovy}    | 34 ++++++++++++--------
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 36 +++++++++++-----------
 3 files changed, 54 insertions(+), 45 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
index dee0a95..c8f97d4 100644
--- a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
+++ b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
@@ -178,7 +178,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin,
Groovy
     private ClassNode classNode;
     private MethodNode methodNode;
     private String[] tokenNames;
-    private int innerClassCounter = 1;
     private boolean enumConstantBeingDef = false;
     private boolean forStatementBeingDef = false;
     private boolean annotationBeingDef = false;
@@ -530,10 +529,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin,
Groovy
     }
 
     protected void interfaceDef(AST classDef) {
-        int oldInnerClassCounter = innerClassCounter;
         innerInterfaceDef(classDef);
         classNode = null;
-        innerClassCounter = oldInnerClassCounter;
     }
 
     protected void innerInterfaceDef(AST classDef) {
@@ -578,21 +575,16 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin,
Groovy
         classNode.setGenericsTypes(genericsType);
         configureAST(classNode, classDef);
 
-        int oldClassCount = innerClassCounter;
-
         assertNodeType(OBJBLOCK, node);
         objectBlock(node);
         output.addClass(classNode);
 
         classNode = outerClass;
-        innerClassCounter = oldClassCount;
     }
 
     protected void classDef(AST classDef) {
-        int oldInnerClassCounter = innerClassCounter;
         innerClassDef(classDef);
         classNode = null;
-        innerClassCounter = oldInnerClassCounter;
     }
 
     private ClassNode getClassOrScript(ClassNode node) {
@@ -600,15 +592,25 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin,
Groovy
         return output.getScriptClassDummy();
     }
 
+    private static int anonymousClassCount(ClassNode node) {
+        int count = 0;
+        for (Iterator<InnerClassNode> it = node.getInnerClasses(); it.hasNext();) {
+            InnerClassNode innerClass = it.next();
+            if (innerClass.isAnonymous()) {
+                count += 1;
+            }
+        }
+        return count;
+    }
+
     protected Expression anonymousInnerClassDef(AST node) {
         ClassNode oldNode = classNode;
         ClassNode outerClass = getClassOrScript(oldNode);
-        String fullName = outerClass.getName() + '$' + innerClassCounter;
-        innerClassCounter++;
+        String innerClassName = outerClass.getName() + '$' + (anonymousClassCount(outerClass)
+ 1);
         if (enumConstantBeingDef) {
-            classNode = new EnumConstantClassNode(outerClass, fullName, Opcodes.ACC_PUBLIC,
ClassHelper.OBJECT_TYPE);
+            classNode = new EnumConstantClassNode(outerClass, innerClassName, Opcodes.ACC_PUBLIC,
ClassHelper.OBJECT_TYPE);
         } else {
-            classNode = new InnerClassNode(outerClass, fullName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
+            classNode = new InnerClassNode(outerClass, innerClassName, Opcodes.ACC_PUBLIC,
ClassHelper.OBJECT_TYPE);
         }
         ((InnerClassNode) classNode).setAnonymous(true);
         classNode.setEnclosingMethod(methodNode);
@@ -685,13 +687,10 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin,
Groovy
         // have here to ensure it won't be the inner class
         output.addClass(classNode);
 
-        int oldClassCount = innerClassCounter;
-
         assertNodeType(OBJBLOCK, node);
         objectBlock(node);
 
         classNode = outerClass;
-        innerClassCounter = oldClassCount;
     }
 
     protected void objectBlock(AST objectBlock) {
diff --git a/src/test/groovy/bugs/Groovy7973Bug.groovy b/src/test/groovy/bugs/Groovy7973.groovy
similarity index 75%
rename from src/test/groovy/bugs/Groovy7973Bug.groovy
rename to src/test/groovy/bugs/Groovy7973.groovy
index a6ab96c..9c05c5b 100644
--- a/src/test/groovy/bugs/Groovy7973Bug.groovy
+++ b/src/test/groovy/bugs/Groovy7973.groovy
@@ -18,41 +18,47 @@
  */
 package groovy.bugs
 
-class Groovy7973Bug extends GroovyTestCase {
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy7973 {
 
     private static final String SCRIPT1 = '''
         class Test {
             def op1() { 'A'.with{ this.class.name } }
             def op2a() { new Object() { def inner() {
-                this.class.name + Test.this.class.name
+                Test.this.class.name + '::' + this.class.name
             } } }
             def op2b() { new Object() { def inner() {
-                'B'.with{ this.class.name + Test.this.class.name }
+                'B'.with { Test.this.class.name + '::' + this.class.name }
             } } }
             def op3a() { new Object() { def inner() { new Object() { def innerinner() {
-                this.class.name + Test$3.this.class.name + Test.this.class.name
+                Test.this.class.name + '::' + this.class.name
             } } } } }
             def op3b() { new Object() { def inner() { new Object() { def innerinner() {
-                'C'.with{ this.class.name + Test$5.this.class.name + Test.this.class.name
}
+                'C'.with { Test.this.class.name + '::' + this.class.name }
             } } } } }
         }
 
         def t = new Test()
         assert t.op1() == 'Test'
-        assert t.op2a().inner() == 'Test$1Test'
-        assert t.op2b().inner() == 'Test$2Test'
-        assert t.op3a().inner().innerinner() == 'Test$3$4Test$3Test'
-        assert t.op3b().inner().innerinner() == 'Test$5$6Test$5Test'
+        assert t.op2a().inner() == 'Test::Test$1'
+        assert t.op2b().inner() == 'Test::Test$2'
+        assert t.op3a().inner().innerinner() == 'Test::Test$3$1'
+        assert t.op3b().inner().innerinner() == 'Test::Test$4$1'
     '''
 
     private static final String SCRIPT2 = '''
         class Test {
             def op1() { this }
-            def op2() { ''.with{ this } }
+            def op2() { ''.with { this } }
             def op3() { new Object() { def inner() { this } } }
-            def op4() { new Object() { def inner() { ''.with{ this } } } }
+            def op4() { new Object() { def inner() { ''.with { this } } } }
             def op5() { new Object() { def inner() { Test.this } } }
-            def op6() { new Object() { def inner() { ''.with{ Test.this } } } }
+            def op6() { new Object() { def inner() { ''.with { Test.this } } } }
             class Inner {
                 def inner1() { this }
                 def inner2() { ''.with { this } }
@@ -76,18 +82,22 @@ class Groovy7973Bug extends GroovyTestCase {
         assert inner.inner4().class.name == 'Test'
     '''
 
+    @Test
     void testClassDotThis() {
         assertScript SCRIPT1
     }
 
+    @Test
     void testClassDotThis_CS() {
         assertScript '@groovy.transform.CompileStatic\n' + SCRIPT1
     }
 
+    @Test
     void testClassDotThisAIC() {
         assertScript SCRIPT2
     }
 
+    @Test
     void testClassDotThisAIC_CS() {
         assertScript '@groovy.transform.CompileStatic\n' + SCRIPT2
     }
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 bd93781..5cb8e59 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
@@ -130,13 +130,14 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Deque;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
-import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -1251,12 +1252,10 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object>
implements Groov
             classNodeList.add(classNode);
         }
 
-        int oldAnonymousInnerClassCounter = this.anonymousInnerClassCounter;
         classNodeStack.push(classNode);
         ctx.classBody().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
         this.visitClassBody(ctx.classBody());
         classNodeStack.pop();
-        this.anonymousInnerClassCounter = oldAnonymousInnerClassCounter;
 
         if (!(asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT()))) {
             classNodeList.add(classNode);
@@ -3288,33 +3287,36 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object>
implements Groov
     }
 
 
-    private String genAnonymousClassName(String outerClassName) {
-        return outerClassName + "$" + this.anonymousInnerClassCounter++;
+    private static String nextAnonymousClassName(ClassNode outerClass) {
+        int anonymousClassCount = 0;
+        for (Iterator<InnerClassNode> it = outerClass.getInnerClasses(); it.hasNext();)
{
+            InnerClassNode innerClass = it.next();
+            if (innerClass.isAnonymous()) {
+                anonymousClassCount += 1;
+            }
+        }
+
+        return outerClass.getName() + "$" + (anonymousClassCount + 1);
     }
 
     @Override
     public InnerClassNode visitAnonymousInnerClassDeclaration(AnonymousInnerClassDeclarationContext
ctx) {
-        ClassNode superClass = ctx.getNodeMetaData(ANONYMOUS_INNER_CLASS_SUPER_CLASS);
-        Objects.requireNonNull(superClass, "superClass should not be null");
+        ClassNode superClass = Objects.requireNonNull(ctx.getNodeMetaData(ANONYMOUS_INNER_CLASS_SUPER_CLASS),
"superClass should not be null");
+        ClassNode outerClass = Optional.ofNullable(classNodeStack.peek()).orElse(moduleNode.getScriptClassDummy());
+        String innerClassName = nextAnonymousClassName(outerClass);
 
         InnerClassNode anonymousInnerClass;
-
-        ClassNode outerClass = this.classNodeStack.peek();
-        outerClass = asBoolean(outerClass) ? outerClass : moduleNode.getScriptClassDummy();
-
-        String fullName = this.genAnonymousClassName(outerClass.getName());
         if (1 == ctx.t) { // anonymous enum
-            anonymousInnerClass = new EnumConstantClassNode(outerClass, fullName, superClass.getModifiers()
| Opcodes.ACC_FINAL, superClass.getPlainNodeReference());
-
+            anonymousInnerClass = new EnumConstantClassNode(outerClass, innerClassName, superClass.getModifiers()
| Opcodes.ACC_FINAL, superClass.getPlainNodeReference());
             // and remove the final modifier from classNode to allow the sub class
             superClass.setModifiers(superClass.getModifiers() & ~Opcodes.ACC_FINAL);
         } else { // anonymous inner class
-            anonymousInnerClass = new InnerClassNode(outerClass, fullName, Opcodes.ACC_PUBLIC,
superClass);
+            anonymousInnerClass = new InnerClassNode(outerClass, innerClassName, Opcodes.ACC_PUBLIC,
superClass);
         }
 
         anonymousInnerClass.setUsingGenerics(false);
         anonymousInnerClass.setAnonymous(true);
-        anonymousInnerClass.putNodeMetaData(CLASS_NAME, fullName);
+        anonymousInnerClass.putNodeMetaData(CLASS_NAME, innerClassName);
         configureAST(anonymousInnerClass, ctx);
 
         classNodeStack.push(anonymousInnerClass);
@@ -4777,7 +4779,6 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object>
implements Groov
     private final List<ClassNode> classNodeList = new LinkedList<>();
     private final Deque<ClassNode> classNodeStack = new ArrayDeque<>();
     private final Deque<List<InnerClassNode>> anonymousInnerClassesDefinedInMethodStack
= new ArrayDeque<>();
-    private int anonymousInnerClassCounter = 1;
 
     private Tuple2<GroovyParserRuleContext, Exception> numberFormatError;
 
@@ -4819,7 +4820,6 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object>
implements Groov
 
     private static final String GROOVY_TRANSFORM_TRAIT = "groovy.transform.Trait";
     private static final Set<String> PRIMITIVE_TYPE_SET = Collections.unmodifiableSet(new
HashSet<>(Arrays.asList("boolean", "char", "byte", "short", "int", "long", "float",
"double")));
-    private static final Logger LOGGER = Logger.getLogger(AstBuilder.class.getName());
 
     private static final String INSIDE_PARENTHESES_LEVEL = "_INSIDE_PARENTHESES_LEVEL";
 


Mime
View raw message