determining enclosing instances for inner class instance creation expressions: accept all qualified super exprs, invalid are checked separately (IDEA-139880)

This commit is contained in:
Anna Kozlova
2015-05-11 18:04:31 +02:00
parent 90e240041a
commit b0f1e6f2be
2 changed files with 36 additions and 7 deletions
@@ -758,7 +758,7 @@ public class HighlightClassUtil {
if (!PsiUtil.isInnerClass(base)) return;
if (resolve == resolved && baseClass != null && (!PsiTreeUtil.isAncestor(baseClass, extendRef, true) || aClass.hasModifierProperty(PsiModifier.STATIC)) &&
!InheritanceUtil.hasEnclosingInstanceInScope(baseClass, extendRef, !aClass.hasModifierProperty(PsiModifier.STATIC), true) && !qualifiedNewCalledInConstructors(aClass, baseClass)) {
!InheritanceUtil.hasEnclosingInstanceInScope(baseClass, extendRef, !aClass.hasModifierProperty(PsiModifier.STATIC), true) && !qualifiedNewCalledInConstructors(aClass)) {
String description = JavaErrorMessages.message("no.enclosing.instance.in.scope", HighlightUtil.formatClass(baseClass));
infos[0] = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(extendRef).descriptionAndTooltip(description).create();
}
@@ -769,7 +769,10 @@ public class HighlightClassUtil {
return infos[0];
}
private static boolean qualifiedNewCalledInConstructors(final PsiClass aClass, final PsiClass baseClass) {
/**
* 15.9 Class Instance Creation Expressions | 15.9.2 Determining Enclosing Instances
*/
private static boolean qualifiedNewCalledInConstructors(final PsiClass aClass) {
PsiMethod[] constructors = aClass.getConstructors();
if (constructors.length == 0) return false;
for (PsiMethod constructor : constructors) {
@@ -785,11 +788,11 @@ public class HighlightClassUtil {
if (PsiKeyword.THIS.equals(methodCallExpression.getMethodExpression().getReferenceName())) continue;
PsiReferenceExpression referenceExpression = methodCallExpression.getMethodExpression();
PsiExpression qualifierExpression = PsiUtil.skipParenthesizedExprDown(referenceExpression.getQualifierExpression());
if (!(qualifierExpression instanceof PsiReferenceExpression) && !(qualifierExpression instanceof PsiCallExpression)) return false;
PsiType type = qualifierExpression.getType();
if (!(type instanceof PsiClassType)) return false;
PsiClass resolved = ((PsiClassType)type).resolve();
if (resolved != baseClass) return false;
//If the class instance creation expression is qualified, then the immediately
//enclosing instance of i is the object that is the value of the Primary expression or the ExpressionName,
//otherwise aClass needs to be a member of a class enclosing the class in which the class instance creation expression appears
//already excluded by InheritanceUtil.hasEnclosingInstanceInScope
if (qualifierExpression == null) return false;
}
return true;
}
@@ -20,3 +20,29 @@ class UsageWithParenthesis extends NonDefaultConstructorContainer.Inner {
(e).super("");
}
}
class ClassA {
public class InnerSuperClass {
public void method() {
}
}
}
class ClassB extends ClassA {
public static class StaticInnerSubClass extends InnerSuperClass {
public StaticInnerSubClass(boolean f) {
(f ? new ClassD() : new ClassC()).super();
}
public StaticInnerSubClass() {
new ClassD().super();
}
public StaticInnerSubClass(String s) {
new ClassB().super();
}
}
}
class ClassC extends ClassA {}
class ClassD extends ClassC {}