You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2023/02/03 18:39:37 UTC

[groovy] 01/02: GROOVY-10238: `@CompileDynamic` outer class `@CompileStatic` inner class

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

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

commit 5c63a088617da6aaafd1e2c864f276d915c8b679
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Feb 3 11:48:49 2023 -0600

    GROOVY-10238: `@CompileDynamic` outer class `@CompileStatic` inner class
    
    3_0_X backport
---
 .../codehaus/groovy/ast/expr/FieldExpression.java  |  2 +-
 .../transform/sc/StaticCompilationVisitor.java     | 14 +++++----
 .../classgen/asm/sc/StaticCompileDGMTest.groovy    | 34 +++++++++++++++++-----
 3 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java
index c221dfc80e..78a4c028a3 100644
--- a/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java
+++ b/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java
@@ -84,6 +84,6 @@ public class FieldExpression extends Expression {
 
     @Override
     public String toString() {
-        return "field(" + getType() + " " + getFieldName() + ")";
+        return "field(" + getType().toString(false) + " " + getFieldName() + ")";
     }
 }
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
index a626f73385..59e8f2a6b8 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
@@ -66,6 +66,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 
+import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.hasAnnotation;
 import static org.codehaus.groovy.ast.ClassHelper.Character_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.LIST_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
@@ -186,13 +187,14 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
 
         ClassNode previousClassNode = classNode; classNode = node;
 
-        classNode.getInnerClasses().forEachRemaining(innerClassNode -> {
-            boolean innerStaticCompile = !(skip || isSkippedInnerClass(innerClassNode));
-            innerClassNode.putNodeMetaData(STATIC_COMPILE_NODE, Boolean.valueOf(innerStaticCompile));
-            innerClassNode.putNodeMetaData(WriterControllerFactory.class, node.getNodeMetaData(WriterControllerFactory.class));
-            if (innerStaticCompile && !anyMethodSkip(innerClassNode)) {
-                innerClassNode.putNodeMetaData(MopWriter.Factory.class, StaticCompilationMopWriter.FACTORY);
+        node.getInnerClasses().forEachRemaining(innerClass -> {
+            boolean isSC = !isSkipMode(innerClass) && (isStaticallyCompiled(node) || hasAnnotation(innerClass, COMPILESTATIC_CLASSNODE));
+            // GROOVY-10238: @CompileDynamic outer class, @CompileStatic inner class ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+            innerClass.putNodeMetaData(STATIC_COMPILE_NODE, Boolean.valueOf(isSC));
+            if (isSC && !anyMethodSkip(innerClass)) {
+                innerClass.putNodeMetaData(MopWriter.Factory.class, StaticCompilationMopWriter.FACTORY);
             }
+            innerClass.putNodeMetaData(WriterControllerFactory.class, node.getNodeMetaData(WriterControllerFactory.class));
         });
         super.visitClass(node);
         addPrivateFieldAndMethodAccessors(node);
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompileDGMTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompileDGMTest.groovy
index 732497866e..ad0dd6899a 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompileDGMTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompileDGMTest.groovy
@@ -21,13 +21,34 @@ package org.codehaus.groovy.classgen.asm.sc
 import groovy.transform.stc.DefaultGroovyMethodsSTCTest
 
 /**
- * Unit tests for static compilation: DGM method calls.
+ * Unit tests for static compilation: default groovy methods.
  */
-class StaticCompileDGMTest extends DefaultGroovyMethodsSTCTest implements StaticCompilationTestSupport {
+final class StaticCompileDGMTest extends DefaultGroovyMethodsSTCTest implements StaticCompilationTestSupport {
+
+    // GROOVY-10238
+    void testMapWithDefault() {
+        assertScript '''
+            import groovy.transform.*
+
+            @CompileDynamic
+            class Outer {
+                @Canonical
+                @CompileStatic
+                static class Inner {
+                    Map map = [:].withDefault { new Object() } // NoSuchMethodError: java.util.Map.withDefault(Lgroovy/lang/Closure;)
+                }
+            }
+
+            def obj = new Outer.Inner()
+            assert obj.toString() == 'Outer$Inner([:])'
+            assert obj.map['foo'] != null
+            assert obj.toString() != 'Outer$Inner([:])'
+        '''
+    }
 
     void testThreadDotStart() {
         assertScript '''
-            @ASTTest(phase = INSTRUCTION_SELECTION, value = {
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
                 lookup('start').each {
                     def target = it.expression.target
                     assert target instanceof org.codehaus.groovy.transform.stc.ExtensionMethodNode
@@ -37,14 +58,13 @@ class StaticCompileDGMTest extends DefaultGroovyMethodsSTCTest implements Static
                     assert target.returnType.nameWithoutPackage == 'Thread'
                 }
             })
-            void foo() {
-                start:
+            void test() {
+              start:
                 Thread.start {
                     println 'ok'
                 }
             }
-            foo()
+            test()
         '''
     }
 }
-