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/03 17:29:57 UTC

[groovy] 01/02: GROOVY-9938: SC: inner class needs implicitThis false for method calls

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 c35a2224c17d99c072b14bb9ed224a5c283230b2
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/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
---
 .../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 0d4c86c..120d611 100644
--- a/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
@@ -365,7 +365,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 75a80e5..b810a3f 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java
@@ -517,7 +517,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 3a8f784..f7bf560 100644
--- a/src/test/groovy/transform/stc/BugsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -19,7 +19,6 @@
 package groovy.transform.stc
 
 import static groovy.test.GroovyAssert.isAtLeastJdk
-import static org.junit.Assume.assumeFalse
 
 /**
  * Unit tests for static type checking : bug fixes.
@@ -863,4 +862,80 @@ Printer
             def ptr = String.&toLowerCaseX
         ''', 'Cannot find matching method java.lang.String#toLowerCaseX.'
     }
+
+    // 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'
+                }
+            }
+        '''
+    }
 }