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 5970172f778d..94c0b8b66563 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 @@ -153,54 +153,55 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { return; } - lExpr.accept(this); - IElementType op = expression.getOperationTokenType(); PsiType type = expression.getType(); boolean isBoolean = PsiType.BOOLEAN.equals(type); if (op == JavaTokenType.EQ) { + lExpr.accept(this); rExpr.accept(this); generateBoxingUnboxingInstructionFor(rExpr, type); } else if (op == JavaTokenType.ANDEQ) { if (isBoolean) { - generateNonLazyExpression(true, lExpr, rExpr, type); + generateBooleanAssignmentExpression(true, lExpr, rExpr, type); } else { - generateDefaultBinOp(lExpr, rExpr, type); + generateDefaultAssignmentBinOp(lExpr, rExpr, type); } } else if (op == JavaTokenType.OREQ) { if (isBoolean) { - generateNonLazyExpression(false, lExpr, rExpr, type); + generateBooleanAssignmentExpression(false, lExpr, rExpr, type); } else { - generateDefaultBinOp(lExpr, rExpr, type); + generateDefaultAssignmentBinOp(lExpr, rExpr, type); } } else if (op == JavaTokenType.XOREQ) { if (isBoolean) { - generateXorExpression(expression, new PsiExpression[]{lExpr, rExpr}, type); + generateXorExpression(expression, new PsiExpression[]{lExpr, rExpr}, type, true); } else { - generateDefaultBinOp(lExpr, rExpr, type); + generateDefaultAssignmentBinOp(lExpr, rExpr, type); } } else if (op == JavaTokenType.PLUSEQ && type != null && type.equalsToText(JAVA_LANG_STRING)) { lExpr.accept(this); + addInstruction(new DupInstruction()); rExpr.accept(this); addInstruction(new BinopInstruction(JavaTokenType.PLUS, null, lExpr.getProject())); } else { - generateDefaultBinOp(lExpr, rExpr, type); + generateDefaultAssignmentBinOp(lExpr, rExpr, type); } addInstruction(new AssignInstruction(rExpr)); finishElement(expression); } - private void generateDefaultBinOp(PsiExpression lExpr, PsiExpression rExpr, final PsiType exprType) { + private void generateDefaultAssignmentBinOp(PsiExpression lExpr, PsiExpression rExpr, final PsiType exprType) { lExpr.accept(this); + addInstruction(new DupInstruction()); generateBoxingUnboxingInstructionFor(lExpr,exprType); rExpr.accept(this); generateBoxingUnboxingInstructionFor(rExpr, exprType); @@ -1062,7 +1063,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { generateOrExpression(operands, type, true); } else if (op == JavaTokenType.XOR && PsiType.BOOLEAN.equals(type)) { - generateXorExpression(expression, operands, type); + generateXorExpression(expression, operands, type, false); } else if (op == JavaTokenType.AND && PsiType.BOOLEAN.equals(type)) { generateAndExpression(operands, type, false); @@ -1153,9 +1154,12 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { } } - private void generateXorExpression(PsiExpression expression, PsiExpression[] operands, final PsiType exprType) { + private void generateXorExpression(PsiExpression expression, PsiExpression[] operands, final PsiType exprType, boolean forAssignment) { PsiExpression operand = operands[0]; operand.accept(this); + if (forAssignment) { + addInstruction(new DupInstruction()); + } generateBoxingUnboxingInstructionFor(operand, exprType); for (int i = 1; i < operands.length; i++) { operand = operands[i]; @@ -1187,7 +1191,11 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { } } - private void generateNonLazyExpression(boolean and, PsiExpression lExpression, PsiExpression rExpression, PsiType exprType) { + private void generateBooleanAssignmentExpression(boolean and, PsiExpression lExpression, PsiExpression rExpression, PsiType exprType) { + lExpression.accept(this); + addInstruction(new DupInstruction()); + generateBoxingUnboxingInstructionFor(lExpression, exprType); + rExpression.accept(this); generateBoxingUnboxingInstructionFor(rExpression, exprType); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/NotEqualsTypo.java b/java/java-tests/testData/inspection/dataFlow/fixture/NotEqualsTypo.java new file mode 100644 index 000000000000..17413ddae617 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/NotEqualsTypo.java @@ -0,0 +1,12 @@ +class Some { + boolean foo(Object first, Object second) { + boolean isEqual = true; + + if (first != null || second -= null) { + return isEqual; + } + + return isEqual; + } + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index 3ce3fe86fa6a..7e0362713496 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -301,5 +301,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testDontMakeUnrelatedVariableFalseWhenMerging() { doTest(); } public void testDontLoseInequalityInformation() { doTest(); } + public void testNotEqualsTypo() { doTest(); } + public void _testNullCheckBeforeInstanceof() { doTest(); } // http://youtrack.jetbrains.com/issue/IDEA-113220 }