mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-386665 [java]: don't report lambda/method reference problems when their class type is unresolved
GitOrigin-RevId: e542751b8352847268bb6f98e83f5af33539e959
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d77eb20227
commit
9905bef526
+11
-12
@@ -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) {
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
class Demo {
|
||||
public static void main(String[] args) {
|
||||
Runnable r = () -> <error descr="void is not a functional interface">() -> () -> {}</error>;
|
||||
<error descr="Cannot resolve symbol 'Supplier'">Supplier</error><String> unresolved = String::new;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ class MyTest {
|
||||
|
||||
{
|
||||
Bar1 b1 = MyTest :: foo;
|
||||
bar(MyTest :: <error descr="Reference to 'foo' is ambiguous, both 'foo(String)' and 'foo(int)' match">foo</error>);
|
||||
bar<error descr="Ambiguous method call: both 'MyTest.bar(Bar1)' and 'MyTest.bar(Bar2)' match">(MyTest :: foo)</error>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ class StaticInner1 {
|
||||
static void call3(I2 s) {}
|
||||
|
||||
static {
|
||||
call3(StaticInner1.Inner :: <error descr="Cannot resolve constructor 'Inner'">new</error>);
|
||||
call3<error descr="Ambiguous method call: both 'StaticInner1.call3(I1)' and 'StaticInner1.call3(I2)' match">(StaticInner1.Inner :: new)</error>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import java.util.*;
|
||||
|
||||
class LambdaTest {
|
||||
public void testR() {
|
||||
new ArrayList<String>() :: <error descr="Reference to 'size' is ambiguous, both 'size()' and 'size()' match">size</error> = "";
|
||||
<error descr="Variable expected">new ArrayList<String>() :: size</error> = "";
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -116,7 +116,7 @@ class MyTest2 {
|
||||
static void call3(I2 s) {}
|
||||
static {
|
||||
call3(MyTest2::m1);
|
||||
call3(MyTest2::<error descr="Reference to 'm2' is ambiguous, both 'm2(MyTest2, String)' and 'm2(String)' match">m2</error>);
|
||||
call3<error descr="Ambiguous method call: both 'MyTest2.call3(I1)' and 'MyTest2.call3(I2)' match">(MyTest2::m2)</error>;
|
||||
call3(MyTest2::m3);
|
||||
call3(MyTest2::<error descr="Reference to 'm4' is ambiguous, both 'm4(MyTest2, String)' and 'm4(String)' match">m4</error>);
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@ import java.util.function.Supplier;
|
||||
class OverloadCast {
|
||||
|
||||
public void runMe() {
|
||||
new OverloadCast<error descr="Cannot resolve constructor 'OverloadCast(<method reference>, <lambda expression>)'">(WhitespaceTokenizer::<error descr="Cannot resolve constructor 'WhitespaceTokenizer'">new</error>, src -> new LowerCaseFilter(src))</error>;
|
||||
overloadCast<error descr="Ambiguous method call: both 'OverloadCast.overloadCast(Supplier<Tokenizer>, Function<TokenStream, TokenFilter>)' and 'OverloadCast.overloadCast(Function<TokenStream, TokenFilter>, Function<String, String>)' match">(WhitespaceTokenizer::<error descr="Cannot resolve constructor 'WhitespaceTokenizer'">new</error>, src -> new LowerCaseFilter(src))</error>;
|
||||
new OverloadCast<error descr="Cannot resolve constructor 'OverloadCast(<method reference>, <lambda expression>)'">(WhitespaceTokenizer::new, src -> new LowerCaseFilter(src))</error>;
|
||||
overloadCast<error descr="Ambiguous method call: both 'OverloadCast.overloadCast(Supplier<Tokenizer>, Function<TokenStream, TokenFilter>)' and 'OverloadCast.overloadCast(Function<TokenStream, TokenFilter>, Function<String, String>)' match">(WhitespaceTokenizer::new, src -> new LowerCaseFilter(src))</error>;
|
||||
}
|
||||
|
||||
private OverloadCast(Supplier<Tokenizer> tokenizerFactory, Function<TokenStream, TokenFilter> filterCreator) {
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ class DemoApplicationTests {
|
||||
Stream.of("")
|
||||
.map(l -> a.get(l.length()))
|
||||
.map(s -> new DemoApplicationTests()).findAny()
|
||||
.map(d -> d.foo(this::<error descr="Reference to 'bar' is ambiguous, both 'bar(int)' and 'bar(long)' match">bar</error>));
|
||||
.map(d -> d.foo<error descr="Ambiguous method call: both 'DemoApplicationTests.foo(Consumer<Object>)' and 'DemoApplicationTests.foo(Function<Object, Object>)' match">(this::bar)</error>);
|
||||
}
|
||||
|
||||
<T> void foo(Consumer<T> c) {}
|
||||
|
||||
+4
-4
@@ -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::<error descr="Reference to 'm01' is ambiguous, both 'm01()' and 'm01(String)' match">m01</error>);
|
||||
String i5 = instanceCall(this::<error descr="Reference to 'm012' is ambiguous, both 'm012()' and 'm012(String)' match">m012</error>);
|
||||
String i4 = instanceCall<error descr="Ambiguous method call: both 'Test.instanceCall(I0)' and 'Test.instanceCall(I1<Object>)' match">(this::m01)</error>;
|
||||
String i5 = instanceCall<error descr="Ambiguous method call: both 'Test.instanceCall(I0)' and 'Test.instanceCall(I1<Object>)' match">(this::m012)</error>;
|
||||
}
|
||||
|
||||
void n0() { }
|
||||
@@ -53,7 +53,7 @@ class Test {
|
||||
Test s1 = staticCall(Test::n0);
|
||||
Test s2 = staticCall(Test::n1);
|
||||
Test s3 = staticCall<error descr="Cannot resolve method 'staticCall(<method reference>)'">(Test::n2)</error>;
|
||||
Test s4 = staticCall(Test::<error descr="Reference to 'n01' is ambiguous, both 'n01()' and 'n01(String)' match">n01</error>);
|
||||
Test s5 = staticCall(Test::<error descr="Reference to 'n012' is ambiguous, both 'n012()' and 'n012(String)' match">n012</error>);
|
||||
Test s4 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Object>)' and 'Test.staticCall(I2<Object, String>)' match">(Test::n01)</error>;
|
||||
Test s5 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Object>)' and 'Test.staticCall(I2<Object, String>)' match">(Test::n012)</error>;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -34,7 +34,7 @@ class Test {
|
||||
{
|
||||
Set<String> m = replyWith(this::query);
|
||||
System.out.println(m);
|
||||
Set<String> m1 = replyWith(this::<error descr="Reference to 'query1' is ambiguous, both 'query1()' and 'query1(String)' match">query1</error>);
|
||||
Set<String> m1 = replyWith<error descr="Ambiguous method call: both 'Test.replyWith(Function<Object, List<Object>>)' and 'Test.replyWith(Callable<List<Object>>)' match">(this::query1)</error>;
|
||||
System.out.println(m1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user