Skip to content

Commit

Permalink
GROOVY-11366: STC: implicit-this closure field call
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Sep 10, 2024
1 parent ba873c5 commit 35ee676
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.apache.groovy.ast.tools.ClassNodeUtils.getField;
import static org.apache.groovy.ast.tools.MethodNodeUtils.withDefaultArgumentMethods;
import static org.apache.groovy.util.BeanUtils.capitalize;
import static org.apache.groovy.util.BeanUtils.decapitalize;
Expand Down Expand Up @@ -3650,14 +3651,18 @@ public void visitMethodCallExpression(final MethodCallExpression call) {
case "doCall":
if (!isThisObjectExpression) {
isCallOnClosure = receiver.equals(CLOSURE_TYPE);
break;
}
default:
if (isThisObjectExpression) {
ClassNode enclosingType = typeCheckingContext.getEnclosingClassNode();
fieldNode = enclosingType.getDeclaredField(name);
if (fieldNode != null && getType(fieldNode).equals(CLOSURE_TYPE)
&& !enclosingType.hasPossibleMethod(name, callArguments)) {
// GROOVY-5705, GROOVY-11366: "this.x(...)" could refer to field
if (!typeCheckingContext.isInStaticContext) {
fieldNode = getField(receiver, name);
} else {
fieldNode = getField(receiver, name, FieldNode::isStatic);
}
if (fieldNode != null
&& getType(fieldNode).equals(CLOSURE_TYPE)
&& !receiver.hasPossibleMethod(name, callArguments)) {
isCallOnClosure = true;
}
}
Expand Down
55 changes: 41 additions & 14 deletions src/test/groovy/transform/stc/ClosuresSTCTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,47 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
'''
}

// GROOVY-5705
void testCallClosure19() {
assertScript '''
class Foo {
Closure c = { it }
def test() {
c("123")
}
}
String result = new Foo().test()
assert result == '123'
'''
shouldFailWithMessages '''
class Foo {
Closure c = { -> }
static test() {
c()
}
}
''',
'Cannot find matching method java.lang.Class#c() or static method Foo#c()'
}

// GROOVY-11366
void testCallClosure20() {
assertScript '''
class Bar {
Closure c = { it }
}
class Foo extends Bar {
def test() {
c("123")
}
}
String result = new Foo().test()
assert result == '123'
'''
}

void testClosureReturnTypeInference1() {
assertScript '''
def c = { int a, int b -> return a + b }
Expand Down Expand Up @@ -693,20 +734,6 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
'''
}

// GROOVY-5705
void testNPEWhenCallingClosureFromAField() {
assertScript '''
class Test {
Closure c = { it }
void test() {
c("123")
}
}
new Test().test()
'''
}

// GROOVY-6219, GROOVY-10277
void testClosureReturnDoesNotMatchTarget() {
shouldFailWithMessages '''
Expand Down

0 comments on commit 35ee676

Please sign in to comment.