From 9905bef52647dbf783c290b22e6761d6d71e1e37 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 27 Mar 2026 15:40:13 +0100 Subject: [PATCH] IDEA-386665 [java]: don't report lambda/method reference problems when their class type is unresolved GitOrigin-RevId: e542751b8352847268bb6f98e83f5af33539e959 --- .../highlighting/JavaErrorVisitor.java | 23 +++++++++---------- .../FunctionalInterfaceCheck.java | 1 + .../lambda/methodRef/Ambiguity.java | 2 +- .../ConstructorRefsInnerClasses.java | 2 +- .../lambda/methodRef/SOE.java | 2 +- .../lambda/methodRef/StaticProblems.java | 2 +- ...iguousConstructorCallWithLambdaInside.java | 4 ++-- ...reateMethodFromMethodRefApplicability.java | 2 +- .../newMethodRef/PotentialApplicability.java | 8 +++---- ...otentialCompatibilityWithInvalidShape.java | 2 +- 10 files changed, 24 insertions(+), 24 deletions(-) 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 4e170bfa990d..dfa5a67fbb7f 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 @@ -1,4 +1,4 @@ -// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.java.codeserver.highlighting; import com.intellij.codeInsight.UnhandledExceptions; @@ -208,7 +208,7 @@ final class JavaErrorVisitor extends JavaElementVisitor { if (ContainerUtil.exists(JavaErrorFilter.EP_NAME.getExtensionList(), ep -> ep.shouldSuppressError(myPsiFile, error))) return; myErrorConsumer.accept(error); } - + @Contract(pure = true) boolean isApplicable(@NotNull JavaFeature feature) { return feature.isSufficient(myLanguageLevel); @@ -242,7 +242,7 @@ final class JavaErrorVisitor extends JavaElementVisitor { boolean hasErrorResults() { return myHasError; } - + @Contract(pure = true) boolean isIncompleteModel() { return IncompleteModelUtil.isIncompleteModel(myPsiFile); @@ -376,7 +376,7 @@ final class JavaErrorVisitor extends JavaElementVisitor { if (!hasErrorResults()) checkFeature(annotation, JavaFeature.ANNOTATIONS); myAnnotationChecker.checkAnnotation(annotation); } - + @Override public void visitPackageStatement(@NotNull PsiPackageStatement statement) { super.visitPackageStatement(statement); @@ -517,8 +517,7 @@ final class JavaErrorVisitor extends JavaElementVisitor { if (!hasErrorResults()) myFunctionChecker.checkMethodReferenceQualifier(expression); if (!hasErrorResults()) { boolean resolvedButNonApplicable = results.length == 1 && results[0] instanceof MethodCandidateInfo methodInfo && - !methodInfo.isApplicable() && - functionalInterfaceType != null; + !methodInfo.isApplicable() && functionalInterfaceType != null; if (results.length != 1 || resolvedButNonApplicable) { if (expression.isConstructor()) { PsiClass containingClass = PsiMethodReferenceUtil.getQualifierResolveResult(expression).getContainingClass(); @@ -548,17 +547,19 @@ final class JavaErrorVisitor extends JavaElementVisitor { } } if (!hasErrorResults()) myFunctionChecker.checkRawConstructorReference(expression); + PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(LambdaUtil.normalizeFunctionalType(functionalInterfaceType)); if (functionalInterfaceType != null) { if (!hasErrorResults()) myFunctionChecker.checkExtendsSealedClass(expression, functionalInterfaceType); - boolean isFunctional = LambdaUtil.isFunctionalType(functionalInterfaceType); - if (!hasErrorResults() && !isFunctional && + if (!hasErrorResults() && (aClass != null || !(functionalInterfaceType instanceof PsiClassType)) && !LambdaUtil.isFunctionalClass(aClass) && !(isIncompleteModel() && IncompleteModelUtil.isUnresolvedClassType(functionalInterfaceType))) { report(JavaErrorKinds.LAMBDA_NOT_FUNCTIONAL_INTERFACE.create(expression, functionalInterfaceType)); } if (!hasErrorResults()) myFunctionChecker.checkMethodReferenceContext(expression, functionalInterfaceType); if (!hasErrorResults()) myFunctionChecker.checkFunctionalInterfaceTypeAccessible(expression, functionalInterfaceType); } - if (!hasErrorResults()) myFunctionChecker.checkMethodReferenceResolve(expression, results, functionalInterfaceType); + if (!hasErrorResults() && (aClass != null || results.length == 0)) { + myFunctionChecker.checkMethodReferenceResolve(expression, results, functionalInterfaceType); + } if (!hasErrorResults()) myFunctionChecker.checkMethodReferenceReturnType(expression, result, functionalInterfaceType); if (!hasErrorResults() && method instanceof PsiModifierListOwner) checkPreviewFeature(expression); } @@ -918,7 +919,7 @@ final class JavaErrorVisitor extends JavaElementVisitor { if (!hasErrorResults()) myTypeChecker.checkVarTypeApplicability(variable); if (!hasErrorResults()) myTypeChecker.checkVariableInitializerType(variable); } - + @Override public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) { visitElement(expression); @@ -978,8 +979,6 @@ final class JavaErrorVisitor extends JavaElementVisitor { if (!hasErrorResults()) myExpressionChecker.checkClassReferenceAfterQualifier(expression, resolved); if (!hasErrorResults() && resolved instanceof PsiModifierListOwner) checkPreviewFeature(expression); } - - @Override public void visitArrayInitializerExpression(@NotNull PsiArrayInitializerExpression expression) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceCheck.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceCheck.java index 74537d41e2c0..bec80c60542b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceCheck.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceCheck.java @@ -1,5 +1,6 @@ class Demo { public static void main(String[] args) { Runnable r = () -> () -> () -> {}; + Supplier unresolved = String::new; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/Ambiguity.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/Ambiguity.java index 294b7554ccff..43a177f60ebc 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/Ambiguity.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/Ambiguity.java @@ -22,7 +22,7 @@ class MyTest { { Bar1 b1 = MyTest :: foo; - bar(MyTest :: foo); + bar(MyTest :: foo); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorRefsInnerClasses.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorRefsInnerClasses.java index 676e16731df6..ec1a5235f21a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorRefsInnerClasses.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorRefsInnerClasses.java @@ -71,7 +71,7 @@ class StaticInner1 { static void call3(I2 s) {} static { - call3(StaticInner1.Inner :: new); + call3(StaticInner1.Inner :: new); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/SOE.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/SOE.java index 23459132ca89..12ccc26a5b76 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/SOE.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/SOE.java @@ -2,7 +2,7 @@ import java.util.*; class LambdaTest { public void testR() { - new ArrayList() :: size = ""; + new ArrayList() :: size = ""; } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/StaticProblems.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/StaticProblems.java index 56b1bad6f2a1..e6e06559878d 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/StaticProblems.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/StaticProblems.java @@ -116,7 +116,7 @@ class MyTest2 { static void call3(I2 s) {} static { call3(MyTest2::m1); - call3(MyTest2::m2); + call3(MyTest2::m2); call3(MyTest2::m3); call3(MyTest2::m4); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AmbiguousConstructorCallWithLambdaInside.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AmbiguousConstructorCallWithLambdaInside.java index 96c76b4a99d1..6c56fe9b4761 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AmbiguousConstructorCallWithLambdaInside.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AmbiguousConstructorCallWithLambdaInside.java @@ -4,8 +4,8 @@ import java.util.function.Supplier; class OverloadCast { public void runMe() { - new OverloadCast(WhitespaceTokenizer::new, src -> new LowerCaseFilter(src)); - overloadCast(WhitespaceTokenizer::new, src -> new LowerCaseFilter(src)); + new OverloadCast(WhitespaceTokenizer::new, src -> new LowerCaseFilter(src)); + overloadCast(WhitespaceTokenizer::new, src -> new LowerCaseFilter(src)); } private OverloadCast(Supplier tokenizerFactory, Function filterCreator) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/CreateMethodFromMethodRefApplicability.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/CreateMethodFromMethodRefApplicability.java index 18864ddf7d99..1cb004a59305 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/CreateMethodFromMethodRefApplicability.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/CreateMethodFromMethodRefApplicability.java @@ -16,7 +16,7 @@ class DemoApplicationTests { Stream.of("") .map(l -> a.get(l.length())) .map(s -> new DemoApplicationTests()).findAny() - .map(d -> d.foo(this::bar)); + .map(d -> d.foo(this::bar)); } void foo(Consumer c) {} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java index cad6bc3d9eb9..bda9f7270b74 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java @@ -31,8 +31,8 @@ class Test { String i1 = instanceCall(this::m0); String i2 = instanceCall(this::m1); String i3 = instanceCall(this::m2); - String i4 = instanceCall(this::m01); - String i5 = instanceCall(this::m012); + String i4 = instanceCall(this::m01); + String i5 = instanceCall(this::m012); } void n0() { } @@ -53,7 +53,7 @@ class Test { Test s1 = staticCall(Test::n0); Test s2 = staticCall(Test::n1); Test s3 = staticCall(Test::n2); - Test s4 = staticCall(Test::n01); - Test s5 = staticCall(Test::n012); + Test s4 = staticCall(Test::n01); + Test s5 = staticCall(Test::n012); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialCompatibilityWithInvalidShape.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialCompatibilityWithInvalidShape.java index 547a5f1b784b..8b2cd92ac7a7 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialCompatibilityWithInvalidShape.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialCompatibilityWithInvalidShape.java @@ -34,7 +34,7 @@ class Test { { Set m = replyWith(this::query); System.out.println(m); - Set m1 = replyWith(this::query1); + Set m1 = replyWith(this::query1); System.out.println(m1); } }