resolve/overload resolution: collect static methods of interface called on foreign class/instance but filter them out during overload resolution (IDEA-145187)

This commit is contained in:
Anna Kozlova
2015-09-17 12:49:52 +03:00
parent bf3fecbb61
commit 99a54a3e76
3 changed files with 76 additions and 0 deletions

View File

@@ -110,6 +110,9 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
checkParametersNumber(conflicts, getActualParametersLength(), false);
if (conflicts.size() == 1) return conflicts.get(0);
checkStaticMethodsOfInterfaces(conflicts);
if (conflicts.size() == 1) return conflicts.get(0);
final int applicabilityLevel = checkApplicability(conflicts);
if (conflicts.size() == 1) return conflicts.get(0);
@@ -357,6 +360,51 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
return ((MethodCandidateInfo)info).getPertinentApplicabilityLevel() != MethodCandidateInfo.ApplicabilityLevel.NOT_APPLICABLE;
}
/**
* choose to accept static interface methods during search to get "Static interface methods must be invoked on containing interface class only" error
* instead of non clear javac message that symbol not found
*
* but these methods should be ignored during overload resolution if another methods are present
*/
private void checkStaticMethodsOfInterfaces(@NotNull List<CandidateInfo> conflicts) {
if (!(myArgumentsList instanceof PsiExpressionList)) return;
PsiClass qualifierClass = null;
for (Iterator<CandidateInfo> iterator = conflicts.iterator(); iterator.hasNext(); ) {
CandidateInfo conflict = iterator.next();
if (!(conflict instanceof MethodCandidateInfo)) continue;
final PsiMethod method = ((MethodCandidateInfo)conflict).getElement();
if (method.hasModifierProperty(PsiModifier.STATIC)) {
final PsiClass containingClass = method.getContainingClass();
if (containingClass != null && containingClass.isInterface()) {
if (qualifierClass == null) {
qualifierClass = getQualifiedClass(method);
if (qualifierClass == null) return;
}
if (!containingClass.getManager().areElementsEquivalent(containingClass, qualifierClass)) {
iterator.remove();
}
}
}
}
}
private PsiClass getQualifiedClass(PsiMethod method) {
final PsiElement parent = myArgumentsList.getParent();
if (parent instanceof PsiMethodCallExpression) {
final PsiExpression expression = ((PsiMethodCallExpression)parent).getMethodExpression().getQualifierExpression();
if (expression instanceof PsiReferenceExpression) {
final PsiElement resolve = ((PsiReferenceExpression)expression).resolve();
if (resolve instanceof PsiClass) {
return (PsiClass)resolve;
}
}
else if (expression == null && !ImportsUtil.hasStaticImportOn(parent, method, true)) {
return PsiTreeUtil.getParentOfType(parent, PsiClass.class);
}
}
return null;
}
public boolean checkParametersNumber(@NotNull List<CandidateInfo> conflicts,
final int argumentsCount,
boolean ignoreIfStaticsProblem) {

View File

@@ -0,0 +1,23 @@
interface A {
static void foo110() {}
}
abstract class B implements A {
static void foo110(String... strs){
System.out.println(strs);
}
static void bar110(){}
}
abstract class C extends B {
static void bar110(String... strs){
System.out.println(strs);
}
}
class D {
public static void main(String[] args) {
B.foo110();
C.bar110();
}
}

View File

@@ -16,6 +16,7 @@
package com.intellij.codeInsight.daemon.lambda;
import com.intellij.JavaTestUtil;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NonNls;
@@ -77,6 +78,10 @@ public class Interface8MethodsHighlightingTest extends LightCodeInsightFixtureTe
public void testIDEA120498() { doTest(false, false); }
public void testIgnoreStaticInterfaceMethods() throws Exception {
doTest(true, false);
}
private void doTest() {
doTest(false, false);
}