static methods of interfaces: accept calls on type parameters with exact one interface bound (IDEA-145269)

This commit is contained in:
Anna Kozlova
2015-09-18 14:37:14 +03:00
parent 434d9b2ec9
commit 8b322fadb7
3 changed files with 54 additions and 4 deletions
@@ -468,11 +468,29 @@ public class LambdaUtil {
return "Static interface method invocations are not supported at this language level";
}
if (qualifierExpression == null &&
(scope instanceof PsiImportStaticStatement || PsiTreeUtil.isAncestor(containingClass, methodReferenceExpression, true)) ||
qualifierExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifierExpression).resolve() == containingClass) {
if (qualifierExpression == null && (scope instanceof PsiImportStaticStatement || PsiTreeUtil.isAncestor(containingClass, methodReferenceExpression, true))) {
return null;
}
if (qualifierExpression instanceof PsiReferenceExpression) {
final PsiElement resolve = ((PsiReferenceExpression)qualifierExpression).resolve();
if (resolve == containingClass) {
return null;
}
if (resolve instanceof PsiTypeParameter) {
final Set<PsiClass> classes = new HashSet<PsiClass>();
for (PsiClassType type : ((PsiTypeParameter)resolve).getExtendsListTypes()) {
final PsiClass aClass = type.resolve();
if (aClass != null) {
classes.add(aClass);
}
}
if (classes.size() == 1 && classes.contains(containingClass)) {
return null;
}
}
}
return "Static method may be invoked on containing interface class only";
}
return null;
@@ -58,7 +58,10 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
if (isAccepted(method) && !(isInterfaceStaticMethodAccessibleThroughInheritance(method) && ImportsUtil.hasStaticImportOn(myPlace, method, true))) {
if (!staticProblem && myAccessClass != null && method.hasModifierProperty(PsiModifier.STATIC)) {
final PsiClass containingClass = method.getContainingClass();
if (containingClass != null && containingClass.isInterface() && !containingClass.equals(myAccessClass)) {
if (containingClass != null &&
containingClass.isInterface() &&
!(myAccessClass instanceof PsiTypeParameter) &&
!containingClass.equals(myAccessClass)) {
staticProblem = true;
}
}
@@ -22,4 +22,33 @@ class Bug {
Function<Integer, Integer> h = IFunction.<error descr="Static method may be invoked on containing interface class only">identity</error>();
}
}
class StaticMethodInterfaceExample {
interface X {}
interface MyInterface {
static void staticMethod() {}
}
static class MyImplementation implements MyInterface { }
public static class Usage {
public <T extends MyInterface> void doStuff() {
T.staticMethod();
}
public <T extends MyImplementation> void doStuff1() {
<error descr="Static method may be invoked on containing interface class only">T.staticMethod();</error>
}
public <T extends MyInterface & X> void doStuff2() {
<error descr="Static method may be invoked on containing interface class only">T.staticMethod();</error>
}
public <T extends MyImplementation & MyInterface> void doStuff3() {
<error descr="Static method may be invoked on containing interface class only">T.staticMethod();</error>
}
}
}