Eric Milles created GROOVY-9077: ----------------------------------- Summary: STC: inferred type of property that resolves to method not always stored Key: GROOVY-9077 URL: https://issues.apache.org/jira/browse/GROOVY-9077 Project: Groovy Issue Type: Bug Affects Versions: 2.5.6 Reporter: Eric Milles
Consider the following: {code:groovy} @groovy.transform.CompileStatic void meth(List list) { if (list instanceof LinkedList && list.first) { } if (list instanceof LinkedList && list.peek()) { } } {code} {{storeTargetMethod}} is called for the method call expression {{list.peek()}}. However, when {{org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.existsProperty}} resolves {{list.first}} to a method, {{storeTargetMethod}} is not called. This means the AST node does not record the direct method call target. Also, a type-checking extension does not have a chance to handle the method selection event. This addition addresses the issue for class getters: {code:java} if (readMode && checkGetterOrSetter) { if (getter != null) { ClassNode cn = inferReturnTypeGenerics(current, getter, ArgumentListExpression.EMPTY_ARGUMENTS); storeInferredTypeForPropertyExpression(pexp, cn); // GRECLIPSE add storeTargetMethod(pexp, getter); // GRECLIPSE end pexp.removeNodeMetaData(StaticTypesMarker.READONLY_PROPERTY); String delegationData = receiver.getData(); if (delegationData != null) pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData); return true; } {code} and this change addresses the issue for extension method getters: {code:java} // GROOVY-5568, the property may be defined by DGM List<ClassNode> dgmReceivers = new ArrayList<ClassNode>(2); dgmReceivers.add(testClass); if (isPrimitiveType(testClass)) dgmReceivers.add(getWrapper(testClass)); for (ClassNode dgmReceiver : dgmReceivers) { List<MethodNode> methods = findDGMMethodsByNameAndArguments(getTransformLoader(), dgmReceiver, "get" + capName, ClassNode.EMPTY_ARRAY); for (MethodNode m : findDGMMethodsByNameAndArguments(getTransformLoader(), dgmReceiver, "is" + capName, ClassNode.EMPTY_ARRAY)) { if (Boolean_TYPE.equals(getWrapper(m.getReturnType()))) methods.add(m); } if (!methods.isEmpty()) { List<MethodNode> methodNodes = chooseBestMethod(dgmReceiver, methods, ClassNode.EMPTY_ARRAY); if (methodNodes.size() == 1) { MethodNode getter = methodNodes.get(0); if (visitor != null) { visitor.visitMethod(getter); } ClassNode cn = inferReturnTypeGenerics(dgmReceiver, getter, ArgumentListExpression.EMPTY_ARGUMENTS); storeInferredTypeForPropertyExpression(pexp, cn); // GRECLIPSE add storeTargetMethod(pexp, getter); // GRECLIPSE end return true; } } } {code} The selection of a setter method is not as simple, since there may be many candidates. -- This message was sent by Atlassian JIRA (v7.6.3#76005)