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 2022/01/31 21:07:58 UTC

[groovy] branch GROOVY_2_5_X updated (c9ba243 -> 2f82d2f)

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

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


    from c9ba243  GROOVY-9862: General error during instruction selection: ClassCastException
     new e542f9f  GROOVY-9890: STC: always search for default methods
     new a45809c  GROOVY-9892: add test case
     new 00b5b0f  GROOVY-9903: incomplete DelegatesTo parameters error links to annotation
     new f30231c  GROOVY-9935: `java.lang.Number` can accommodate any number type
     new 6661c96  GROOVY-9938: SC: inner class needs `implicitThis` false for method calls
     new 2f82d2f  GROOVY-9973: add test case

The 6 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/org/codehaus/groovy/ast/MethodNode.java   |   7 +-
 .../transform/DelegateASTTransformation.java       |   3 +-
 .../transform/stc/StaticTypeCheckingSupport.java   |  10 +-
 .../transform/stc/StaticTypeCheckingVisitor.java   |  32 ++---
 .../groovy/transform/trait/TraitComposer.java      |   2 +-
 src/test/groovy/transform/stc/BugsSTCTest.groovy   |  77 ++++++++++-
 .../groovy/transform/stc/DelegatesToSTCTest.groovy |  29 ++--
 .../stc/FieldsAndPropertiesSTCTest.groovy          |  34 +++--
 .../groovy/transform/stc/MethodCallsSTCTest.groovy | 150 +++++++++++++++++----
 .../stc/StaticTypeCheckingTestCase.groovy          |   7 +-
 .../transform/stc/TypeInferenceSTCTest.groovy      |  13 ++
 .../{Groovy7355Bug.groovy => Groovy9892Bug.groovy} |  28 ++--
 12 files changed, 302 insertions(+), 90 deletions(-)
 copy src/test/org/codehaus/groovy/classgen/asm/sc/bugs/{Groovy7355Bug.groovy => Groovy9892Bug.groovy} (70%)

[groovy] 06/06: GROOVY-9973: add 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_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 2f82d2fd63fe073b5fbf4f601970ad6d37fc476d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Mar 9 09:31:14 2021 -0600

    GROOVY-9973: add test case
---
 .../stc/FieldsAndPropertiesSTCTest.groovy          | 34 ++++++++++++++++------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index 3a77d47e..0e55f07 100644
--- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
+++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
@@ -237,21 +237,37 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    void testMethodUsageForProperty() {
+    void testDateProperties() {
         assertScript '''
-            class Foo {
-                String name
+            Date d = new Date()
+            def time = d.time
+            d.time = 0
+        '''
+    }
+
+    void testGetterForProperty1() {
+        assertScript '''
+            class C {
+                String p
             }
-            def name = new Foo().getName()
-            name?.toUpperCase()
+            def x = new C().getP()
+            x = x?.toUpperCase()
         '''
     }
 
-    void testDateProperties() {
+    // GROOVY-9973
+    void testGetterForProperty2() {
         assertScript '''
-            Date d = new Date()
-            def time = d.time
-            d.time = 0
+            class C {
+                private int f
+                int getP() { f }
+                Integer m() { 123456 - p }
+                Integer m(int i) { i - p }
+            }
+
+            def c = new C()
+            assert c.m() == 123456 // BUG! exception in phase 'class generation' ...
+            assert c.m(123) == 123 // ClassCastException: class org.codehaus.groovy.ast.Parameter cannot be cast to ...
         '''
     }
 

[groovy] 05/06: GROOVY-9938: SC: inner class needs `implicitThis` false for method calls

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 6661c967cb90d14574523754bfe24b68ff09891f
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Feb 13 11:04:04 2021 -0600

    GROOVY-9938: SC: inner class needs `implicitThis` false for method calls
    
    Conflicts:
    	src/test/groovy/transform/stc/BugsSTCTest.groovy
---
 .../transform/DelegateASTTransformation.java       |  3 +-
 .../groovy/transform/trait/TraitComposer.java      |  2 +-
 src/test/groovy/transform/stc/BugsSTCTest.groovy   | 77 +++++++++++++++++++++-
 3 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
index 355a81e..f8c3f2e 100644
--- a/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
@@ -326,7 +326,8 @@ public class DelegateASTTransformation extends AbstractASTTransformation {
                     alsoLazy ? propX(varX("this"), delegate.name.substring(1)) : delegate.getOp,
                     candidate.getName(),
                     args);
-            mce.setSourcePosition(delegate.delegate);
+            mce.setImplicitThis(false); // GROOVY-9938
+            mce.setSourcePosition(delegate.delegate); // GROOVY-6542
             ClassNode returnType = correctToGenericsSpecRecurse(genericsSpec, candidate.getReturnType(), currentMethodGenPlaceholders);
             MethodNode newMethod = addGeneratedMethod(delegate.owner, candidate.getName(),
                     candidate.getModifiers() & (~ACC_ABSTRACT) & (~ACC_NATIVE),
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java
index d536791..53ed407 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java
@@ -522,7 +522,7 @@ public abstract class TraitComposer {
         superCall.setImplicitThis(false);
         CastExpression proxyReceiver = new CastExpression(Traits.GENERATED_PROXY_CLASSNODE, new VariableExpression("this"));
         MethodCallExpression getProxy = new MethodCallExpression(proxyReceiver, "getProxyTarget", ArgumentListExpression.EMPTY_ARGUMENTS);
-        getProxy.setImplicitThis(true);
+        getProxy.setImplicitThis(false);
         StaticMethodCallExpression proxyCall = new StaticMethodCallExpression(
                 ClassHelper.make(InvokerHelper.class),
                 "invokeMethod",
diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy b/src/test/groovy/transform/stc/BugsSTCTest.groovy
index 37e0a99..0f70397 100644
--- a/src/test/groovy/transform/stc/BugsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -792,7 +792,7 @@ Printer
         '''
     }
 
-    //GROOVY-8590
+    // GROOVY-8590
     void testNestedMethodCallInferredTypeInReturnStmt() {
         assertScript '''
             class Source {
@@ -805,4 +805,79 @@ Printer
         '''
     }
 
+    // GROOVY-9938
+    void testInnerClassImplementsInterfaceMethod() {
+        assertScript '''
+            class Main {
+                interface I {
+                    def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c)
+                }
+                static class C implements I {
+                    def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c) {
+                        new D().with(c)
+                    }
+                }
+                static class D {
+                    def f() {
+                        return 'retval'
+                    }
+                }
+                static main(args) {
+                    def result = new C().m { f() }
+                    assert result == 'retval'
+                }
+            }
+        '''
+    }
+    void testInnerClassImplementsInterfaceMethodWithTrait() {
+        assertScript '''
+            class Main {
+                interface I {
+                    def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c)
+                }
+                trait T {
+                    def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c) {
+                        new D().with(c)
+                    }
+                }
+                static class C implements T { // generates m(Closure) that delegates to T#m(Closure)
+                }
+                static class D {
+                    def f() {
+                        return 'retval'
+                    }
+                }
+                static main(args) {
+                    def result = new C().m { f() }
+                    assert result == 'retval'
+                }
+            }
+        '''
+    }
+    void testInnerClassImplementsInterfaceMethodWithDelegate() {
+        assertScript '''
+            class Main {
+                interface I {
+                    def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c)
+                }
+                static class T implements I {
+                    def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c) {
+                        new D().with(c)
+                    }
+                }
+                static class C implements I {
+                    @Delegate(parameterAnnotations=true) T t = new T() // generates m(Closure) that delegates to T#m(Closure)
+                }
+                static class D {
+                    def f() {
+                        return 'retval'
+                    }
+                }
+                static main(args) {
+                    def result = new C().m { f() }
+                    assert result == 'retval'
+                }
+            }
+        '''
+    }
 }

[groovy] 03/06: GROOVY-9903: incomplete DelegatesTo parameters error links to annotation

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 00b5b0ff85145d130db5fb798f5702721fa60b09
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Jan 20 15:57:26 2021 -0600

    GROOVY-9903: incomplete DelegatesTo parameters error links to annotation
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
---
 .../transform/stc/StaticTypeCheckingVisitor.java   |  2 +-
 .../groovy/transform/stc/DelegatesToSTCTest.groovy | 29 ++++++++++------------
 .../stc/StaticTypeCheckingTestCase.groovy          |  7 +++---
 3 files changed, 17 insertions(+), 21 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 e0cad0c..3cea7e5 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3221,7 +3221,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         }
                     }
                     if (expression.getNodeMetaData(StaticTypesMarker.DELEGATION_METADATA) == null) {
-                        addError("Not enough arguments found for a @DelegatesTo method call. Please check that you either use an explicit class or @DelegatesTo.Target with a correct id", arguments);
+                        addError("Not enough arguments found for a @DelegatesTo method call. Please check that you either use an explicit class or @DelegatesTo.Target with a correct id", annotation);
                     }
                 }
             }
diff --git a/src/test/groovy/transform/stc/DelegatesToSTCTest.groovy b/src/test/groovy/transform/stc/DelegatesToSTCTest.groovy
index fdd7e62..4d8f49d 100644
--- a/src/test/groovy/transform/stc/DelegatesToSTCTest.groovy
+++ b/src/test/groovy/transform/stc/DelegatesToSTCTest.groovy
@@ -277,24 +277,21 @@ class DelegatesToSTCTest extends StaticTypeCheckingTestCase {
     }
 
     void testShouldFailDelegateToParameterIfNoTargetSpecified() {
-        shouldFailWithMessages '''
-        class Foo {
-            boolean called = false
-            def foo() { called = true }
-        }
+        shouldFailWithMessages '''\
+            class Foo {
+                boolean called = false
+                def bar() { called = true }
+            }
 
-        def with(Object target, @DelegatesTo Closure arg) {
-            arg.delegate = target
-            arg()
-        }
+            def m(Object o, @DelegatesTo Closure c) {
+                c.delegate = o
+                c.call()
+            }
 
-        def test() {
-            def obj = new Foo()
-            with(obj) { foo() }
-            assert obj.called
-        }
-        test()
-        ''', 'Not enough arguments found for a @DelegatesTo method call', 'Cannot find matching method'
+            def foo = new Foo()
+            m(foo) { -> bar() }
+            assert foo.called
+        ''', 'Not enough arguments found for a @DelegatesTo method call', '@ line 6, column 29', 'Cannot find matching method'
     }
 
     void testDelegatesToWithSetter() {
diff --git a/src/test/groovy/transform/stc/StaticTypeCheckingTestCase.groovy b/src/test/groovy/transform/stc/StaticTypeCheckingTestCase.groovy
index cfb9480..34d69f0 100644
--- a/src/test/groovy/transform/stc/StaticTypeCheckingTestCase.groovy
+++ b/src/test/groovy/transform/stc/StaticTypeCheckingTestCase.groovy
@@ -83,14 +83,13 @@ abstract class StaticTypeCheckingTestCase extends GroovyTestCase {
                     it instanceof SyntaxErrorMessage && it.cause.message.contains(message)
                 }
             }
-            if (success && mce.errorCollector.errorCount!=messages.length) {
-                throw new AssertionError("Expected error messages were found, but compiler threw additional errors : " + mce.toString())
+            if (success && mce.errorCollector.errorCount > messages.length) {
+                throw new AssertionError("Expected error messages were found, but compiler threw additional errors : $mce")
             }
             if (!success) {
-                throw new AssertionError("Not all expected error messages were found, compiler threw these errors : " + mce.toString())
+                throw new AssertionError("Not all expected error messages were found, compiler threw these errors : $mce")
             }
         }
         if (!success) throw new AssertionError("Test passed but should have failed with messages [$messages]")
     }
-
 }

[groovy] 02/06: GROOVY-9892: add 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_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit a45809cb38cea6e40242845fec24a09970628b6c
Author: Fiouz <fi...@gmail.com>
AuthorDate: Tue Jan 12 21:52:03 2021 +0800

    GROOVY-9892: add test case
---
 .../classgen/asm/sc/bugs/Groovy9892Bug.groovy      | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy9892Bug.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy9892Bug.groovy
new file mode 100644
index 0000000..142892a
--- /dev/null
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy9892Bug.groovy
@@ -0,0 +1,42 @@
+/*
+ *  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 org.codehaus.groovy.classgen.asm.sc.bugs
+
+import groovy.transform.stc.StaticTypeCheckingTestCase
+import org.codehaus.groovy.classgen.asm.sc.StaticCompilationTestSupport
+
+final class Groovy9892Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
+    void testUnaryIncrementInGString() {
+        assertScript '''
+            class C {
+                int i, j
+
+                def call() {
+                    { ->
+                        "Hello${++i}World${j++}"
+                    }.call()
+                }
+            }
+            def obj = new C()
+            assert obj.call() == 'Hello1World0'
+            assert obj.i == 1
+            assert obj.j == 1
+        '''
+    }
+}

[groovy] 01/06: GROOVY-9890: STC: always search for default methods

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e542f9f54b381ed682072176a85e8c5545a443f9
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Jan 17 17:58:13 2021 -0600

    GROOVY-9890: STC: always search for default methods
    
    2_5_X backport
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
---
 .../java/org/codehaus/groovy/ast/MethodNode.java   |   7 +-
 .../transform/stc/StaticTypeCheckingVisitor.java   |  30 +++--
 .../groovy/transform/stc/MethodCallsSTCTest.groovy | 150 +++++++++++++++++----
 3 files changed, 149 insertions(+), 38 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/MethodNode.java b/src/main/java/org/codehaus/groovy/ast/MethodNode.java
index c4289b3..8ce5415 100644
--- a/src/main/java/org/codehaus/groovy/ast/MethodNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/MethodNode.java
@@ -148,6 +148,11 @@ public class MethodNode extends AnnotatedNode implements Opcodes {
         return (modifiers & ACC_ABSTRACT) != 0;
     }
 
+    public boolean isDefault() {
+        return (modifiers & (ACC_ABSTRACT | ACC_PUBLIC | ACC_STATIC)) == ACC_PUBLIC
+                && getDeclaringClass() != null && getDeclaringClass().isInterface();
+    }
+
     public boolean isStatic() {
         return (modifiers & ACC_STATIC) != 0;
     }
@@ -260,7 +265,7 @@ public class MethodNode extends AnnotatedNode implements Opcodes {
 
     /**
      * Provides a nicely formatted string of the method definition. For simplicity, generic types on some of the elements
-     * are not displayed. 
+     * are not displayed.
      * @return
      *      string form of node with some generic elements suppressed
      */
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 f505312..e0cad0c 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2409,7 +2409,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 ClassNode receiverType = wrapTypeIfNecessary(currentReceiver.getType());
 
                 candidates = findMethodsWithGenerated(receiverType, nameText);
-                collectAllInterfaceMethodsByName(receiverType, nameText, candidates);
                 if (isBeingCompiled(receiverType)) candidates.addAll(GROOVY_OBJECT_TYPE.getMethods(nameText));
                 candidates.addAll(findDGMMethodsForClassNode(getTransformLoader(), receiverType, nameText));
                 candidates = filterMethodsByVisibility(candidates);
@@ -4462,10 +4461,23 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      */
     protected List<MethodNode> findMethodsWithGenerated(ClassNode receiver, String name) {
         List<MethodNode> methods = receiver.getMethods(name);
-        if (methods.isEmpty() || receiver.isResolved()) return methods;
-        List<MethodNode> result = addGeneratedMethods(receiver, methods);
+        if (receiver.isAbstract()) {
+            collectAllInterfaceMethodsByName(receiver, name, methods);
+        } else { // GROOVY-9890: always search for default methods
+            List<MethodNode> interfaceMethods = new ArrayList<>();
+            collectAllInterfaceMethodsByName(receiver, name, interfaceMethods);
+            for (MethodNode method : interfaceMethods) {
+                if (method.isDefault()) methods.add(method);
+            }
+        }
+        if (receiver.isInterface()) {
+            methods.addAll(OBJECT_TYPE.getMethods(name));
+        }
 
-        return result;
+        if (methods.isEmpty() || receiver.isResolved()) {
+            return methods;
+        }
+        return addGeneratedMethods(receiver, methods);
     }
 
     private static List<MethodNode> addGeneratedMethods(final ClassNode receiver, final List<MethodNode> methods) {
@@ -4543,10 +4555,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             }
         } else {
             methods = findMethodsWithGenerated(receiver, name);
-            if (receiver.isInterface()) {
-                collectAllInterfaceMethodsByName(receiver, name, methods);
-                methods.addAll(OBJECT_TYPE.getMethods(name));
-            }
             // TODO: investigate the trait exclusion a bit further, needed otherwise
             // CallMethodOfTraitInsideClosureAndClosureParamTypeInference fails saying
             // not static method can't be called from a static context
@@ -4614,12 +4622,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             }
         }
 
-        if (methods.isEmpty()) {
-            // look at the interfaces, there's a chance that a method is not implemented and we should not hide the
-            // error from the compiler
-            collectAllInterfaceMethodsByName(receiver, name, methods);
-        }
-
         if (!"<init>".equals(name) && !"<clinit>".equals(name)) {
             // lookup in DGM methods too
             findDGMMethodsByNameAndArguments(getSourceUnit().getClassLoader(), receiver, name, args, methods);
diff --git a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
index 6971243..2f61d0c 100644
--- a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -18,8 +18,8 @@
  */
 package groovy.transform.stc
 
-import org.codehaus.groovy.control.customizers.ImportCustomizer;
-import static org.codehaus.groovy.control.CompilerConfiguration.DEFAULT as config
+import org.codehaus.groovy.control.customizers.ImportCustomizer
+import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit
 
 /**
  * Unit tests for static type checking : method calls.
@@ -34,7 +34,6 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
         } catch (ClassNotFoundException e) {
             IS_PRE_8 = true
         }
-
     }
 
     @Override
@@ -439,7 +438,7 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
         assertScript '''
                 1.with { obj ->
                     if (obj instanceof String) {
-                        obj.toUpperCase() 
+                        obj.toUpperCase()
                     }
                 }
             '''
@@ -450,11 +449,11 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
             public interface SAM {
                 boolean run(String var1, Thread th);
             }
-            
+
             static boolean foo(SAM sam) {
                sam.run("foo",  new Thread())
             }
-            
+
             static def callSAM() {
                 foo { str, th ->
                     str.toUpperCase().equals(th.getName())
@@ -468,11 +467,11 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
 
         assertScript '''
             import java.util.function.Predicate
