mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
lambda highlighting: if return statement has problem, try to highlight only corresponding return even if containing inference failed
This commit is contained in:
+51
-63
@@ -325,77 +325,65 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
myHolder.add(checkFeature(expression, Feature.LAMBDA_EXPRESSIONS));
|
||||
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent());
|
||||
if (parent instanceof PsiExpressionStatement) return;
|
||||
if (!myHolder.hasErrorResults() && !LambdaUtil.isValidLambdaContext(parent)) {
|
||||
myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
|
||||
.descriptionAndTooltip("Lambda expression not expected here").create());
|
||||
}
|
||||
|
||||
PsiType functionalInterfaceType = null;
|
||||
if (!myHolder.hasErrorResults()) {
|
||||
if (LambdaUtil.isValidLambdaContext(parent)) {
|
||||
final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
|
||||
if (functionalInterfaceType != null) {
|
||||
final String notFunctionalMessage = LambdaHighlightingUtil.checkInterfaceFunctional(functionalInterfaceType);
|
||||
if (notFunctionalMessage != null) {
|
||||
HighlightInfo result =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(notFunctionalMessage)
|
||||
.create();
|
||||
myHolder.add(result);
|
||||
}
|
||||
else {
|
||||
final PsiCallExpression callExpression = parent instanceof PsiExpressionList && parent.getParent() instanceof PsiCallExpression ?
|
||||
(PsiCallExpression)parent.getParent() : null;
|
||||
final JavaResolveResult containingCallResolveResult = callExpression != null ? callExpression.resolveMethodGenerics() : null;
|
||||
final String errorMessage;
|
||||
if (containingCallResolveResult instanceof MethodCandidateInfo) {
|
||||
errorMessage = ((MethodCandidateInfo)containingCallResolveResult).getParentInferenceErrorMessage((PsiExpressionList)parent);
|
||||
}
|
||||
else {
|
||||
errorMessage = null;
|
||||
}
|
||||
if (errorMessage != null) {
|
||||
HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
|
||||
.range(expression).descriptionAndTooltip(errorMessage).create();
|
||||
myHolder.add(result);
|
||||
}
|
||||
else {
|
||||
final Map<PsiElement, String> returnErrors = LambdaUtil
|
||||
.checkReturnTypeCompatible(expression, LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType));
|
||||
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);
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
|
||||
if (interfaceMethod != null) {
|
||||
final PsiParameter[] parameters = interfaceMethod.getParameterList().getParameters();
|
||||
HighlightInfo result = LambdaHighlightingUtil
|
||||
.checkParametersCompatible(expression, parameters, LambdaUtil.getSubstitutor(interfaceMethod, resolveResult));
|
||||
if (result != null) {
|
||||
myHolder.add(result);
|
||||
}
|
||||
else {
|
||||
checkFunctionalInterfaceTypeAccessible(expression, functionalInterfaceType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
functionalInterfaceType = expression.getFunctionalInterfaceType();
|
||||
if (functionalInterfaceType != null) {
|
||||
final String notFunctionalMessage = LambdaHighlightingUtil.checkInterfaceFunctional(functionalInterfaceType);
|
||||
if (notFunctionalMessage != null) {
|
||||
myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
|
||||
.descriptionAndTooltip(notFunctionalMessage).create());
|
||||
}
|
||||
else if (LambdaUtil.getFunctionalInterfaceType(expression, true) != null) {
|
||||
myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip("Cannot infer functional interface type").create());
|
||||
else {
|
||||
checkFunctionalInterfaceTypeAccessible(expression, functionalInterfaceType);
|
||||
}
|
||||
}
|
||||
else {
|
||||
HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
|
||||
.descriptionAndTooltip("Lambda expression not expected here").create();
|
||||
myHolder.add(result);
|
||||
else if (LambdaUtil.getFunctionalInterfaceType(expression, true) != null) {
|
||||
myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip("Cannot infer functional interface type").create());
|
||||
}
|
||||
if (!myHolder.hasErrorResults()) {
|
||||
final PsiElement body = expression.getBody();
|
||||
if (body instanceof PsiCodeBlock) {
|
||||
myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement((PsiCodeBlock)body));
|
||||
}
|
||||
|
||||
if (!myHolder.hasErrorResults() && functionalInterfaceType != null) {
|
||||
String parentInferenceErrorMessage = null;
|
||||
final PsiCallExpression callExpression = parent instanceof PsiExpressionList && parent.getParent() instanceof PsiCallExpression ?
|
||||
(PsiCallExpression)parent.getParent() : null;
|
||||
final JavaResolveResult containingCallResolveResult = callExpression != null ? callExpression.resolveMethodGenerics() : null;
|
||||
if (containingCallResolveResult instanceof MethodCandidateInfo) {
|
||||
parentInferenceErrorMessage = ((MethodCandidateInfo)containingCallResolveResult).getParentInferenceErrorMessage((PsiExpressionList)parent);
|
||||
}
|
||||
final Map<PsiElement, String> returnErrors = LambdaUtil.checkReturnTypeCompatible(expression, LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType));
|
||||
if (parentInferenceErrorMessage != null && (returnErrors == null || !returnErrors.containsValue(parentInferenceErrorMessage))) {
|
||||
myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(parentInferenceErrorMessage).create());
|
||||
}
|
||||
else if (returnErrors != null) {
|
||||
for (Map.Entry<PsiElement, String> entry : returnErrors.entrySet()) {
|
||||
myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
|
||||
.range(entry.getKey())
|
||||
.descriptionAndTooltip(entry.getValue()).create());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!myHolder.hasErrorResults() && functionalInterfaceType != null) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
|
||||
if (interfaceMethod != null) {
|
||||
final PsiParameter[] parameters = interfaceMethod.getParameterList().getParameters();
|
||||
myHolder.add(LambdaHighlightingUtil.checkParametersCompatible(expression, parameters, LambdaUtil.getSubstitutor(interfaceMethod, resolveResult)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!myHolder.hasErrorResults()) {
|
||||
final PsiElement body = expression.getBody();
|
||||
if (body instanceof PsiCodeBlock) {
|
||||
myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement((PsiCodeBlock)body));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class TypeArgsConsistency1 {
|
||||
I<Integer> i1 = (i, j) -> i + j;
|
||||
foo((i, j) -> i + j);
|
||||
I<Integer> i2 =bar((i, j) -> i) ;
|
||||
I<Integer> i3 = bar(<error descr="Bad return type in lambda expression: String cannot be converted to int">(i, j) -> "" + i + j</error>);
|
||||
I<Integer> i3 = bar((i, j) -> <error descr="Bad return type in lambda expression: String cannot be converted to int">"" + i + j</error>);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -66,9 +66,9 @@ class Test2 {
|
||||
{
|
||||
bar(x -> x);
|
||||
bar1(x -> x);
|
||||
bar2(1, <error descr="Bad return type in lambda expression: List<Integer> cannot be converted to Integer">x -> x</error>);
|
||||
bar2("", <error descr="Bad return type in lambda expression: List<String> cannot be converted to String">x -> x</error>);
|
||||
bar3(<error descr="Bad return type in lambda expression: List<String> cannot be converted to String">x -> x</error>, "");
|
||||
bar2(1, x -> <error descr="Bad return type in lambda expression: List<Integer> cannot be converted to Integer">x</error>);
|
||||
bar2("", x -> <error descr="Bad return type in lambda expression: List<String> cannot be converted to String">x</error>);
|
||||
bar3(x -> <error descr="Bad return type in lambda expression: List<String> cannot be converted to String">x</error>, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-1
@@ -1,4 +1,5 @@
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class Test {
|
||||
@@ -12,4 +13,14 @@ class Test {
|
||||
}
|
||||
|
||||
public static void foo(Supplier<String> consumer) {}
|
||||
|
||||
private void foo(List<String> descriptions) {
|
||||
Collections.sort(descriptions, (o1, o2) -> {
|
||||
final int elementsDiff = o1.length() - o2.length();
|
||||
if (elementsDiff == 0) {
|
||||
return <error descr="Bad return type in lambda expression: boolean cannot be converted to int">o1.equals(o2)</error>;
|
||||
}
|
||||
return -elementsDiff;
|
||||
});
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@ class Test {
|
||||
}
|
||||
|
||||
void bar(C c) {
|
||||
foo(c, <error descr="Bad return type in lambda expression: A cannot be converted to C">x -> x.f()</error>);
|
||||
foo(c, x -> <error descr="Bad return type in lambda expression: A cannot be converted to C">x.f()</error>);
|
||||
foo(c, x -> x);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user