From 09d64a4b1d47cfc1bf289f846210c3fe5a3e6fa3 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 10 Jul 2019 16:29:04 +0700 Subject: [PATCH] DFA control flow: properly push inner class qualifier (IDEA-216732) GitOrigin-RevId: 25db91c6e1e19e393c35a40450a9abd70ee49704 --- .../dataFlow/ControlFlowAnalyzer.java | 22 +++++++---- .../intellij/psi/util/InheritanceUtil.java | 7 ++-- .../fixture/FieldRewrittenInInner.java | 37 +++++++++++++++++++ .../DataFlowInspectionTest.java | 1 + 4 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/FieldRewrittenInInner.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 6ac5830bdc4e..076b83ed1071 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -1801,12 +1801,6 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { @Override public void visitNewExpression(PsiNewExpression expression) { startElement(expression); - PsiExpression qualifier = expression.getQualifier(); - if (qualifier != null) { - qualifier.accept(this); - addInstruction(new PopInstruction()); - } - PsiType type = expression.getType(); if (type instanceof PsiArrayType) { PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer(); @@ -1850,7 +1844,21 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { initializeSmallArray((PsiArrayType)type, var, dimensions); } else { - pushUnknown(); // qualifier + PsiExpression qualifier = expression.getQualifier(); + DfaValue qualifierValue = DfaUnknownValue.getInstance(); + if (qualifier != null) { + qualifier.accept(this); + } else { + PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(expression.getType()); + if (aClass != null) { + PsiClass outerClass = aClass.getContainingClass(); + if (outerClass != null && InheritanceUtil.hasEnclosingInstanceInScope(outerClass, expression, true, false)) { + qualifierValue = myFactory.getVarFactory().createThisValue(outerClass); + } + } + addInstruction(new PushInstruction(qualifierValue, null)); + } + PsiMethod constructor = pushConstructorArguments(expression); PsiAnonymousClass anonymousClass = expression.getAnonymousClass(); if (anonymousClass != null) { diff --git a/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java b/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java index 71aa4cad904c..c3523ebafc7f 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java @@ -132,21 +132,22 @@ public class InheritanceUtil { } } - public static boolean hasEnclosingInstanceInScope(PsiClass aClass, + public static boolean hasEnclosingInstanceInScope(@NotNull PsiClass aClass, PsiElement scope, boolean isSuperClassAccepted, boolean isTypeParamsAccepted) { return hasEnclosingInstanceInScope(aClass, scope, psiClass -> isSuperClassAccepted, isTypeParamsAccepted); } - public static boolean hasEnclosingInstanceInScope(PsiClass aClass, + public static boolean hasEnclosingInstanceInScope(@NotNull PsiClass aClass, PsiElement scope, Condition isSuperClassAccepted, boolean isTypeParamsAccepted) { return findEnclosingInstanceInScope(aClass, scope, isSuperClassAccepted, isTypeParamsAccepted) != null; } - public static PsiClass findEnclosingInstanceInScope(PsiClass aClass, + @Nullable + public static PsiClass findEnclosingInstanceInScope(@NotNull PsiClass aClass, PsiElement scope, Condition isSuperClassAccepted, boolean isTypeParamsAccepted) { diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/FieldRewrittenInInner.java b/java/java-tests/testData/inspection/dataFlow/fixture/FieldRewrittenInInner.java new file mode 100644 index 000000000000..4259d5e70835 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/FieldRewrittenInInner.java @@ -0,0 +1,37 @@ +class Tester +{ + public static void main(String[] args) + { + new Tester(); + } + + private boolean flag; + + private Tester() + { + // qualified ctor: should drop locality + this.new Inner(); + if (flag) + System.err.println("Is true."); + else + System.err.println("Is false"); + } + + private Tester(boolean b) + { + // unqualified ctor: should drop locality + new Inner(); + if (flag) + System.err.println("Is true."); + else + System.err.println("Is false"); + } + + class Inner + { + Inner() + { + flag = true; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java index 5ab200f05312..49b0613bfc4b 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java @@ -662,4 +662,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase { public void testInferenceForNonStableParameters() { doTest(); } public void testNullableTernaryInConstructor() { doTest(); } public void testEqualityLongInteger() { doTest(); } + public void testFieldRewrittenInInner() { doTest(); } }