DFA control flow: properly push inner class qualifier (IDEA-216732)

GitOrigin-RevId: 25db91c6e1e19e393c35a40450a9abd70ee49704
This commit is contained in:
Tagir Valeev
2019-07-10 13:03:18 +03:00
committed by intellij-monorepo-bot
parent a3e4728dbf
commit 09d64a4b1d
4 changed files with 57 additions and 10 deletions
@@ -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) {
@@ -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<? super PsiClass> 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<? super PsiClass> isSuperClassAccepted,
boolean isTypeParamsAccepted) {
@@ -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;
}
}
}
@@ -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(); }
}