IDEA-112358 'Constant Conditions' does not understand non-short-circuit 'or'

This commit is contained in:
peter
2013-08-21 19:08:48 +02:00
parent dbb57c5ddb
commit 78ecf28ff5
4 changed files with 60 additions and 6 deletions
@@ -998,14 +998,20 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
}
PsiType type = expression.getType();
if (op == JavaTokenType.ANDAND) {
generateAndExpression(operands, type);
generateAndExpression(operands, type, true);
}
else if (op == JavaTokenType.OROR) {
generateOrExpression(operands, type);
generateOrExpression(operands, type, true);
}
else if (op == JavaTokenType.XOR && PsiType.BOOLEAN.equals(type)) {
generateXorExpression(expression, operands, type);
}
else if (op == JavaTokenType.AND && PsiType.BOOLEAN.equals(type)) {
generateAndExpression(operands, type, false);
}
else if (op == JavaTokenType.OR && PsiType.BOOLEAN.equals(type)) {
generateOrExpression(operands, type, false);
}
else {
generateOther(expression, op, operands, type);
}
@@ -1104,11 +1110,18 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
}
}
private void generateOrExpression(PsiExpression[] operands, final PsiType exprType) {
private void generateOrExpression(PsiExpression[] operands, final PsiType exprType, boolean shortCircuit) {
for (int i = 0; i < operands.length; i++) {
PsiExpression operand = operands[i];
operand.accept(this);
generateBoxingUnboxingInstructionFor(operand, exprType);
if (!shortCircuit) {
if (i > 0) {
combineStackBooleans(false, operand);
}
continue;
}
PsiExpression nextOperand = i == operands.length - 1 ? null : operands[i + 1];
if (nextOperand != null) {
addInstruction(new ConditionalGotoInstruction(getStartOffset(nextOperand), true, operand));
@@ -1125,7 +1138,11 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
lExpression.accept(this);
generateBoxingUnboxingInstructionFor(lExpression, exprType);
ConditionalGotoInstruction toPopAndPushSuccess = new ConditionalGotoInstruction(-1, and, lExpression);
combineStackBooleans(and, lExpression);
}
private void combineStackBooleans(boolean and, PsiExpression anchor) {
ConditionalGotoInstruction toPopAndPushSuccess = new ConditionalGotoInstruction(-1, and, anchor);
addInstruction(toPopAndPushSuccess);
GotoInstruction overPushSuccess = new GotoInstruction(-1);
addInstruction(overPushSuccess);
@@ -1140,17 +1157,29 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
overPushSuccess.setOffset(pushSuccess.getIndex() + 1);
}
private void generateAndExpression(PsiExpression[] operands, final PsiType exprType) {
private void generateAndExpression(PsiExpression[] operands, final PsiType exprType, boolean shortCircuit) {
List<ConditionalGotoInstruction> branchToFail = new ArrayList<ConditionalGotoInstruction>();
for (PsiExpression operand : operands) {
for (int i = 0; i < operands.length; i++) {
PsiExpression operand = operands[i];
operand.accept(this);
generateBoxingUnboxingInstructionFor(operand, exprType);
if (!shortCircuit) {
if (i > 0) {
combineStackBooleans(false, operand);
}
continue;
}
ConditionalGotoInstruction onFail = new ConditionalGotoInstruction(-1, true, operand);
branchToFail.add(onFail);
addInstruction(onFail);
}
if (!shortCircuit) {
return;
}
addInstruction(new PushInstruction(myFactory.getConstFactory().getTrue(), null));
GotoInstruction toSuccess = new GotoInstruction(-1);
addInstruction(toSuccess);
@@ -36,4 +36,9 @@
<description>Condition &lt;code&gt;o&lt;/code&gt; at the left side of assignment expression is always &lt;code&gt;false&lt;/code&gt;. Can be simplified to normal assignment.</description>
</problem>
<problem>
<file>Test.java</file>
<line>52</line>
<description>Condition &lt;code&gt;o&lt;/code&gt; is always &lt;code&gt;true&lt;/code&gt;</description>
</problem>
</problems>
@@ -0,0 +1,19 @@
class X {
int foo(String d1, String d2) {
if(d1 == null | d2 == null)
return 0;
return d1.compareTo(d2);
}
void foo2(String d1, String d2) {
if(<warning descr="Condition 'd1 == null & d1 != null' is always 'true'">d1 == null & d1 != null</warning>)
System.out.println("impossible");
}
void foo3(String d1, String d2) {
if(d1 == null | <warning descr="Method invocation 'd1.compareTo(d2)' may produce 'java.lang.NullPointerException'">d1.compareTo(d2)</warning> > 0)
System.out.println("impossible");
}
}
@@ -286,4 +286,5 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testBoxingImpliesNotNull() { doTest(); }
public void testLargeIntegersAreNotEqualWhenBoxed() { doTest(); }
public void testNoGenericCCE() { doTest(); }
public void testLongCircuitOperations() { doTest(); }
}