-            
+
             static boolean foo(Predicate<? super String> p) {
                 p.test("foo")
             }
-            
+
             static def testPredicate() {
                 foo { it ->
                     it.toUpperCase()
@@ -501,9 +500,9 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
                     filter { s -> s.length() < 10 }.
                     toArray()
             }
-            
-            final words = ["orange", "sit", "test", "flabbergasted", "honorific"] 
-            
+
+            final words = ["orange", "sit", "test", "flabbergasted", "honorific"]
+
             println doIt(words)
             '''
     }
@@ -552,7 +551,7 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
                 }
             '''
     }
-    
+
     void testOneDefaultParam() {
         assertScript '''
             String m(String val = 'hello') {
@@ -590,7 +589,7 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
             m('test', new Object())
         ''', 'm(java.lang.String, java.lang.Object)'
     }
-    
+
     void testMultipleDefaultArgs() {
         assertScript '''
             String m(String first = 'first', String second, String third = 'third') {
@@ -996,17 +995,122 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
             Test.test(null)
         '''
     }
+
     void testShouldFindInheritedInterfaceMethod() {
         assertScript '''
-            interface Top { void close() }
+            interface Top { void foo() }
             interface Middle extends Top {}
             interface Bottom extends Middle {}
-            void foo(Bottom obj) {
-               obj.close()
+
+            void test(Bottom b) {
+               b.foo()
+            }
+        '''
+    }
+
+    void testShouldFindInheritedInterfaceMethod2() {
+        assertScript '''
+            interface Top { int foo(int i) }
+            interface Middle extends Top { int foo(String s) }
+            interface Bottom extends Middle {}
+
+            void test(Bottom b) {
+                b.foo(123)
+            }
+        '''
+    }
+
+    void testShouldFindInheritedInterfaceMethod3() {
+        assertScript '''
+            interface Top { int foo(int i) }
+            interface Middle extends Top { }
+            interface Bottom extends Middle { int foo(String s) }
+
+            void test(Bottom b) {
+                b.foo(123)
+            }
+        '''
+    }
+
+    void testShouldFindInheritedInterfaceMethod4() {
+        assertScript '''
+            interface Top { int foo(int i) }
+            interface Middle extends Top { int foo(String s) }
+            abstract class Bottom implements Middle {}
+
+            int test(Bottom b) {
+                b.foo(123)
             }
+            def bot = new Bottom() {
+                int foo(int i) { 1 }
+                int foo(String s) { 2 }
+            }
+            assert test(bot) == 1
+        '''
+    }
+
+    void testShouldFindInheritedInterfaceMethod5() {
+        assertScript '''
+            interface Top { int foo(int i) }
+            interface Middle extends Top { }
+            abstract class Bottom implements Middle { abstract int foo(String s) }
+
+            int test(Bottom b) {
+                b.foo(123)
+            }
+            def bot = new Bottom() {
+                int foo(int i) { 1 }
+                int foo(String s) { 2 }
+            }
+            assert test(bot) == 1
         '''
     }
 
