Fix IndexOutOfBoundsException with lambda that has wrong shape

This commit is contained in:
Clément Fournier committed 2022-04-14 21:23:21 +02:00
1 parent 7cf97d6afc
commit 6d152b1552
5 files changed
+42 -2

No files matched your search

@@ -110,6 +110,13 @@ public final class ASTLambdaExpression extends AbstractJavaExpr implements Funct
}
/**
* Returns the number of formal parameters of this lambda.
*/
public int getArity() {
return getParameters().size();
}
@Override
protected <P, R> R acceptVisitor(JavaVisitor<? super P, ? extends R> visitor, P data) {
return visitor.visit(this, data);
@@ -41,6 +41,12 @@ public final class ASTLambdaParameter extends AbstractJavaTypeNode
return visitor.visit(this, data);
}
/**
* Returns the lambda that owns this parameter.
*/
public ASTLambdaExpression getOwner() {
return (ASTLambdaExpression) getParent().getParent();
}
/**
* Returns the declarator ID of this formal parameter.
@@ -565,6 +565,9 @@ public final class LazyTypeResolver extends JavaVisitorBase<TypingContext, @NonN
JMethodSig m = lambda.getFunctionalMethod(); // this forces resolution of the lambda
if (!isUnresolved(m)) {
if (m.getArity() != node.getOwner().getArity()) {
return ts.ERROR;
}
return m.getFormalParameters().get(node.getIndexInParent());
}
return ts.UNKNOWN;
@@ -629,4 +629,28 @@ class C {
}
}
parserTest("Lambda with wrong form") {
val (acu, _) = parser.parseWithTypeInferenceSpy("""
interface Lambda {
void call();
}
class Foo {
{
Lambda l = () -> {}; // ok
Lambda l = x -> {}; // wrong form!
}
}
""")
val (ok, wrong) = acu.descendants(ASTLambdaExpression::class.java).toList()
val t_Lambda = acu.typeDeclarations.firstOrThrow().typeMirror
acu.withTypeDsl {
ok shouldHaveType t_Lambda
wrong shouldHaveType t_Lambda
wrong.parameters[0] shouldHaveType ts.ERROR
}
}
})
@@ -191,7 +191,7 @@ import java.util.concurrent.*;
import java.nio.file.Path;
public class Foo {
private Map<Path, List<String>> joinFutures(Map<String, List<Future<String>>> map) {
private Map<String, List<String>> joinFutures(Map<String, List<Future<String>>> map) {
Map<String, List<String>> joined = new HashMap<>();
for (String p : map.keySet()) {
@@ -214,7 +214,7 @@ public class Foo {
}
// checking basic lambdas and anonymous classes as well
Callable<Object> c = a -> { return null; }; // <----- false positive here
Callable<Object> c = () -> { return null; }; // <----- false positive here
Callable<Object> c2 = new Callable<Object>() {
public Object call() {
return null; // <----- false positive here