Skip to content

Commit

Permalink
Fix for #804: method pointer to category method not supported for Class
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Feb 2, 2019
1 parent a1732cf commit c1f518b
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,10 @@ public class CategoryTypeLookup implements ITypeLookup {

@Override
public TypeLookupResult lookupType(Expression node, VariableScope scope, ClassNode objectExpressionType) {
if (node instanceof VariableExpression || isCompatibleConstantExpression(node, scope)) {
if (node instanceof VariableExpression || isCompatibleConstantExpression(node, scope, objectExpressionType)) {
String simpleName = node.getText();
ClassNode expectedType = objectExpressionType;
if (expectedType == null) expectedType = scope.getDelegateOrThis();
ClassNode normalizedType = GroovyUtils.getWrapperTypeIfPrimitive(expectedType);
ClassNode selfType = GroovyUtils.getWrapperTypeIfPrimitive(
objectExpressionType != null ? objectExpressionType : scope.getDelegateOrThis());
boolean isMethodPointer = (scope.getEnclosingNode() instanceof MethodPointerExpression);

//
Expand All @@ -56,7 +55,7 @@ public TypeLookupResult lookupType(Expression node, VariableScope scope, ClassNo
for (ClassNode category : scope.getCategoryNames()) {
if (scope.isMethodCall() || isMethodPointer) {
for (MethodNode method : category.getMethods(simpleName)) {
if (isCompatibleCategoryMethod(method, normalizedType, scope)) {
if (isCompatibleCategoryMethod(method, selfType, scope)) {
candidates.add(method);
}
}
Expand All @@ -65,7 +64,7 @@ public TypeLookupResult lookupType(Expression node, VariableScope scope, ClassNo
if (getterName != null && !isMethodPointer) {
for (MethodNode method : category.getMethods(getterName)) {
if (AccessorSupport.findAccessorKind(method, true) == AccessorSupport.GETTER &&
isCompatibleCategoryMethod(method, normalizedType, scope)) {
isCompatibleCategoryMethod(method, selfType, scope)) {
candidates.add(method);
}
}
Expand All @@ -74,7 +73,7 @@ public TypeLookupResult lookupType(Expression node, VariableScope scope, ClassNo
if (setterName != null && !isMethodPointer) {
for (MethodNode method : category.getMethods(setterName)) {
if (AccessorSupport.findAccessorKind(method, true) == AccessorSupport.SETTER &&
isCompatibleCategoryMethod(method, normalizedType, scope)) {
isCompatibleCategoryMethod(method, selfType, scope)) {
candidates.add(method);
}
}
Expand All @@ -84,7 +83,7 @@ public TypeLookupResult lookupType(Expression node, VariableScope scope, ClassNo
if (!candidates.isEmpty()) {
int args = 1 + scope.getMethodCallNumberOfArguments();
List<ClassNode> argumentTypes = new ArrayList<>(args);
argumentTypes.add(normalizedType); // lhs of dot or delegate type
argumentTypes.add(selfType); // lhs of dot or delegate type
if (args > 1) argumentTypes.addAll(scope.getMethodCallArgumentTypes());

MethodNode method = selectBestMatch(candidates, argumentTypes);
Expand All @@ -98,9 +97,13 @@ public TypeLookupResult lookupType(Expression node, VariableScope scope, ClassNo
return null;
}

protected static boolean isCompatibleConstantExpression(Expression node, VariableScope scope) {
if (node instanceof ConstantExpression && !(scope.getEnclosingNode() instanceof AttributeExpression) && !scope.isTopLevel()) {
return (VariableScope.STRING_CLASS_NODE.equals(node.getType()) && node.getLength() <= node.getText().length());
protected static boolean isCompatibleConstantExpression(Expression node, VariableScope scope, ClassNode selfType) {
if (node instanceof ConstantExpression && !scope.isTopLevel()) {
org.codehaus.groovy.ast.ASTNode enclosingNode = scope.getEnclosingNode();
if (!(enclosingNode instanceof AttributeExpression || (enclosingNode instanceof MethodPointerExpression &&
VariableScope.CLASS_CLASS_NODE.equals(selfType)))) {
return (VariableScope.STRING_CLASS_NODE.equals(node.getType()) && node.getLength() <= node.getText().length());
}
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2017 the original author or authors.
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -36,8 +36,9 @@ public interface ITypeLookup {
*
* @param node the AST Node to determine the type for
* @param scope the variable scope at this location
* @param objectExpressionType if the parent of node is a {@link PropertyExpression}, then this value contains the type of
* {@link PropertyExpression#getObjectExpression()}, otherwise null
* @param objectExpressionType if the parent of node is a ClassExpression,
* PropertyExpression, AttributeExpression, MethodPointerExpression, or
* the like then this value contains the type of the left-hand expression
* @return the type for the node and confidence in that type, or null if cannot determine
*/
TypeLookupResult lookupType(Expression node, VariableScope scope, ClassNode objectExpressionType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ protected TypeLookupResult findType(Expression node, ClassNode declaringType, Va
if (isCompatible(field, isStaticObjectExpression)) {
return new TypeLookupResult(field.getType(), clazz, field, TypeConfidence.EXACT, scope);
} else {
return new TypeLookupResult(VariableScope.VOID_CLASS_NODE, clazz, null, TypeConfidence.UNKNOWN, scope);
return new TypeLookupResult(VariableScope.VOID_CLASS_NODE, null, null, TypeConfidence.UNKNOWN, scope);
}
}

Expand Down

0 comments on commit c1f518b

Please sign in to comment.