Details
-
Bug
-
Status: Closed
-
Minor
-
Resolution: Fixed
-
2.5.6
-
None
-
None
Description
Consider the following:
@groovy.transform.CompileStatic void meth(List list) { if (list instanceof LinkedList && list.first) { } if (list instanceof LinkedList && list.peek()) { } }
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:
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; }
and this change addresses the issue for extension method getters:
// 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; } } }
The selection of a setter method is not as simple, since there may be many candidates.