+    // GROOVY-9890
+    void testShouldFindInheritedInterfaceDefaultMethod() {
+        if (IS_PRE_8) return
+
+        def parentDir = File.createTempDir()
+        config.targetDirectory = File.createTempDir()
+        config.jointCompilationOptions = [stubDir: File.createTempDir()]
+        try {
+            def a = new File(parentDir, 'Face.java')
+            a.write '''
+                public interface Face {
+                    default Object foo(long n) {
+                        return n;
+                    }
+                    Object foo(String s);
+                }
+            '''
+            def b = new File(parentDir, 'Impl.groovy')
+            b.write '''
+                class Impl implements Face {
+                    @Override def foo(String s) {
+                        return s
+                    }
+                    // def foo(long n)
+                }
+            '''
+            def c = new File(parentDir, 'Main.groovy')
+            c.write '''
+                def result = new Impl().foo(42L)
+                assert result.class == Long.class
+            '''
+
+            def loader = new GroovyClassLoader(this.class.classLoader)
+            def cu = new JavaAwareCompilationUnit(config, loader)
+            cu.addSources(a, b, c)
+            cu.compile()
+
+            loader.loadClass('Main').main()
+        } finally {
+            parentDir.deleteDir()
+            config.targetDirectory.deleteDir()
+            config.jointCompilationOptions.stubDir.deleteDir()
+        }
+    }
+
     // GROOVY-5743
     void testClosureAsParameter() {
         assertScript '''
@@ -1115,7 +1219,7 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
             assert b.overload('a','b') == 2
         '''
     }
