diff --git a/java/java-impl-inspections/src/com/intellij/codeInspection/dataFlow/ConstantValueInspection.java b/java/java-impl-inspections/src/com/intellij/codeInspection/dataFlow/ConstantValueInspection.java index 9776b7b24423..4b7cbc2f62bf 100644 --- a/java/java-impl-inspections/src/com/intellij/codeInspection/dataFlow/ConstantValueInspection.java +++ b/java/java-impl-inspections/src/com/intellij/codeInspection/dataFlow/ConstantValueInspection.java @@ -21,6 +21,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.controlFlow.DefUseUtil; import com.intellij.psi.impl.source.PsiFieldImpl; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; @@ -429,6 +430,10 @@ public class ConstantValueInspection extends AbstractBaseJavaLocalInspectionTool if (PsiUtil.skipParenthesizedExprUp(psiAnchor.getParent()) instanceof PsiAssignmentExpression assignment && PsiTreeUtil.isAncestor(assignment.getLExpression(), psiAnchor, false)) { + IElementType tokenType = assignment.getOperationTokenType(); + if (tokenType.equals(JavaTokenType.ANDEQ) || tokenType.equals(JavaTokenType.OREQ)) { + if (isFlagSetChain(assignment.getLExpression(), tokenType.equals(JavaTokenType.ANDEQ))) return; + } reporter.registerProblem( psiAnchor, JavaAnalysisBundle.message("dataflow.message.pointless.assignment.expression", Boolean.toString(evaluatesToTrue)), @@ -456,6 +461,18 @@ public class ConstantValueInspection extends AbstractBaseJavaLocalInspectionTool reporter.registerProblem(psiAnchor, message, fixes.toArray(LocalQuickFix.EMPTY_ARRAY)); } + private static boolean isFlagSetChain(@NotNull PsiExpression expression, boolean isAnd) { + PsiLocalVariable local = ExpressionUtils.resolveLocalVariable(expression); + if (local == null) return false; + PsiExpression initializer = local.getInitializer(); + if (!ExpressionUtils.isLiteral(initializer, isAnd)) return false; + if (!(PsiUtil.getVariableCodeBlock(local, null) instanceof PsiCodeBlock block)) return false; + PsiElement[] defs = DefUseUtil.getDefs(block, local, expression.getParent()); + // boolean x = false; x|=something; + return defs.length == 1 && defs[0] == local && + VariableAccessUtils.getVariableReferences(local, block).stream().filter(PsiUtil::isAccessedForWriting).limit(2).count() > 1; + } + private static @Nullable LocalQuickFix createSimplifyBooleanExpressionFix(PsiElement element, final boolean value) { LocalQuickFixOnPsiElement fix = createSimplifyBooleanFix(element, value); if (fix == null) return null; diff --git a/java/java-tests/testData/inspection/dataFlow/ancient/AndEq.java b/java/java-tests/testData/inspection/dataFlow/ancient/AndEq.java index fce099daa2c1..065cc91db952 100644 --- a/java/java-tests/testData/inspection/dataFlow/ancient/AndEq.java +++ b/java/java-tests/testData/inspection/dataFlow/ancient/AndEq.java @@ -1,7 +1,7 @@ class Test { public void foo(boolean x, boolean y, boolean z) { boolean r = true; - r &= x; + r &= x; r &= y; r &= z; } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/BooleanOrEquals.java b/java/java-tests/testData/inspection/dataFlow/fixture/BooleanOrEquals.java new file mode 100644 index 000000000000..6f80de67991a --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/BooleanOrEquals.java @@ -0,0 +1,22 @@ +// IDEA-304296 +class BooleanOrEquals { + boolean test() { + boolean result = false; + result |= check1(); + result |= check2(); + result |= check3(); + return result; + } + + boolean testWrong() { + boolean result = true; + result |= check1(); + result |= check2(); + result |= check3(); + return result; + } + + native boolean check1(); + native boolean check2(); + native boolean check3(); +} \ 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 dc8d471812c2..b377c0809034 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java @@ -722,4 +722,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase { public void testSuppression() { doTest(); } public void testRewiringSubclassMethod() { doTest(); } public void testTryWithResourcesCloseThrows() { doTest(); } + public void testBooleanOrEquals() { doTest(); } }