From b0f1e6f2bed2755a29a8c06292780868aa29b907 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 11 May 2015 17:21:11 +0200 Subject: [PATCH] determining enclosing instances for inner class instance creation expressions: accept all qualified super exprs, invalid are checked separately (IDEA-139880) --- .../impl/analysis/HighlightClassUtil.java | 17 +++++++----- .../advHighlighting7/EnclosingInstance.java | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java index 28ae5e5eb691..a360745cb500 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java @@ -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; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/EnclosingInstance.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/EnclosingInstance.java index 4906f5498464..5d5b958e5f7a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/EnclosingInstance.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/EnclosingInstance.java @@ -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 {} \ No newline at end of file