Skip to content

Commit

Permalink
Fix for #1199: use LHS type to further resolve method pointer/reference
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Dec 2, 2020
1 parent ebae30f commit e5dfebc
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,15 @@ public void testClosure12() {
assertType(contents, "asList", "java.util.List<java.lang.Integer>");
}

@Test // https://github.com/groovy/groovy-eclipse/issues/1199
public void testClosure13() {
String contents = "def <T> String test(T t) {}\n" + "java.util.function.Function<Integer, String> f = this.&test\n";
int offset = contents.lastIndexOf("test");
MethodNode m = assertDeclaration(contents, offset, offset + 4, "Search", "test", DeclarationKind.METHOD);
assertEquals("java.lang.String", printTypeName(m.getReturnType()));
assertEquals("java.lang.Integer", printTypeName(m.getParameters()[0].getType()));
}

@Test
public void testArrayDGM() {
String contents =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ public TypeLookupResult resolveTypeParameterization(final ClassNode objExprType,

List<ClassNode> argumentTypes = new ArrayList<>();
if (isGroovy) argumentTypes.add(objectType);
ClassNode targetType = null;
GenericsMapper mapper;

if (scope.getEnclosingNode() instanceof MethodPointerExpression) {
Expand All @@ -188,44 +189,33 @@ public TypeLookupResult resolveTypeParameterization(final ClassNode objExprType,
int index = ((TupleExpression) cat.call.getArguments()).getExpressions().indexOf(scope.getEnclosingNode());
Parameter[] params = ((MethodNode) cat.declaration).getParameters();
if (index != -1 && params.length > 0) {
ClassNode targetType = params[Math.min(index, params.length - 1)].getType();
targetType = params[Math.min(index, params.length - 1)].getType();
if (targetType.isArray() && index >= params.length - 1) {
targetType = objectType.getComponentType();
}
if (targetType.equals(VariableScope.CLOSURE_CLASS_NODE)) {
ClassNode returnType = Optional.of(targetType).map(ClassNode::getGenericsTypes)
.filter(Objects::nonNull).map(gts -> gts[0].getType()).orElse(VariableScope.OBJECT_CLASS_NODE);

mapper = GenericsMapper.gatherGenerics(singletonList(returnType), declaringType, returnTypeStub(method));
method = VariableScope.resolveTypeParameterization(mapper, method);
} else {
MethodNode sam = ClassHelper.findSAM(targetType);
if (sam != null) {
// use parameter types of SAM as "argument types" for referenced method to help resolve type parameters
mapper = GenericsMapper.gatherGenerics(GroovyUtils.getParameterTypes(sam.getParameters()), declaringType, method);
method = VariableScope.resolveTypeParameterization(mapper, method);

mapper = GenericsMapper.gatherGenerics(targetType);
method = VariableScope.resolveTypeParameterization(mapper, method);
}
}
}
} else if (testEnclosingAssignment(scope, rhs -> rhs == scope.getEnclosingNode())) {
// maybe the assign target type can help resolve type parameters of method pointer
ClassNode targetType = scope.getEnclosingAssignment().getLeftExpression().getType();
// maybe the assign target type can help resolve type parameters of method
targetType = scope.getEnclosingAssignment().getLeftExpression().getType();
}

ClassNode returnType; // aligned with referenced method
if (targetType != null) {
if (targetType.equals(VariableScope.CLOSURE_CLASS_NODE)) {
returnType = Optional.of(targetType).map(ClassNode::getGenericsTypes)
ClassNode returnType = Optional.of(targetType).map(ClassNode::getGenericsTypes)
.filter(Objects::nonNull).map(gts -> gts[0].getType()).orElse(VariableScope.OBJECT_CLASS_NODE);
} else {
returnType = Optional.ofNullable(ClassHelper.findSAM(targetType)).map(sam ->
VariableScope.resolveTypeParameterization(GenericsMapper.gatherGenerics(targetType), VariableScope.clone(sam.getReturnType()))
).orElse(null);
}
if (returnType != null) {

mapper = GenericsMapper.gatherGenerics(singletonList(returnType), declaringType, returnTypeStub(method));
method = VariableScope.resolveTypeParameterization(mapper, method);
} else {
MethodNode sam = ClassHelper.findSAM(targetType);
if (sam != null) {
// use parameter types of SAM as "argument types" for referenced method to help resolve type parameters
mapper = GenericsMapper.gatherGenerics(GroovyUtils.getParameterTypes(sam.getParameters()), declaringType, method);
method = VariableScope.resolveTypeParameterization(mapper, method);

mapper = GenericsMapper.gatherGenerics(targetType);
method = VariableScope.resolveTypeParameterization(mapper, method);
}
}
}
} else {
Expand All @@ -239,8 +229,8 @@ public TypeLookupResult resolveTypeParameterization(final ClassNode objExprType,
(rhs instanceof StaticMethodCallExpression && rhs == scope.getCurrentNode()) ||
(rhs instanceof MethodCallExpression && ((MethodCallExpression) rhs).getMethod() == scope.getCurrentNode())
)) {
// maybe the assign target type can help resolve type parameters of method call
ClassNode targetType = scope.getEnclosingAssignment().getLeftExpression().getType();
// maybe the assign target type can help resolve type parameters of method
targetType = scope.getEnclosingAssignment().getLeftExpression().getType();

mapper = GenericsMapper.gatherGenerics(singletonList(targetType), declaringType, returnTypeStub(method));
method = VariableScope.resolveTypeParameterization(mapper, method);
Expand Down

0 comments on commit e5dfebc

Please sign in to comment.