From d0adc5895a0724a375d79a1aaf54bf2bd9a69ac6 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 15 Dec 2023 11:09:52 +0100 Subject: [PATCH] Java: fix good code is red super() call problem 3 (IDEA-340994) "Cannot reference class before supertype constructor has been called" GitOrigin-RevId: 70471c3f1a58c5c57ab229e24d39baa1794b8e72 --- .../daemon/impl/analysis/HighlightUtil.java | 8 ++++--- .../QualifiedThisCalledFromSuper.java | 22 +++++++++++++++++++ .../daemon/LightAdvHighlightingTest.java | 1 + 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/QualifiedThisCalledFromSuper.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 22b7af6b8feb..7b730b1e04dc 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -2679,6 +2679,7 @@ public final class HighlightUtil { PsiClass referencedClass; String resolvedName; PsiType type; + PsiElement parent = expression.getParent(); if (expression instanceof PsiJavaCodeReferenceElement) { // redirected ctr if (PsiKeyword.THIS.equals(((PsiJavaCodeReferenceElement)expression).getReferenceName()) @@ -2690,7 +2691,7 @@ public final class HighlightUtil { type = qualifier instanceof PsiExpression ? ((PsiExpression)qualifier).getType() : null; referencedClass = PsiUtil.resolveClassInType(type); - boolean isSuperCall = JavaPsiConstructorUtil.isSuperConstructorCall(expression.getParent()); + boolean isSuperCall = JavaPsiConstructorUtil.isSuperConstructorCall(parent); if (resolved == null && isSuperCall) { if (qualifier instanceof PsiReferenceExpression) { resolved = ((PsiReferenceExpression)qualifier).resolve(); @@ -2778,7 +2779,7 @@ public final class HighlightUtil { return null; } - PsiElement element = expression.getParent(); + PsiElement element = parent; while (element != null) { // check if expression inside super()/this() call @@ -2820,11 +2821,12 @@ public final class HighlightUtil { return null; } - if (expression.getParent() instanceof PsiNewExpression newExpression && + if (parent instanceof PsiNewExpression newExpression && newExpression.isArrayCreation() && newExpression.getClassOrAnonymousClassReference() == expression) { return null; } + if (parent instanceof PsiThisExpression || parent instanceof PsiSuperExpression) return null; } HighlightInfo.Builder builder = createMemberReferencedError(resolvedName, expression.getTextRange()); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/QualifiedThisCalledFromSuper.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/QualifiedThisCalledFromSuper.java new file mode 100644 index 000000000000..c2756b631c34 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/QualifiedThisCalledFromSuper.java @@ -0,0 +1,22 @@ +class FirstLevel { + FirstLevel(int i) { + } + + int hello() { + return 1; + } + + class SecondLevel extends FirstLevel { + SecondLevel() { + super(1); + } + + + class ThirdLevel extends FirstLevel { + ThirdLevel() { + super(SecondLevel.this.hello()); + } + + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingTest.java index 5cda1f3dfcae..2ff6bfe3aeb7 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingTest.java @@ -380,6 +380,7 @@ public class LightAdvHighlightingTest extends LightDaemonAnalyzerTestCase { public void testExplicitConstructorInvocation() { doTest(false); } public void testExtendFinalClass() { doTest(false); } public void testPrivateMethodCalledFromSuper() { doTest(false); } + public void testQualifiedThisCalledFromSuper() { doTest(false); } public void testReferenceToClassFromSuper() { IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_16, () -> doTest(false)); } public void testThisInInterface() { doTest(false); } public void testInnerClassConstantReference() { doTest(false); }