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/08/19 15:43:37 UTC

[groovy] branch GROOVY_3_0_X updated (6ed96b1 -> 5daebe3)

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

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


    from 6ed96b1  GROOVY-10106: trait field init may call trait method(s) so process first
     new bd50767  GROOVY-10107: STC: check assign null before type parameter compatibility
     new 2ebcc54  GROOVY-9985, GROOVY-9994, GROOVY-10111: STC: check array sizes and values (not like cast)
     new d3ca22e  GROOVY-10112: IndexedProperty AST transform should only provide the getter for immutable fields
     new fc02ed9  GROOVY-10113: check class cycle for outer types and type parameters
     new 5daebe3  remove test case

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/groovy/transform/IndexedProperty.java     |  3 +-
 .../codehaus/groovy/control/ResolveVisitor.java    | 86 +++++++++++---------
 .../transform/ImmutableASTTransformation.java      |  2 +
 .../IndexedPropertyASTTransformation.java          |  7 +-
 .../transform/stc/StaticTypeCheckingSupport.java   | 11 ++-
 .../transform/stc/StaticTypeCheckingVisitor.java   | 22 +++--
 src/test/groovy/bugs/Groovy10113.groovy            | 94 ++++++++++++++++++++++
 .../{Groovy1465Bug.groovy => Groovy1465.groovy}    | 39 +++++----
 .../{Groovy3904Bug.groovy => Groovy3904.groovy}    | 55 ++++++-------
 .../{Groovy8048Bug.groovy => Groovy8048.groovy}    | 32 ++++----
 .../stc/ArraysAndCollectionsSTCTest.groovy         | 34 +++++++-
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 14 ++++
 .../transform/IndexedPropertyTransformTest.groovy  | 30 ++++++-
 13 files changed, 303 insertions(+), 126 deletions(-)
 create mode 100644 src/test/groovy/bugs/Groovy10113.groovy
 rename src/test/groovy/bugs/{Groovy1465Bug.groovy => Groovy1465.groovy} (63%)
 rename src/test/groovy/bugs/{Groovy3904Bug.groovy => Groovy3904.groovy} (62%)
 rename src/test/groovy/bugs/{Groovy8048Bug.groovy => Groovy8048.groovy} (65%)

[groovy] 02/05: GROOVY-9985, GROOVY-9994, GROOVY-10111: STC: check array sizes and values (not like cast)

