Skip to content

Commit

Permalink
Fix for #1000: apply SAM type generics to method parameter types
Browse files Browse the repository at this point in the history
add handling for wildcard types in GenericsMapper
  • Loading branch information
eric-milles committed Dec 12, 2019
1 parent 1ef40a5 commit a00cdb9
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,29 @@ public void testCoercedClosure2() {
assertType(contents, "z", "java.util.regex.Pattern");
}

@Test // https://github.com/groovy/groovy-eclipse/issues/1000
public void testCoercedClosure3() {
createUnit("Face",
//@formatter:off
"interface Face<T> {\n" +
" boolean test(T t)\n" +
"}");
//@formatter:on

//@formatter:off
String contents =
"class C<E> {\n" + // like Collection
" boolean meth(Face<? super E> f) {\n" + // like removeIf
" f.test(null)\n" +
" }\n" +
"}\n" +
"def c = new C<Integer>()\n" +
"def result = c.meth { e -> e }\n";
//@formatter:on

assertType(contents, "e", "java.lang.Integer");
}

@Test // Closure type inference without @CompileStatic
public void testCompileStaticClosure0() {
String contents =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public static GenericsMapper gatherGenerics(ClassNode resolvedType, ClassNode de
GenericsType[] ugts = GroovyUtils.getGenericsTypes(uCandidate);

int n = ugts.length;
if (n > 0 && rgts.length < 1) {
if (n > 0 && rgts.length == 0) {
rgts = new GenericsType[n]; // assume rCandidate is a raw type
for (int i = 0; i < n; i += 1) {
rgts[i] = new GenericsType(Optional.ofNullable(ugts[i].getUpperBounds()).map(bounds -> bounds[0]).orElse(VariableScope.OBJECT_CLASS_NODE));
Expand Down Expand Up @@ -160,7 +160,16 @@ public static GenericsMapper gatherGenerics(List<ClassNode> argumentTypes, Class
*/
public ClassNode resolveParameter(GenericsType topGT, int depth) {
if (allGenerics.isEmpty()) {
return topGT.getType();
if (!topGT.isWildcard()) {
return topGT.getType();
}
if (topGT.getLowerBound() != null) {
return topGT.getLowerBound();
}
if (topGT.getUpperBounds() != null) {
return topGT.getUpperBounds()[0];
}
return VariableScope.OBJECT_CLASS_NODE;
}

if (depth > 10) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2245,11 +2245,14 @@ private ClassNode[] inferClosureParamTypes(final ClosureExpression node, final V
}

if (inferredTypes[0] == null) {
int i = 0; MethodNode sam; // check for SAM-type coercion of closure expression
int i = 0;
MethodNode sam;
// check for SAM-type coercion of closure/lambda expression
if (primaryType != null && (sam = ClassHelper.findSAM(primaryType)) != null) {
GenericsMapper m = GenericsMapper.gatherGenerics(primaryType, primaryType.redirect());
for (ClassNode t : GroovyUtils.getParameterTypes(sam.getParameters())) {
if (i == inferredTypes.length) break;
inferredTypes[i++] = t;
inferredTypes[i++] = VariableScope.resolveTypeParameterization(m, t);
}
}
Arrays.fill(inferredTypes, i, inferredTypes.length, VariableScope.OBJECT_CLASS_NODE);
Expand Down

0 comments on commit a00cdb9

Please sign in to comment.