mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
ControlFlowAnalyzer: translate switch using temporary variable
Fixes IDEA-195700 Incorrect NPE warning when conditional expression is used in switch
This commit is contained in:
+27
-15
@@ -848,13 +848,30 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
startElement(switchStmt);
|
||||
PsiExpression caseExpression = switchStmt.getExpression();
|
||||
Set<PsiEnumConstant> enumValues = null;
|
||||
if (caseExpression != null /*&& !(caseExpression instanceof PsiReferenceExpression)*/) {
|
||||
caseExpression.accept(this);
|
||||
DfaVariableValue expressionValue = null;
|
||||
if (caseExpression != null) {
|
||||
PsiType targetType = caseExpression.getType();
|
||||
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(targetType);
|
||||
if (unboxedType != null) {
|
||||
targetType = unboxedType;
|
||||
}
|
||||
expressionValue = getFactory().getVarFactory().createVariableValue(new DfaVariableSource() {
|
||||
@Override
|
||||
public boolean isStable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
generateBoxingUnboxingInstructionFor(caseExpression, PsiType.INT);
|
||||
final PsiClass psiClass = PsiUtil.resolveClassInType(caseExpression.getType());
|
||||
@Override
|
||||
public String toString() {
|
||||
return "switch$var";
|
||||
}
|
||||
}, targetType);
|
||||
addInstruction(new PushInstruction(expressionValue, null, true));
|
||||
caseExpression.accept(this);
|
||||
generateBoxingUnboxingInstructionFor(caseExpression, targetType);
|
||||
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(targetType);
|
||||
if (psiClass != null) {
|
||||
addInstruction(new DereferenceInstruction(caseExpression));
|
||||
addInstruction(new CheckNotNullInstruction(NullabilityProblemKind.fieldAccessNPE.problem(caseExpression)));
|
||||
if (psiClass.isEnum()) {
|
||||
enumValues = new HashSet<>();
|
||||
for (PsiField f : psiClass.getFields()) {
|
||||
@@ -863,10 +880,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addInstruction(new PopInstruction());
|
||||
}
|
||||
|
||||
addInstruction(new AssignInstruction(null, null));
|
||||
addInstruction(new PopInstruction());
|
||||
}
|
||||
|
||||
PsiCodeBlock body = switchStmt.getBody();
|
||||
@@ -894,12 +910,8 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
if (alwaysTrue) {
|
||||
addInstruction(new PushInstruction(myFactory.getConstFactory().getTrue(), null));
|
||||
}
|
||||
else if (caseValue != null &&
|
||||
caseExpression instanceof PsiReferenceExpression &&
|
||||
((PsiReferenceExpression)caseExpression).getQualifierExpression() == null) {
|
||||
|
||||
addInstruction(new PushInstruction(myFactory.createValue(caseExpression), caseExpression));
|
||||
generateBoxingUnboxingInstructionFor(caseExpression, PsiType.INT);
|
||||
else if (caseValue != null && expressionValue != null) {
|
||||
addInstruction(new PushInstruction(expressionValue, null));
|
||||
caseValue.accept(this);
|
||||
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, PsiType.BOOLEAN));
|
||||
}
|
||||
@@ -908,7 +920,6 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
}
|
||||
|
||||
addInstruction(new ConditionalGotoInstruction(offset, false, statement));
|
||||
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
@@ -925,6 +936,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
body.accept(this);
|
||||
}
|
||||
|
||||
addInstruction(new FlushVariableInstruction(expressionValue));
|
||||
finishElement(switchStmt);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,4 +25,20 @@ class InspectionTest {
|
||||
public static String test(@NotNull Object a) {
|
||||
return a.toString();
|
||||
}
|
||||
|
||||
enum X {A, B, C}
|
||||
|
||||
void testTernary(@Nullable String foo, X x) {
|
||||
switch (foo == null ? X.A : x) {
|
||||
case A:
|
||||
System.out.println(foo.<warning descr="Method invocation 'trim' may produce 'java.lang.NullPointerException'">trim</warning>());
|
||||
break;
|
||||
case B:
|
||||
System.out.println(foo.trim());
|
||||
break;
|
||||
case C:
|
||||
System.out.println(foo.trim());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user