diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ExpressionChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ExpressionChecker.java index 9c00d15de7fd..71c6216a7294 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ExpressionChecker.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ExpressionChecker.java @@ -141,8 +141,7 @@ final class ExpressionChecker { if (expression != null && myVisitor.isIncompleteModel() && IncompleteModelUtil.isPotentiallyConvertible(lType, expression)) { return true; } - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(elementToHighlight, new JavaIncompatibleTypeErrorContext(lType, rType))); - return false; + return myVisitor.reportIncompatibleType(lType, rType, elementToHighlight); } void checkMustBeBoolean(@NotNull PsiExpression expr) { @@ -157,7 +156,7 @@ final class ExpressionChecker { if (type == null && myVisitor.isIncompleteModel() && IncompleteModelUtil.mayHaveUnknownTypeDueToPendingReference(expr)) { return; } - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(expr, new JavaIncompatibleTypeErrorContext(PsiTypes.booleanType(), type))); + myVisitor.reportIncompatibleType(PsiTypes.booleanType(), type, expr); } } } @@ -366,7 +365,7 @@ final class ExpressionChecker { PsiClassType processorType = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING_TEMPLATE_PROCESSOR, processor.getResolveScope()); if (!TypeConversionUtil.isAssignable(processorType, type)) { if (myVisitor.isIncompleteModel() && IncompleteModelUtil.isPotentiallyConvertible(processorType, processor)) return; - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(processor, new JavaIncompatibleTypeErrorContext(processorType, type))); + myVisitor.reportIncompatibleType(processorType, type, processor); return; } @@ -566,7 +565,7 @@ final class ExpressionChecker { return; } if (myVisitor.isIncompleteModel() && IncompleteModelUtil.isPotentiallyConvertible(lType, rExpr)) return; - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(rExpr, new JavaIncompatibleTypeErrorContext(lType, type))); + myVisitor.reportIncompatibleType(lType, type, rExpr); } } @@ -1381,7 +1380,7 @@ final class ExpressionChecker { } // cannot derive type of conditional expression // elseType will never be cast-able to thenType, so no quick fix here - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(expression, new JavaIncompatibleTypeErrorContext(thenType, type))); + myVisitor.reportIncompatibleType(thenType, type, expression); } } diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/GenericsChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/GenericsChecker.java index 07a3b921ac1c..cc5448e48051 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/GenericsChecker.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/GenericsChecker.java @@ -99,7 +99,7 @@ final class GenericsChecker { if (myVisitor.isIncompleteModel() && IncompleteModelUtil.isPotentiallyConvertible(parameterType, itemType, expression)) { return; } - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(parameter, new JavaIncompatibleTypeErrorContext(itemType, parameterType))); + myVisitor.reportIncompatibleType(itemType, parameterType, parameter); } void checkDiamondTypeNotAllowed(@NotNull PsiNewExpression expression) { diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java index e0ec11711d16..99c7eb238445 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java @@ -6,6 +6,7 @@ import com.intellij.java.codeserver.core.JavaPreviewFeatureUtil; import com.intellij.java.codeserver.core.JavaPsiModuleUtil; import com.intellij.java.codeserver.highlighting.errors.JavaCompilationError; import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds; +import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext; import com.intellij.lang.ASTNode; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.IndexNotReadyException; @@ -1348,6 +1349,16 @@ final class JavaErrorVisitor extends JavaElementVisitor { } } + boolean reportIncompatibleType(@NotNull PsiType lType, @Nullable PsiType rType, @NotNull PsiElement elementToHighlight) { + if (rType instanceof PsiLambdaParameterType || lType instanceof PsiLambdaParameterType) { + // Do not report an incompatible type if the lambda parameter type is not known; + // this problem is induced by another problem, which is more useful to report + return true; + } + report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(elementToHighlight, new JavaIncompatibleTypeErrorContext(lType, rType))); + return false; + } + private void checkPreviewFeature(@NotNull PsiElement element) { if (myLanguageLevel.isPreview()) return; JavaPreviewFeatureUtil.PreviewFeatureUsage usage = JavaPreviewFeatureUtil.getPreviewFeatureUsage(element); diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/MethodChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/MethodChecker.java index 77fc95bd607d..ab9880651d3f 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/MethodChecker.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/MethodChecker.java @@ -7,7 +7,6 @@ import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil; import com.intellij.java.codeserver.core.JavaPsiMethodUtil; import com.intellij.java.codeserver.highlighting.errors.JavaCompilationError; import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds; -import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Couple; @@ -59,7 +58,7 @@ final class MethodChecker { PsiClassType type = factory.createType(aClass); PsiClassType throwable = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE, context.getResolveScope()); if (myVisitor.isIncompleteModel() && IncompleteModelUtil.isPotentiallyConvertible(throwable, type, context)) return; - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(context, new JavaIncompatibleTypeErrorContext(throwable, type))); + myVisitor.reportIncompatibleType(throwable, type, context); } } diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/PatternChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/PatternChecker.java index f4a01a1b6949..aa9b07094bcc 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/PatternChecker.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/PatternChecker.java @@ -100,7 +100,7 @@ final class PatternChecker { @NotNull PsiType itemType) { if (!TypeConversionUtil.areTypesConvertible(itemType, patternType) && (!myVisitor.isIncompleteModel() || !IncompleteModelUtil.isPotentiallyConvertible(patternType, itemType, pattern))) { - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(pattern, new JavaIncompatibleTypeErrorContext(itemType, patternType))); + myVisitor.reportIncompatibleType(itemType, patternType, pattern); return; } checkUncheckedPatternConversion(pattern); @@ -154,8 +154,7 @@ final class PatternChecker { IncompleteModelUtil.hasUnresolvedComponent(deconstructionComponentType))) { continue; } - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create( - deconstructionComponent, new JavaIncompatibleTypeErrorContext(substitutedRecordComponentType, deconstructionComponentType))); + myVisitor.reportIncompatibleType(substitutedRecordComponentType, deconstructionComponentType, deconstructionComponent); } } else { diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/StatementChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/StatementChecker.java index 24b4aaa7054a..d643d04a07a9 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/StatementChecker.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/StatementChecker.java @@ -6,7 +6,6 @@ import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil; import com.intellij.core.JavaPsiBundle; import com.intellij.java.codeserver.core.JavaPsiVariableUtil; import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds; -import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext; import com.intellij.pom.java.JavaFeature; import com.intellij.psi.*; import com.intellij.psi.impl.IncompleteModelUtil; @@ -191,8 +190,7 @@ final class StatementChecker { if (TypeConversionUtil.isAssignable(autoCloseable, type)) return; if (myVisitor.isIncompleteModel() && IncompleteModelUtil.isPotentiallyConvertible(autoCloseable, type, resource)) return; - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create( - resource, new JavaIncompatibleTypeErrorContext(autoCloseable, type))); + myVisitor.reportIncompatibleType(autoCloseable, type, resource); } void checkBreakTarget(@NotNull PsiBreakStatement statement) { @@ -335,8 +333,7 @@ final class StatementChecker { PsiType type = expression.getType(); if (type == null) return; if (expression == assertStatement.getAssertCondition() && !TypeConversionUtil.isBooleanType(type)) { - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create( - expression, new JavaIncompatibleTypeErrorContext(PsiTypes.booleanType(), type))); + myVisitor.reportIncompatibleType(PsiTypes.booleanType(), type, expression); } else if (expression == assertStatement.getAssertDescription() && TypeConversionUtil.isVoidType(type)) { myVisitor.report(JavaErrorKinds.TYPE_VOID_NOT_ALLOWED.create(expression)); @@ -350,7 +347,7 @@ final class StatementChecker { if (type == null) return; if (type instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(type)) { PsiClassType objectType = PsiType.getJavaLangObject(myVisitor.file().getManager(), expression.getResolveScope()); - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(expression, new JavaIncompatibleTypeErrorContext(objectType, type))); + myVisitor.reportIncompatibleType(objectType, type, expression); } } } diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/SwitchChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/SwitchChecker.java index 9c696e4a4e12..e4c29fdeb066 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/SwitchChecker.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/SwitchChecker.java @@ -263,8 +263,7 @@ final class SwitchChecker { } } if (!TypeConversionUtil.isBooleanType(guardingExpr.getType())) { - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create( - guardingExpr, new JavaIncompatibleTypeErrorContext(PsiTypes.booleanType(), guardingExpr.getType()))); + myVisitor.reportIncompatibleType(PsiTypes.booleanType(), guardingExpr.getType(), guardingExpr); return; } Object constVal = JavaPsiFacade.getInstance(myVisitor.project()).getConstantEvaluationHelper().computeConstantExpression(guardingExpr); @@ -305,8 +304,7 @@ final class SwitchChecker { } if (label instanceof PsiExpression expr) { if (selectorType.equals(PsiTypes.nullType())) { - myVisitor.report( - JavaErrorKinds.TYPE_INCOMPATIBLE.create(expr, new JavaIncompatibleTypeErrorContext(selectorType, expr.getType()))); + myVisitor.reportIncompatibleType(selectorType, expr.getType(), expr); continue; } if (label instanceof PsiReferenceExpression ref) { @@ -382,14 +380,13 @@ final class SwitchChecker { (kind == JavaPsiSwitchUtil.SelectorKind.BOOLEAN && !(constValue instanceof Boolean))) { PsiType unboxedType = PsiPrimitiveType.getOptionallyUnboxedType(selectorType); if (unboxedType != null) { - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create( - expr, new JavaIncompatibleTypeErrorContext(unboxedType, expr.getType()))); + myVisitor.reportIncompatibleType(unboxedType, expr.getType(), expr); } } return; } if (ConstantExpressionUtil.computeCastTo(constValue, selectorType) == null) { - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(expr, new JavaIncompatibleTypeErrorContext(selectorType, expr.getType()))); + myVisitor.reportIncompatibleType(selectorType, expr.getType(), expr); return; } if (kind == JavaPsiSwitchUtil.SelectorKind.INT || kind == JavaPsiSwitchUtil.SelectorKind.STRING) { @@ -429,8 +426,7 @@ final class SwitchChecker { myVisitor.report(JavaErrorKinds.UNSUPPORTED_FEATURE.create(elementToReport, JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS)); } else { - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create( - elementToReport, new JavaIncompatibleTypeErrorContext(selectorType, patternType))); + myVisitor.reportIncompatibleType(selectorType, patternType, elementToReport); } return; } diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/TypeChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/TypeChecker.java index aaa1a7745ea9..1f777c230107 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/TypeChecker.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/TypeChecker.java @@ -2,7 +2,6 @@ package com.intellij.java.codeserver.highlighting; import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds; -import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext; import com.intellij.psi.*; import com.intellij.psi.impl.IncompleteModelUtil; import com.intellij.psi.util.PsiTreeUtil; @@ -186,7 +185,7 @@ final class TypeChecker { PsiClassType throwable = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE, context.getResolveScope()); if (type != null && !TypeConversionUtil.isAssignable(throwable, type) && !(myVisitor.isIncompleteModel() && IncompleteModelUtil.isPotentiallyConvertible(throwable, type, context))) { - myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(context, new JavaIncompatibleTypeErrorContext(throwable, type))); + myVisitor.reportIncompatibleType(throwable, type, context); } } } diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java index f8c994159bfc..9e7f615dca59 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java @@ -1658,7 +1658,7 @@ public final class JavaErrorKinds { } /** - * Context for errors related to annotation value + * Context for errors related to the annotation value * @param method corresponding annotation method * @param expectedType expected value type * @param fromDefaultValue if true, the error is reported for the method default value, rather than for use site @@ -1689,7 +1689,7 @@ public final class JavaErrorKinds { /** * A context for {@link #CONSTRUCTOR_AMBIGUOUS_IMPLICIT_CALL} error kind - * @param psiClass a class where ambiguous call is performed + * @param psiClass a class where an ambiguous call is performed * @param candidate1 first constructor candidate in super class * @param candidate2 second constructor candidate in super class */ diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/WrongTargetTypeDoNotReportIncompatibleTypeInside.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/WrongTargetTypeDoNotReportIncompatibleTypeInside.java new file mode 100644 index 000000000000..4b412b6b1a88 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/WrongTargetTypeDoNotReportIncompatibleTypeInside.java @@ -0,0 +1,8 @@ +class Test { + void test() { + Object obj = x -> { + String s = x; + x = "hello"; + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igtest/assignment/assignment_to_lambda_parameter/AssignmentToLambdaParameter.java b/java/java-tests/testData/ig/com/siyeh/igtest/assignment/assignment_to_lambda_parameter/AssignmentToLambdaParameter.java index 5e4dadbd6d0b..41c93c0c2d41 100644 --- a/java/java-tests/testData/ig/com/siyeh/igtest/assignment/assignment_to_lambda_parameter/AssignmentToLambdaParameter.java +++ b/java/java-tests/testData/ig/com/siyeh/igtest/assignment/assignment_to_lambda_parameter/AssignmentToLambdaParameter.java @@ -13,7 +13,7 @@ class AssignmentToLambdaParameter { } void x() { - Runnable r = a -> a = ""; + Runnable r = a -> a = ""; } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index ece5fc068992..478e2db395ee 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -151,6 +151,7 @@ class NewLambdaHighlightingTest extends LightJavaCodeInsightFixtureTestCase5 { @Test void testLambdaWithExplicitTypeAndTargetTypeParameter() { doTest(); } @Test void testAmbiguousConstructorCallWithLambdaInside() { doTest(); } @Test void testMultiResolveSameFunction() {doTest();} + @Test void testWrongTargetTypeDoNotReportIncompatibleTypeInside() {doTest();} @Override protected @NotNull String getRelativePath() {