-    
+
     // GROOVY-5883 and GROOVY-6270
     void testClosureUpperBound() {
         assertScript '''
@@ -1148,7 +1252,7 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
             String.doSomething()
         ''', 'Cannot find matching method java.lang.String#doSomething()'
     }
-    
+
     // GROOVY-6646
     void testNPlusVargsCallInOverloadSituation() {
         assertScript '''
@@ -1166,7 +1270,7 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
             assert foo("2","1") == "Strings"
         '''
     }
-    
+
     //GROOVY-6776
     void testPrimtiveParameterAndNullArgument() {
         shouldFailWithMessages '''
@@ -1252,13 +1356,13 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
         import java.util.stream.Stream
-        
+
         @CompileStatic
         public class Test1 {
             public static void main(String[] args) {
                 p();
             }
-            
+
             public static void p() {
                 assert 13 == [1, 2, 3].stream().reduce(7, {Integer r, Integer e -> r + e});
             }
@@ -1272,9 +1376,9 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
 
         assertScript '''
         import groovy.transform.CompileStatic
-        
+
         import static java.util.stream.Collectors.toList
-        
+
         @CompileStatic
         class Test {
             static void main(String[] args) {

[groovy] 04/06: GROOVY-9935: `java.lang.Number` can accommodate any number type

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f30231cf78a1e10c8a16f9fcf7735b87da64a798
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Feb 10 13:50:02 2021 -0600

    GROOVY-9935: `java.lang.Number` can accommodate any number type
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
---
 .../groovy/transform/stc/StaticTypeCheckingSupport.java     | 10 ++++++----
 src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy   | 13 +++++++++++++
 2 files changed, 19 insertions(+), 4 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 b19931b..dcdbd15 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -76,6 +76,7 @@ import java.util.regex.Matcher;
 
 import static java.lang.Math.min;
 import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedMethod;
+import static org.apache.groovy.ast.tools.ExpressionUtils.isNullConstant;
 import static org.codehaus.groovy.ast.ClassHelper.BigDecimal_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.BigInteger_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Boolean_TYPE;
@@ -90,6 +91,7 @@ import static org.codehaus.groovy.ast.ClassHelper.GROOVY_OBJECT_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.GSTRING_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Integer_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Long_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.Number_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Short_TYPE;
@@ -685,9 +687,9 @@ public abstract class StaticTypeCheckingSupport {
             return left == VOID_TYPE || left == void_WRAPPER_TYPE;
         }
 
-        if ((isNumberType(rightRedirect) || WideningCategories.isNumberCategory(rightRedirect))) {
-            if (BigDecimal_TYPE == leftRedirect) {
-                // any number can be assigned to a big decimal
+        if (isNumberType(rightRedirect) || WideningCategories.isNumberCategory(rightRedirect)) {
+            if (BigDecimal_TYPE == leftRedirect || Number_TYPE == leftRedirect) {
+                // any number can be assigned to BigDecimal or Number
                 return true;
             }
             if (BigInteger_TYPE == leftRedirect) {
@@ -697,7 +699,7 @@ public abstract class StaticTypeCheckingSupport {
         }
 
         // if rightExpression is null and leftExpression is not a primitive type, it's ok
-        boolean rightExpressionIsNull = rightExpression instanceof ConstantExpression && ((ConstantExpression) rightExpression).getValue() == null;
+        boolean rightExpressionIsNull = isNullConstant(rightExpression);
         if (rightExpressionIsNull && !isPrimitiveType(left)) {
             return true;
         }
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index 6e8128a..8fe23b8 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -41,6 +41,19 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
         """
     }
 
+    // GROOVY-9935
+    void testIntegerToNumber() {
+        ['def', 'int', 'Integer', 'BigInteger'].each { type ->
+            assertScript """
+                Number f() {
+                    $type n = 10
+                    return n
+                }
+                assert f() == 10
+            """
+        }
+    }
+
     void testGStringMethods() {
         assertScript '''
             def myname = 'Cedric'