You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/02/15 07:48:10 UTC
[groovy] branch master updated: GROOVY-9938: SC: inner class needs
implicitThis false for method calls
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new e053cbb GROOVY-9938: SC: inner class needs implicitThis false for method calls
e053cbb is described below
commit e053cbbcc4ebb30ebec0e8e3bcc207e548b5d758
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
---
.../transform/DelegateASTTransformation.java | 1 +
.../groovy/transform/trait/TraitComposer.java | 2 +-
src/test/groovy/transform/stc/BugsSTCTest.groovy | 77 +++++++++++++++++++++-
3 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
index 2a93680..4cfdf63 100644
--- a/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
@@ -379,6 +379,7 @@ public class DelegateASTTransformation extends AbstractASTTransformation {
alsoLazy ? propX(varX("this"), delegate.name.substring(1)) : delegate.getOp,
candidate.getName(),
args);
+ 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(),
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 5ea86d7..2f5fe42 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'
+ }
+ }
+ '''
+ }
}