[java-highlighting] IDEA-316141 incorrect resolving static reference to static method in interfaces

GitOrigin-RevId: d558946ecb71dd2edb475d96508b1965a1036d9a
This commit is contained in:
Mikhail Pyltsin
2023-04-06 16:07:12 +02:00
committed by intellij-monorepo-bot
parent aec2d04db5
commit 899e5292e5
5 changed files with 95 additions and 1 deletions

View File

@@ -740,7 +740,7 @@ public final class HighlightMethodUtil {
return null;
}
/* see also PsiReferenceExpressionImpl.hasValidQualifier() */
/* see also PsiReferenceExpressionImpl.hasValidQualifier(), StaticImportResolveProcessor.filterStaticMethodsFromOtherInterfaces() */
private static @NlsContexts.DetailedDescription String checkStaticInterfaceMethodCallQualifier(@NotNull PsiJavaCodeReferenceElement ref,
@Nullable PsiElement scope,
@NotNull PsiClass containingClass) {

View File

@@ -87,6 +87,7 @@ public class StaticImportResolveProcessor implements PsiScopeProcessor, NameHint
public JavaResolveResult @NotNull [] getResults() {
if (myResults.size() + myFieldResults.size() + myClassResult.size() > 1) {
filterStaticMethodsFromOtherInterfaces(myResults);
filterInvalid(myResults);
filterInvalid(myFieldResults);
filterInvalid(myClassResult);
@@ -100,6 +101,39 @@ public class StaticImportResolveProcessor implements PsiScopeProcessor, NameHint
return myResults.toArray(JavaResolveResult.EMPTY_ARRAY);
}
/**
* If the length of results is 1, do nothing. If this result has errors, it will be checked later. <br>
* (See HighlightMethodUtil.checkStaticInterfaceMethodCallQualifier()) <br>
* Otherwise results with methods from other interfaces should be deleted <br>
* (see JavaMethodsConflictResolver.checkStaticMethodsOfInterfaces())
*/
private void filterStaticMethodsFromOtherInterfaces(List<JavaResolveResult> results) {
if (results.size() <= 1) {
return;
}
ListIterator<JavaResolveResult> iterator = results.listIterator();
PsiElement qualifier = myReference.getQualifier();
if (!(qualifier instanceof PsiReference)) {
return;
}
PsiElement resolved = ((PsiReference)qualifier).resolve();
if (!(resolved instanceof PsiClass)) {
return;
}
while (iterator.hasNext()) {
JavaResolveResult result = iterator.next();
if (!(result.getElement() instanceof PsiMethod)) {
continue;
}
PsiClass containingClass = ((PsiMethod)result.getElement()).getContainingClass();
if (containingClass != null && containingClass.isInterface()) {
if (!containingClass.getManager().areElementsEquivalent(resolved, containingClass)) {
iterator.remove();
}
}
}
}
private static void filterInvalid(final List<JavaResolveResult> resultList) {
if (resultList.isEmpty()) return;
for (ListIterator<JavaResolveResult> i = resultList.listIterator(resultList.size()); i.hasPrevious();) {

View File

@@ -0,0 +1,8 @@
package sample;
import static sample.Lambda1.lambda;
class Sample {
public static void main(String[] args) {
lambda();
}
}

View File

@@ -0,0 +1,8 @@
package sample;
import static sample.Lambda2.<error descr="Cannot resolve symbol 'lambda'">lambda</error>;
class Sample {
public static void main(String[] args) {
<error descr="Cannot resolve method 'lambda' in 'Sample'">lambda</error>();
}
}

View File

@@ -128,6 +128,50 @@ public class Interface8MethodsHighlightingTest extends LightJavaCodeInsightFixtu
doTest();
}
public void testAmbiguousStaticCall() {
myFixture.addClass("""
package sample;
interface Lambda0 {
void run();
static <T> Lambda0 lambda() {
return () -> {};
}
}
""");
myFixture.addClass("""
package sample;
interface Lambda1 extends Lambda0 {
static <E1 extends Exception> Lambda1 lambda() {
return ()->{};
}
}
""");
doTest();
}
public void testAmbiguousStaticCall2() {
myFixture.addClass("""
package sample;
interface Lambda0 {
void run();
static <T> Lambda0 lambda() {
return () -> {};
}
}
""");
myFixture.addClass("""
package sample;
interface Lambda1 extends Lambda0 {
static <E1 extends Exception> Lambda1 lambda() {
return ()->{};
}
}
""");
myFixture.addClass("""
package sample;
interface Lambda2 extends Lambda1 {}""");
doTest();
}
private void doTest() {
doTest(false, false);
}