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 2021/03/02 17:50:34 UTC

[groovy] branch GROOVY_3_0_X updated: GROOVY-9707: CompileStatic by configuration + TypeChecked by annotation

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


The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new f7778bd  GROOVY-9707: CompileStatic by configuration + TypeChecked by annotation
f7778bd is described below

commit f7778bd422e802a07d15cb237a20e08e100a4d13
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Jan 24 23:25:11 2021 -0600

    GROOVY-9707: CompileStatic by configuration + TypeChecked by annotation
---
 .../transform/sc/StaticCompileTransformation.java  | 33 +++++++++++-----------
 .../transform/stc/StaticTypeCheckingVisitor.java   |  1 +
 .../sc/TypeCheckingModeStaticCompileTest.groovy    | 21 ++++++++++----
 3 files changed, 34 insertions(+), 21 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompileTransformation.java b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompileTransformation.java
index 906ccd8..b2857f3 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompileTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompileTransformation.java
@@ -49,27 +49,29 @@ public class StaticCompileTransformation extends StaticTypesTransformation {
 
     @Override
     public void visit(final ASTNode[] nodes, final SourceUnit source) {
-        AnnotationNode annotationInformation = (AnnotationNode) nodes[0];
-        AnnotatedNode node = (AnnotatedNode) nodes[1];
-        StaticTypeCheckingVisitor visitor = null;
-        Map<String,Expression> members = annotationInformation.getMembers();
+        AnnotatedNode target = (AnnotatedNode) nodes[1];
+        if (Boolean.TRUE.equals(target.getNodeMetaData(StaticTypeCheckingVisitor.class))) {
+            return;
+        }
+        Map<String,Expression> members = ((AnnotationNode) nodes[0]).getMembers();
         Expression extensions = members.get("extensions");
-        if (node instanceof ClassNode) {
-            ClassNode classNode = (ClassNode) node;
+        StaticTypeCheckingVisitor visitor = null;
+        if (target instanceof ClassNode) {
+            ClassNode classNode = (ClassNode) target;
             visitor = newVisitor(source, classNode);
             visitor.setCompilationUnit(compilationUnit);
             addTypeCheckingExtensions(visitor, extensions);
             classNode.putNodeMetaData(WriterControllerFactory.class, factory);
-            node.putNodeMetaData(STATIC_COMPILE_NODE, !visitor.isSkipMode(node));
+            target.putNodeMetaData(STATIC_COMPILE_NODE, !visitor.isSkipMode(target));
             visitor.initialize();
             visitor.visitClass(classNode);
-        } else if (node instanceof MethodNode) {
-            MethodNode methodNode = (MethodNode) node;
+        } else if (target instanceof MethodNode) {
+            MethodNode methodNode = (MethodNode) target;
             ClassNode declaringClass = methodNode.getDeclaringClass();
             visitor = newVisitor(source, declaringClass);
             visitor.setCompilationUnit(compilationUnit);
             addTypeCheckingExtensions(visitor, extensions);
-            methodNode.putNodeMetaData(STATIC_COMPILE_NODE, !visitor.isSkipMode(node));
+            methodNode.putNodeMetaData(STATIC_COMPILE_NODE, !visitor.isSkipMode(target));
             if (declaringClass.getNodeMetaData(WriterControllerFactory.class) == null) {
                 declaringClass.putNodeMetaData(WriterControllerFactory.class, factory);
             }
@@ -77,17 +79,16 @@ public class StaticCompileTransformation extends StaticTypesTransformation {
             visitor.initialize();
             visitor.visitMethod(methodNode);
         } else {
-            source.addError(new SyntaxException(STATIC_ERROR_PREFIX + "Unimplemented node type",
-                    node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()));
+            source.addError(new SyntaxException(STATIC_ERROR_PREFIX + "Unimplemented node type", target));
         }
         if (visitor != null) {
             visitor.performSecondPass();
         }
         StaticCompilationTransformer transformer = new StaticCompilationTransformer(source, visitor);
-        if (node instanceof ClassNode) {
-            transformer.visitClass((ClassNode) node);
-        } else if (node instanceof MethodNode) {
-            transformer.visitMethod((MethodNode) node);
+        if (target instanceof ClassNode) {
+            transformer.visitClass((ClassNode) target);
+        } else if (target instanceof MethodNode) {
+            transformer.visitMethod((MethodNode) target);
         }
     }
 
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index c3190a8..82a9f9c 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -413,6 +413,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             }
 
             node.putNodeMetaData(INFERRED_TYPE, node);
+            node.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE);
             // mark all methods as visited. We can't do this in visitMethod because the type checker
             // works in a two pass sequence and we don't want to skip the second pass
             node.getMethods().forEach(n -> n.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE));
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/TypeCheckingModeStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/TypeCheckingModeStaticCompileTest.groovy
index 93332bf..3b50ec4 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/TypeCheckingModeStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/TypeCheckingModeStaticCompileTest.groovy
@@ -23,11 +23,11 @@ import groovy.transform.stc.TypeCheckingModeTest
 /**
  * Unit tests for static type checking : type checking mode.
  */
-class TypeCheckingModeStaticCompileTest extends TypeCheckingModeTest implements StaticCompilationTestSupport {
+final class TypeCheckingModeStaticCompileTest extends TypeCheckingModeTest implements StaticCompilationTestSupport {
 
     void testEnsureBytecodeIsDifferentWhenSkipped() {
         assertScript '''
-            // transparent @CompileStatic
+            // @CompileStatic is implicit
             String foo() { 'foo'.toUpperCase() }
 
             @groovy.transform.CompileStatic(groovy.transform.TypeCheckingMode.SKIP)
@@ -51,8 +51,7 @@ class TypeCheckingModeStaticCompileTest extends TypeCheckingModeTest implements
             public interface HibernateCallback<T> {
                 T doInHibernate()
             }
-
-            @CompileStatic
+            // @CompileStatic is implicit
             class Enclosing {
                 @CompileStatic(groovy.transform.TypeCheckingMode.SKIP)
                 def shouldBeSkipped(Closure callable) {
@@ -69,5 +68,17 @@ class TypeCheckingModeStaticCompileTest extends TypeCheckingModeTest implements
             }
         '''
     }
-}
 
+    // GROOVY-9707: CompileStatic by configuration and TypeChecked by annotation
+    void testTypeCheckedAnnotation() {
+        assertScript '''
+            @groovy.transform.TypeChecked
+            class C {
+                def m() {
+                    'a' + 'b'
+                }
+            }
+            assert new C().m() == 'ab'
+        '''
+    }
+}