Posted by em...@apache.org.
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 2ebcc54bb52c1936387465cc926651a2efc1949d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed May 26 17:22:25 2021 -0500

    GROOVY-9985, GROOVY-9994, GROOVY-10111: STC: check array sizes and values (not like cast)
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 22 +++++++-----
 .../stc/ArraysAndCollectionsSTCTest.groovy         | 40 ++++++++++++++++++++--
 2 files changed, 51 insertions(+), 11 deletions(-)

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 26a9385..4afb2ec 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4091,14 +4091,20 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
-    public void visitArrayExpression(ArrayExpression source) {
-        super.visitArrayExpression(source);
-        ClassNode elementType = source.getElementType();
-        for (Expression expression : source.getExpressions()) {
-            if (!checkCast(elementType, expression)) {
-                addStaticTypeError("Cannot assign value of type " +
-                        prettyPrintType(getType(expression)) + " into array of type " +
-                        prettyPrintType(source.getType()), expression);
+    public void visitArrayExpression(final ArrayExpression expression) {
+        super.visitArrayExpression(expression);
+        ClassNode elementType;
+        List<Expression> expressions;
+        if (expression.hasInitializer()) {
+            elementType = expression.getElementType();
+            expressions = expression.getExpressions();
+        } else {
+            elementType = int_TYPE;
+            expressions = expression.getSizeExpression();
+        }
+        for (Expression elementExpr : expressions) {
+            if (!checkCompatibleAssignmentTypes(elementType, getType(elementExpr), elementExpr, false)) {
+                addStaticTypeError("Cannot convert from " + prettyPrintType(getType(elementExpr)) + " to " + prettyPrintType(elementType), elementExpr);
             }
         }
     }
diff --git a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
index fb0d2ab..716b1a8 100644
--- a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
@@ -28,10 +28,11 @@ class ArraysAndCollectionsSTCTest extends StaticTypeCheckingTestCase {
         assertScript '''
             String[] strings = ['a','b','c']
             String str = strings[0]
+            assert str == 'a'
         '''
     }
 
-    void testArrayElementReturnType() {
+    void testArrayElementTypeInference() {
         shouldFailWithMessages '''
             String[] strings = ['a','b','c']
             int str = strings[0]
@@ -44,10 +45,43 @@ class ArraysAndCollectionsSTCTest extends StaticTypeCheckingTestCase {
         ''', 'Cannot assign value of type java.lang.String into array of type int[]'
     }
 
+    // GROOVY-9985, GROOVY-9994
     void testWrongComponentTypeInArrayInitializer() {
         shouldFailWithMessages '''
-            int[] intArray = new int[]{'a'}
-        ''', 'Cannot assign value of type java.lang.String into array of type int[]'
+            new int['a']
+        ''', 'Cannot convert from java.lang.String to int'
+        shouldFailWithMessages '''
+            new int[]{'a'}
+        ''', 'Cannot convert from java.lang.String to int'
+        shouldFailWithMessages '''
+            new Integer[]{new Object(),1}
+        ''', 'Cannot convert from java.lang.Object to java.lang.Integer'
+    }
+
+    // GROOVY-10111
+    void testBoundedComponentTypeInArrayInitializer() {
+        assertScript '''
+            class C<X, Y> {
+            }
+            def <X extends C<Number, String>> X[] m() {
+                new X[]{new C<Number, String>()}
+            }
+        '''
+        shouldFailWithMessages '''
+            class C<X, Y> {
+            }
+            def <X extends C<Number, String>> X[] m() {
+                new X[]{new C<Object, String>()}
+            }
+        ''', 'Cannot convert from C<java.lang.Object, java.lang.String> to X'
+    }
+
+    void testConvertibleTypesInArrayInitializer() {
+        assertScript '''
+            def strings = new String[]{1,(long)2,(short)3}
+            assert strings.every { it.class == String }
+            assert strings.toString() == '[1, 2, 3]'
+        '''
     }
 
     void testAssignValueInArrayWithCorrectType() {

[groovy] 03/05: GROOVY-10112: IndexedProperty AST transform should only provide the getter for immutable fields

Posted by em...@apache.org.
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 d3ca22e7439ab226d6fa2eb20be09b94bdee428f
Author: Paul King <pa...@asert.com.au>
AuthorDate: Thu May 27 15:48:40 2021 +1000

    GROOVY-10112: IndexedProperty AST transform should only provide the
    getter for immutable fields
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/IndexedPropertyASTTransformation.java
---
 .../java/groovy/transform/IndexedProperty.java     |  3 ++-
 .../transform/ImmutableASTTransformation.java      |  2 ++
 .../IndexedPropertyASTTransformation.java          |  7 +++--
 .../transform/IndexedPropertyTransformTest.groovy  | 30 +++++++++++++++++++---
 4 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/src/main/java/groovy/transform/IndexedProperty.java b/src/main/java/groovy/transform/IndexedProperty.java
index 9ec47b4..d395ce4 100644
--- a/src/main/java/groovy/transform/IndexedProperty.java
+++ b/src/main/java/groovy/transform/IndexedProperty.java
@@ -28,7 +28,8 @@ import java.lang.annotation.Target;
 /**
  * Field annotation used with properties to provide an indexed getter and setter for the property.
  * Groovy provides nice GPath syntax support for accessing indexed properties but Java tools
- * or frameworks may expect the JavaBean style setters and getters.
+ * or frameworks may expect the JavaBean style getters and setters.
+ * Only the getter is produced when an immutable field can be determined.
  * <p>
  * <em>Example usage:</em> suppose you have a class with the following properties:
  * <pre>
diff --git a/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java
index b81046f..2b1a535 100644
--- a/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java
@@ -91,6 +91,7 @@ public class ImmutableASTTransformation extends AbstractASTTransformation implem
     private static final Class<? extends Annotation> MY_CLASS = ImmutableBase.class;
     public static final ClassNode MY_TYPE = makeWithoutCaching(MY_CLASS, false);
     private static final String MY_TYPE_NAME = MY_TYPE.getNameWithoutPackage();
+    public static final String IMMUTABLE_BREADCRUMB = "_IMMUTABLE_BREADCRUMB";
 
     private static final String MEMBER_ADD_COPY_WITH = "copyWith";
     private static final String COPY_WITH_METHOD = "copyWith";
@@ -220,6 +221,7 @@ public class ImmutableASTTransformation extends AbstractASTTransformation implem
     private static void adjustPropertyForImmutability(PropertyNode pNode, List<PropertyNode> newNodes, PropertyHandler handler) {
         final FieldNode fNode = pNode.getField();
         fNode.setModifiers((pNode.getModifiers() & (~ACC_PUBLIC)) | ACC_FINAL | ACC_PRIVATE);
+        fNode.setNodeMetaData(IMMUTABLE_BREADCRUMB, Boolean.TRUE);
         pNode.setSetterBlock(null);
         Statement getter = handler.createPropGetter(pNode);
         if (getter != null) {
diff --git a/src/main/java/org/codehaus/groovy/transform/IndexedPropertyASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/IndexedPropertyASTTransformation.java
index 6f30ab7..22ec5bb 100644
--- a/src/main/java/org/codehaus/groovy/transform/IndexedPropertyASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/IndexedPropertyASTTransformation.java
@@ -69,11 +69,14 @@ public class IndexedPropertyASTTransformation extends AbstractASTTransformation
                 return;
             }
             ClassNode fType = fNode.getType();
+            // TODO: consider looking for an initial value expression that is a call to asUnmodifiable() or an
+            // explicit call to Collections.unmodifiableList(). But currently that is processed one stage too early.
+            boolean immutable = Boolean.TRUE.equals(fNode.getNodeMetaData(ImmutableASTTransformation.IMMUTABLE_BREADCRUMB));
             if (fType.isArray()) {
-                addArraySetter(fNode);
+                if (!immutable) addArraySetter(fNode);
                 addArrayGetter(fNode);
             } else if (fType.isDerivedFrom(LIST_TYPE)) {
-                addListSetter(fNode);
+                if (!immutable) addListSetter(fNode);
                 addListGetter(fNode);
             } else {
                 addError("Error during " + MY_TYPE_NAME + " processing. Non-Indexable property '" + fNode.getName() +
diff --git a/src/test/org/codehaus/groovy/transform/IndexedPropertyTransformTest.groovy b/src/test/org/codehaus/groovy/transform/IndexedPropertyTransformTest.groovy
index e56e2b2..7b20fbe 100644
--- a/src/test/org/codehaus/groovy/transform/IndexedPropertyTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/IndexedPropertyTransformTest.groovy
@@ -26,7 +26,7 @@ import groovy.test.GroovyShellTestCase
 class IndexedPropertyTransformTest extends GroovyShellTestCase {
 
     void testStandardCase() {
-        assertScript """
+        assertScript '''
             import groovy.transform.IndexedProperty
             class Demo {
                 @IndexedProperty List<Integer> foo
@@ -46,11 +46,11 @@ class IndexedPropertyTransformTest extends GroovyShellTestCase {
             d.baz = ['cat']
             d.setBaz(0, 'dog')
             assert d.getBaz(0) == 'dog'
-        """
+        '''
     }
 
     void testWithCompileStatic() {
-        assertScript """
+        assertScript '''
             import groovy.transform.IndexedProperty
             @groovy.transform.CompileStatic
             class Demo {
@@ -71,7 +71,29 @@ class IndexedPropertyTransformTest extends GroovyShellTestCase {
             d.baz = ['cat']
             d.setBaz(0, 'dog')
             assert d.getBaz(0) == 'dog'
-        """
+        '''
+    }
+
+    void testReadOnlyProperty() {
+        assertScript '''
+            import groovy.transform.*
+            import static groovy.test.GroovyAssert.shouldFail
+
+            class Demo1 {
+                @IndexedProperty List<Integer> foo
+            }
+            @Immutable
+            class Demo2 {
+                @IndexedProperty List<Integer> foo
+            }
+
+            assert Demo1.getMethod('getFoo', int)
+            assert Demo1.getMethod('setFoo', int, Integer)
+            assert Demo2.getMethod('getFoo', int)
+            shouldFail(NoSuchMethodException) {
+                Demo2.getMethod('setFoo', int, Integer)
+            }
+        '''
     }
 
 }
\ No newline at end of file

[groovy] 04/05: GROOVY-10113: check class cycle for outer types and type parameters

Posted by em...@apache.org.
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 fc02ed9d7911917fd3ac88401e3e429f426e4d9d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Jun 6 16:19:45 2021 -0500

    GROOVY-10113: check class cycle for outer types and type parameters
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
---
 .../codehaus/groovy/control/ResolveVisitor.java    | 86 +++++++++++---------
 src/test/groovy/bugs/Groovy10113.groovy            | 94 ++++++++++++++++++++++
 .../{Groovy1465Bug.groovy => Groovy1465.groovy}    | 39 +++++----
 .../{Groovy3904Bug.groovy => Groovy3904.groovy}    | 55 ++++++-------
 .../{Groovy8048Bug.groovy => Groovy8048.groovy}    | 32 ++++----
 5 files changed, 205 insertions(+), 101 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index eb54daf..61c4235 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -73,6 +73,7 @@ import java.lang.annotation.Annotation;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.reflect.Modifier;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -1461,13 +1462,26 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
         }
 
         ClassNode sn = node.getUnresolvedSuperClass();
-        if (sn != null) resolveOrFail(sn, "", node, true);
-
-        for (ClassNode anInterface : node.getInterfaces()) {
-            resolveOrFail(anInterface, "", node, true);
+        if (sn != null) {
+            resolveOrFail(sn, "", node, true);
+        }
+        for (ClassNode in : node.getInterfaces()) {
+            resolveOrFail(in, "", node, true);
         }
 
-        checkCyclicInheritance(node, node.getUnresolvedSuperClass(), node.getInterfaces());
+        if (sn != null) checkCyclicInheritance(node, sn);
+        for (ClassNode in : node.getInterfaces()) {
+            checkCyclicInheritance(node, in);
+        }
+        if (node.getGenericsTypes() != null) {
+            for (GenericsType gt : node.getGenericsTypes()) {
+                if (gt != null && gt.getUpperBounds() != null) {
+                    for (ClassNode variant : gt.getUpperBounds()) {
+                        if (variant.isGenericsPlaceHolder()) checkCyclicInheritance(gt.getType().redirect(), variant);
+                    }
+                }
+            }
+        }
 
         super.visitClass(node);
 
@@ -1476,6 +1490,33 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
         currentClass = oldNode;
     }
 
+    private void checkCyclicInheritance(final ClassNode node, final ClassNode type) {
+        if (type.redirect() == node || type.getOuterClasses().contains(node)) {
+            addError("Cycle detected: the type " + node.getName() + " cannot extend/implement itself or one of its own member types", type);
+        } else if (type != ClassHelper.OBJECT_TYPE) {
+            Set<ClassNode> done = new HashSet<>();
+            done.add(ClassHelper.OBJECT_TYPE);
+            done.add(null);
+
+            LinkedList<ClassNode> todo = new LinkedList<>();
+            Collections.addAll(todo, type.getInterfaces());
+            todo.add(type.getUnresolvedSuperClass());
+            todo.add(type.getOuterClass());
+            do {
+                ClassNode next = todo.poll();
+                if (!done.add(next)) continue;
+                if (next.redirect() == node) {
+                    ClassNode cn = type; while (cn.getOuterClass() != null) cn = cn.getOuterClass();
+                    addError("Cycle detected: a cycle exists in the type hierarchy between " + node.getName() + " and " + cn.getName(), type);
+                    return;
+                }
+                Collections.addAll(todo, next.getInterfaces());
+                todo.add(next.getUnresolvedSuperClass());
+                todo.add(next.getOuterClass());
+            } while (!todo.isEmpty());
+        }
+    }
+
     // GROOVY-7812(#2): Static inner classes cannot be accessed from other files when running by 'groovy' command
     private void resolveOuterNestedClassFurther(final ClassNode node) {
         CompileUnit compileUnit = currentClass.getCompileUnit();
@@ -1507,41 +1548,6 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
         }
     }
 
-    private void checkCyclicInheritance(final ClassNode originalNode, final ClassNode parentToCompare, final ClassNode[] interfacesToCompare) {
-        if (!originalNode.isInterface()) {
-            if (parentToCompare == null) return;
-            if (originalNode == parentToCompare.redirect()) {
-                addError("Cyclic inheritance involving " + parentToCompare.getName() + " in class " + originalNode.getName(), originalNode);
-                return;
-            }
-            if (interfacesToCompare != null && interfacesToCompare.length > 0) {
-                for (ClassNode intfToCompare : interfacesToCompare) {
-                    if (originalNode == intfToCompare.redirect()) {
-                        addError("Cycle detected: the type " + originalNode.getName() + " cannot implement itself" , originalNode);
-                        return;
-                    }
-                }
-            }
-            if (parentToCompare == ClassHelper.OBJECT_TYPE) return;
-            checkCyclicInheritance(originalNode, parentToCompare.getUnresolvedSuperClass(), null);
-        } else {
-            if (interfacesToCompare != null && interfacesToCompare.length > 0) {
-                // check interfaces at this level first
-                for (ClassNode intfToCompare : interfacesToCompare) {
-                    if(originalNode == intfToCompare.redirect()) {
-                        addError("Cyclic inheritance involving " + intfToCompare.getName() + " in interface " + originalNode.getName(), originalNode);
-                        return;
-                    }
-                }
-                // check next level of interfaces
-                for (ClassNode intf : interfacesToCompare) {
-                    checkCyclicInheritance(originalNode, null, intf.getInterfaces());
-                }
-            }
-        }
-    }
-
-    @Override
     public void visitCatchStatement(final CatchStatement cs) {
         resolveOrFail(cs.getExceptionType(), cs);
         if (cs.getExceptionType() == ClassHelper.DYNAMIC_TYPE) {
diff --git a/src/test/groovy/bugs/Groovy10113.groovy b/src/test/groovy/bugs/Groovy10113.groovy
new file mode 100644
index 0000000..142f2f3
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy10113.groovy
@@ -0,0 +1,94 @@
+/*
+ *  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.
+ */
+package groovy.bugs
+
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.shouldFail
+
+final class Groovy10113 {
+
+    @Test
+    void testTypeParamCycle() {
+        def err = shouldFail '''
+            class C<T extends T> {
+            }
+        '''
+        assert err =~ /Cycle detected: the type T cannot extend.implement itself or one of its own member types/
+    }
+
+    @Test
+    void testInnerClassCycle1() {
+        def err = shouldFail '''
+            class C extends C.Inner {
+                class Inner {
+                }
+            }
+        '''
+        assert err =~ /Cycle detected: the type C cannot extend.implement itself or one of its own member types/
+    }
+
+    @Test
+    void testInnerClassCycle2() {
+        def err = shouldFail '''
+            class C extends D {
+                class Inner {
+                }
+            }
+            class D extends C.Inner {
+            }
+        '''
+        assert err =~ /Cycle detected: a cycle exists in the type hierarchy between D and C/
+    }
+
+    @Test
+    void testInnerInterfaceCycle1() {
+        def err = shouldFail '''
+            class C implements C.I {
+                interface I {
+                }
+            }
+        '''
+        assert err =~ /Cycle detected: the type C cannot extend.implement itself or one of its own member types/
+    }
+
+    @Test
+    void testInnerInterfaceCycle2() {
+        def err = shouldFail '''
+            class C extends D {
+              interface I {
+              }
+            }
+            class D implements C.I {
+            }
+        '''
+        assert err =~ /Cycle detected: a cycle exists in the type hierarchy between D and C/
+    }
+
+    @Test
+    void testClassExtendsInterfaceCycle() {
+        def err = shouldFail '''
+            interface A extends B {
+            }
+            class B extends A {
+            }
+        '''
+        assert err =~ /Cycle detected: a cycle exists in the type hierarchy between B and A/
+    }
+}
diff --git a/src/test/groovy/bugs/Groovy1465Bug.groovy b/src/test/groovy/bugs/Groovy1465.groovy
similarity index 63%
rename from src/test/groovy/bugs/Groovy1465Bug.groovy
rename to src/test/groovy/bugs/Groovy1465.groovy
index bef408a..fc40e09 100644
--- a/src/test/groovy/bugs/Groovy1465Bug.groovy
+++ b/src/test/groovy/bugs/Groovy1465.groovy
@@ -18,41 +18,40 @@
  */
 package groovy.bugs
 
-import groovy.test.GroovyTestCase
-import org.codehaus.groovy.control.MultipleCompilationErrorsException
+import org.junit.Test
 
-class Groovy1465Bug extends GroovyTestCase {
-    
-    void compileAndVerifyCyclicInheritenceCompilationError(script) {
-        try {
-            new GroovyShell().parse(script)
-            fail('The compilation should have failed as it is a cyclic reference')
-        } catch (MultipleCompilationErrorsException e) {
-            def syntaxError = e.errorCollector.getSyntaxError(0)
-            assert syntaxError.message.contains('Cyclic inheritance')
-        }
+import static groovy.test.GroovyAssert.shouldFail
+
+final class Groovy1465 {
+
+    private static void compileAndVerifyCyclicInheritenceCompilationError(String sourceCode) {
+        def err = shouldFail(sourceCode)
+        assert err =~ /Cycle detected/
     }
-    
+
+    @Test
     void testInterfaceCyclicInheritenceTC1() {
-        compileAndVerifyCyclicInheritenceCompilationError """
+        compileAndVerifyCyclicInheritenceCompilationError '''
             interface G1465Tt extends G1465Tt { }
             def tt = {} as G1465Tt
-        """ 
+        '''
     }
 
+    @Test
     void testInterfaceCyclicInheritenceTC2() {
-        compileAndVerifyCyclicInheritenceCompilationError """
+        compileAndVerifyCyclicInheritenceCompilationError '''
             interface G1465Rr extends G1465Ss { }
             interface G1465Ss extends G1465Rr { }
             def ss = {} as G1465Ss
-        """ 
+        '''
     }
 
+    @Test
     void testInterfaceCyclicInheritenceTC3() {
-        compileAndVerifyCyclicInheritenceCompilationError """
+        compileAndVerifyCyclicInheritenceCompilationError '''
             interface G1465A extends G1465B { }
             interface G1465B extends G1465C { }
             interface G1465C extends G1465B { }
-        """ 
+        '''
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/groovy/bugs/Groovy3904Bug.groovy b/src/test/groovy/bugs/Groovy3904.groovy
similarity index 62%
rename from src/test/groovy/bugs/Groovy3904Bug.groovy
rename to src/test/groovy/bugs/Groovy3904.groovy
index a8b7464..419d2f0 100644
--- a/src/test/groovy/bugs/Groovy3904Bug.groovy
+++ b/src/test/groovy/bugs/Groovy3904.groovy
@@ -18,68 +18,69 @@
  */
 package groovy.bugs
 
-import groovy.test.GroovyTestCase
-import org.codehaus.groovy.control.MultipleCompilationErrorsException
+import org.junit.Test
 
-class Groovy3904Bug extends GroovyTestCase {
-    
-    void compileAndVerifyCyclicInheritenceCompilationError(script) {
-        try {
-            new GroovyShell().parse(script)
-            fail('The compilation should have failed as it is a cyclic reference')
-        } catch (MultipleCompilationErrorsException e) {
-            def syntaxError = e.errorCollector.getSyntaxError(0)
-            assert syntaxError.message.contains('Cyclic inheritance')
-        }
+import static groovy.test.GroovyAssert.shouldFail
+
+final class Groovy3904 {
+
+    private static void compileAndVerifyCyclicInheritenceCompilationError(String sourceCode) {
+        def err = shouldFail(sourceCode)
+        assert err =~ /Cycle detected/
     }
-    
+
+    @Test
     void testCyclicInheritenceTC1() {
-        compileAndVerifyCyclicInheritenceCompilationError """
+        compileAndVerifyCyclicInheritenceCompilationError '''
             class G3904R1A extends G3904R1A {}
-        """ 
+        '''
     }
 
+    @Test
     void testCyclicInheritenceTC2() {
-        compileAndVerifyCyclicInheritenceCompilationError """
+        compileAndVerifyCyclicInheritenceCompilationError '''
             class G3904R2A extends G3904R2A {
                 public static void main(String []argv) {
                   print 'hey'
                 }
             }
-        """
+        '''
     }
 
     /* next 2 tests are similar but in reverse order */
+
+    @Test
     void testCyclicInheritenceTC3() {
-        compileAndVerifyCyclicInheritenceCompilationError """
+        compileAndVerifyCyclicInheritenceCompilationError '''
             class G3904R3A extends G3904R3B {}
             class G3904R3B extends G3904R3A {}
-        """
+        '''
     }
 
+    @Test
     void testCyclicInheritenceTC4() {
-        compileAndVerifyCyclicInheritenceCompilationError """
+        compileAndVerifyCyclicInheritenceCompilationError '''
             class G3904R4B extends G3904R4A {}
             class G3904R4A extends G3904R4B {}
-        """
+        '''
     }
 
-    // cyclic inheritence is between 2 parent classes
+    @Test // cyclic inheritence is between 2 parent classes
     void testCyclicInheritenceTC5() {
-        compileAndVerifyCyclicInheritenceCompilationError """
+        compileAndVerifyCyclicInheritenceCompilationError '''
             class G3904R5A extends G3904R5B {}
             class G3904R5B extends G3904R5C {}
             class G3904R5C extends G3904R5B {}
-        """
+        '''
     }
 
-    // cyclic inheritence is between 2 parent classes with a normal level in-between
+    @Test // cyclic inheritence is between 2 parent classes with a normal level in-between
     void testCyclicInheritenceTC6() {
-        compileAndVerifyCyclicInheritenceCompilationError """
+        compileAndVerifyCyclicInheritenceCompilationError '''
             class G3904R6A extends G3904R6B {}
             class G3904R6B extends G3904R6C {}
             class G3904R6C extends G3904R6D {}
             class G3904R6D extends G3904R6B {}
-        """
+        '''
     }
 }
diff --git a/src/test/groovy/bugs/Groovy8048Bug.groovy b/src/test/groovy/bugs/Groovy8048.groovy
similarity index 65%
rename from src/test/groovy/bugs/Groovy8048Bug.groovy
rename to src/test/groovy/bugs/Groovy8048.groovy
index 23b4cf4..6a85e39 100644
--- a/src/test/groovy/bugs/Groovy8048Bug.groovy
+++ b/src/test/groovy/bugs/Groovy8048.groovy
@@ -18,30 +18,34 @@
  */
 package groovy.bugs
 
-import groovy.test.GroovyTestCase
+import org.junit.Test
 
-class Groovy8048Bug extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
+
+final class Groovy8048 {
+
+    @Test
     void testFinalFieldInPreCompiledTrait() {
-        def shell = new GroovyShell(getClass().classLoader)
-        shell.evaluate('''
-            class Bar implements groovy.bugs.Groovy8048Bug.Groovy8048Trait, BarTrait {
+        assertScript """
+            class C implements ${getClass().getName()}.Foo, Bar {
                 static void main(args) {
-                    assert Bar.otherItems1 && Bar.otherItems1[0] == 'bar1'
-                    assert Bar.items1 && Bar.items1[0] == 'foo1'
-                    new Bar().with {
+                    assert this.otherItems1 && this.otherItems1[0] == 'bar1'
+                    assert this.items1 && this.items1[0] == 'foo1'
+                    new C().with {
                         assert otherItems2 && otherItems2[0] == 'bar2'
                         assert items2 && items2[0] == 'foo2'
                     }
                 }
-                trait BarTrait {
-                    final static List otherItems1 = ['bar1']
-                    final List otherItems2 = ['bar2']
-                }
             }
-        ''', 'testScript')
+
+            trait Bar {
+                final static List otherItems1 = ['bar1']
+                final List otherItems2 = ['bar2']
+            }
+        """
     }
 
-    trait Groovy8048Trait {
+    trait Foo {
         final static List items1 = ['foo1']
         final List items2 = ['foo2']
     }

[groovy] 01/05: GROOVY-10107: STC: check assign null before type parameter compatibility

Posted by em...@apache.org.
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 bd5076773d3f81b22cd9ada6da266ca6847c881e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Jun 4 09:48:39 2021 -0500

    GROOVY-10107: STC: check assign null before type parameter compatibility
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
---
 .../groovy/transform/stc/StaticTypeCheckingSupport.java    | 11 +++++------
 src/test/groovy/transform/stc/GenericsSTCTest.groovy       | 14 ++++++++++++++
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 2a5fd0d..ddc4419 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -644,6 +644,10 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     public static boolean checkCompatibleAssignmentTypes(final ClassNode left, final ClassNode right, final Expression rightExpression, final boolean allowConstructorCoercion) {
+        if (!isPrimitiveType(left) && isNullConstant(rightExpression)) {
+            return true;
+        }
+
         ClassNode leftRedirect = left.redirect();
         ClassNode rightRedirect = right.redirect();
         if (leftRedirect == rightRedirect) return true;
@@ -666,13 +670,8 @@ public abstract class StaticTypeCheckingSupport {
             }
         }
 
-        boolean rightExpressionIsNull = isNullConstant(rightExpression);
-        if (rightExpressionIsNull && !isPrimitiveType(left)) {
-            return true;
-        }
-
         // anything can be assigned to an Object, String, [Bb]oolean or Class receiver; except null to boolean
-        if (isWildcardLeftHandSide(leftRedirect) && !(boolean_TYPE.equals(left) && rightExpressionIsNull)) return true;
+        if (isWildcardLeftHandSide(leftRedirect) && !(boolean_TYPE.equals(left) && isNullConstant(rightExpression))) return true;
 
         if (leftRedirect == char_TYPE && rightRedirect == Character_TYPE) return true;
         if (leftRedirect == Character_TYPE && rightRedirect == char_TYPE) return true;
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 6631867..0779304 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1014,6 +1014,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         assertScript '''
             Map<String, Integer> foo = null
             Integer result = foo?.get('a')
+            assert result == null
         '''
     }
 
@@ -1021,6 +1022,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         assertScript '''
             List<Integer> foo = null
             Integer result = foo?.get(0)
+            assert result == null
         '''
     }
 
@@ -1029,8 +1031,20 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             List<Integer> foo = [1]
             foo = null
             Integer result = foo?.get(0)
+            assert result == null
         '''
+    }
 
+    // GROOVY-10107
+    void testAssignNullTypeParameterWithUpperBounds() {
+        assertScript '''
+            class C<T extends Number> {
+                void m() {
+                    T n = null
+                }
+            }
+            new C<Long>().m()
+        '''
     }
 
     void testMethodCallWithArgumentUsingNestedGenerics() {

[groovy] 05/05: remove test case

Posted by em...@apache.org.
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 5daebe3467fcc31d62619b3fec7879b3b8279389
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Aug 19 10:43:22 2021 -0500

    remove test case
---
 src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
index 716b1a8..df087c9 100644
--- a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
@@ -18,7 +18,6 @@
  */
 package groovy.transform.stc
 
-
 /**
  * Unit tests for static type checking : arrays and collections.
  */
@@ -67,13 +66,6 @@ class ArraysAndCollectionsSTCTest extends StaticTypeCheckingTestCase {
                 new X[]{new C<Number, String>()}
             }
         '''
-        shouldFailWithMessages '''
-            class C<X, Y> {
-            }
-            def <X extends C<Number, String>> X[] m() {
-                new X[]{new C<Object, String>()}
-            }
-        ''', 'Cannot convert from C<java.lang.Object, java.lang.String> to X'
     }
 
     void testConvertibleTypesInArrayInitializer() {