Permalink
Browse files

GROOVY-5470: even if delegate/owner are subject to caution when used …

…in static type checking mode, the properties should be recognized
  • Loading branch information...
1 parent 2169178 commit c8325a8cb320dbc12bad8b200019d00ec4233256 @melix committed Jun 12, 2012
View
24 src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -66,6 +66,9 @@
private static final ClassNode DGM_CLASSNODE = ClassHelper.make(DefaultGroovyMethods.class);
private static final int CURRENT_SIGNATURE_PROTOCOL_VERSION = 1;
private static final Expression CURRENT_SIGNATURE_PROTOCOL = new ConstantExpression(CURRENT_SIGNATURE_PROTOCOL_VERSION, true);
+ private static final MethodNode GET_DELEGATE = CLOSURE_TYPE.getGetterMethod("getDelegate");
+ private static final MethodNode GET_OWNER = CLOSURE_TYPE.getGetterMethod("getOwner");
+ private static final MethodNode GET_THISOBJECT = CLOSURE_TYPE.getGetterMethod("getThisObject");
public static final MethodNode CLOSURE_CALL_NO_ARG;
public static final MethodNode CLOSURE_CALL_ONE_ARG;
@@ -281,6 +284,14 @@ public void visitVariableExpression(VariableExpression vexp) {
vexp != VariableExpression.SUPER_EXPRESSION) {
if (vexp.getName().equals("this")) storeType(vexp, classNode);
if (vexp.getName().equals("super")) storeType(vexp, classNode.getSuperClass());
+ if (closureExpression!=null) {
+ if (vexp.getName().equals("owner")
+ || vexp.getName().equals("delegate")
+ || vexp.getName().equals("thisObject")) {
+ storeType(vexp, classNode);
+ return;
+ }
+ }
}
if (vexp.getAccessedVariable() instanceof DynamicVariable) {
// a dynamic variable is either an undeclared variable
@@ -1561,6 +1572,16 @@ public void visitMethodCallExpression(MethodCallExpression call) {
break;
}
}
+ if (mn.isEmpty() && closureExpression!=null && args.length==0) {
+ // add special handling of getDelegate() and getOwner()
+ if ("getDelegate".equals(name)) {
+ mn = Collections.singletonList(GET_DELEGATE);
+ } else if ("getOwner".equals(name)) {
+ mn = Collections.singletonList(GET_OWNER);
+ }else if ("getThisObject".equals(name)) {
+ mn = Collections.singletonList(GET_THISOBJECT);
+ }
+ }
if (mn.isEmpty()) {
addStaticTypeError("Cannot find matching method " + receiver.getText() + "#" + toMethodParametersString(name, args), call);
} else {
@@ -2168,6 +2189,9 @@ protected ClassNode getType(ASTNode exp) {
return inferMapExpressionType((MapExpression) exp);
}
if (exp instanceof MethodNode) {
+ if ((exp==GET_DELEGATE || exp==GET_OWNER || exp==GET_THISOBJECT) && closureExpression!=null) {
+ return classNode;
+ }
ClassNode ret = (ClassNode) exp.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
return ret != null ? ret : ((MethodNode) exp).getReturnType();
}
View
67 src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -135,4 +135,71 @@ class BugsSTCTest extends StaticTypeCheckingTestCase {
}
new StaticGroovy2()'''
}
+
+ void testClosureDelegateThisOwner() {
+ assertScript '''
+ class A {
+ A that = this
+ void m() {
+ def cl = {
+ @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+ assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'A'
+ })
+ def foo = this
+ assert this == that
+ }
+ cl()
+ cl = {
+ @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+ assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'A'
+ })
+ def foo = delegate
+ assert delegate == that
+ }
+ cl()
+ cl = {
+ @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+ assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'A'
+ })
+ def foo = owner
+ assert owner == that
+ }
+ }
+ }
+ new A().m()
+ '''
+ }
+ void testClosureDelegateThisOwnerUsingGetters() {
+ assertScript '''
+ class A {
+ A that = this
+ void m() {
+ def cl = {
+ @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+ assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'A'
+ })
+ def foo = getThisObject()
+ assert getThisObject() == that
+ }
+ cl()
+ cl = {
+ @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+ assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'A'
+ })
+ def foo = getDelegate()
+ assert getDelegate() == that
+ }
+ cl()
+ cl = {
+ @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+ assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'A'
+ })
+ def foo = getOwner()
+ assert getOwner() == that
+ }
+ }
+ }
+ new A().m()
+ '''
+ }
}

0 comments on commit c8325a8

Please sign in to comment.