mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
lambda return type inconsistency: highlight all found errors (IDEA-158853)
This commit is contained in:
+7
-7
@@ -337,14 +337,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
myHolder.add(result);
|
||||
}
|
||||
else {
|
||||
final String incompatibleReturnTypesMessage = LambdaUtil
|
||||
final Map<PsiElement, String> returnErrors = LambdaUtil
|
||||
.checkReturnTypeCompatible(expression, LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType));
|
||||
if (incompatibleReturnTypesMessage != null) {
|
||||
final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions(expression);
|
||||
final PsiElement returnStatementToHighlight = returnExpressions.size() == 1 ? returnExpressions.get(0) : expression.getBody();
|
||||
HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(returnStatementToHighlight != null ? returnStatementToHighlight : expression)
|
||||
.descriptionAndTooltip(incompatibleReturnTypesMessage).create();
|
||||
myHolder.add(result);
|
||||
if (returnErrors != null) {
|
||||
for (Map.Entry<PsiElement, String> entry : returnErrors.entrySet()) {
|
||||
myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
|
||||
.range(entry.getKey())
|
||||
.descriptionAndTooltip(entry.getValue()).create());
|
||||
}
|
||||
}
|
||||
else {
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
|
||||
|
||||
@@ -651,25 +651,32 @@ public class LambdaUtil {
|
||||
return map;
|
||||
}
|
||||
|
||||
public static String checkReturnTypeCompatible(PsiLambdaExpression lambdaExpression, PsiType functionalInterfaceReturnType) {
|
||||
public static Map<PsiElement, String> checkReturnTypeCompatible(PsiLambdaExpression lambdaExpression, PsiType functionalInterfaceReturnType) {
|
||||
Map<PsiElement, String> errors = new LinkedHashMap<PsiElement, String>();
|
||||
if (PsiType.VOID.equals(functionalInterfaceReturnType)) {
|
||||
final PsiElement body = lambdaExpression.getBody();
|
||||
if (body instanceof PsiCodeBlock) {
|
||||
if (!getReturnExpressions(lambdaExpression).isEmpty()) return "Unexpected return value";
|
||||
} else if (body instanceof PsiExpression) {
|
||||
for (PsiExpression expression : getReturnExpressions(lambdaExpression)) {
|
||||
errors.put(expression, "Unexpected return value");
|
||||
}
|
||||
}
|
||||
else if (body instanceof PsiExpression) {
|
||||
final PsiType type = ((PsiExpression)body).getType();
|
||||
try {
|
||||
if (!PsiUtil.isStatement(JavaPsiFacade.getElementFactory(body.getProject()).createStatementFromText(body.getText(), body))) {
|
||||
if (PsiType.VOID.equals(type)) {
|
||||
return "Lambda body must be a statement expression";
|
||||
errors.put(body, "Lambda body must be a statement expression");
|
||||
}
|
||||
else {
|
||||
errors.put(body, "Bad return type in lambda expression: " + (type == PsiType.NULL || type == null ? "<null>" : type.getPresentableText()) + " cannot be converted to void");
|
||||
}
|
||||
return "Bad return type in lambda expression: " + (type == PsiType.NULL || type == null ? "<null>" : type.getPresentableText()) + " cannot be converted to void";
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException ignore) {
|
||||
}
|
||||
}
|
||||
} else if (functionalInterfaceReturnType != null) {
|
||||
}
|
||||
else if (functionalInterfaceReturnType != null) {
|
||||
final List<PsiExpression> returnExpressions = getReturnExpressions(lambdaExpression);
|
||||
for (final PsiExpression expression : returnExpressions) {
|
||||
final PsiType expressionType = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, true, new Computable<PsiType>() {
|
||||
@@ -679,14 +686,23 @@ public class LambdaUtil {
|
||||
}
|
||||
});
|
||||
if (expressionType != null && !functionalInterfaceReturnType.isAssignableFrom(expressionType)) {
|
||||
return "Bad return type in lambda expression: " + expressionType.getPresentableText() + " cannot be converted to " + functionalInterfaceReturnType.getPresentableText();
|
||||
errors.put(expression, "Bad return type in lambda expression: " + expressionType.getPresentableText() + " cannot be converted to " + functionalInterfaceReturnType.getPresentableText());
|
||||
}
|
||||
}
|
||||
if (getReturnStatements(lambdaExpression).length > returnExpressions.size() || returnExpressions.isEmpty() && !lambdaExpression.isVoidCompatible()) {
|
||||
return "Missing return value";
|
||||
final PsiReturnStatement[] returnStatements = getReturnStatements(lambdaExpression);
|
||||
if (returnStatements.length > returnExpressions.size()) {
|
||||
for (PsiReturnStatement statement : returnStatements) {
|
||||
final PsiExpression value = statement.getReturnValue();
|
||||
if (value == null) {
|
||||
errors.put(statement, "Missing return value");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (returnExpressions.isEmpty() && !lambdaExpression.isVoidCompatible()) {
|
||||
errors.put(lambdaExpression, "Missing return value");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return errors.isEmpty() ? null : errors;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class Test {
|
||||
public static void bar(boolean f) {
|
||||
foo(() -> {
|
||||
if (f) <error descr="Missing return value">return;</error>
|
||||
if (false) <error descr="Missing return value">return;</error>
|
||||
if (!f) return <error descr="Bad return type in lambda expression: int cannot be converted to String">1</error>;
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public static void foo(Supplier<String> consumer) {}
|
||||
}
|
||||
+4
@@ -327,6 +327,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testHighlightFaultyLambdaReturnExpression() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user