[java-dfa] IDEA-307630 Constant values: remove warning at the beginning of |= and &= series

GitOrigin-RevId: 3841398346bfc13b26cd6bed05e51e762e2f78e1
This commit is contained in:
Tagir Valeev
2022-12-05 15:06:26 +00:00
committed by intellij-monorepo-bot
parent 604f30df53
commit c4fee89a6e
4 changed files with 41 additions and 1 deletions
@@ -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;
@@ -1,7 +1,7 @@
class Test {
public void foo(boolean x, boolean y, boolean z) {
boolean r = true;
<warning descr="Condition 'r' at the left side of assignment expression is always 'true'. Can be simplified">r</warning> &= x;
r &= x;
r &= y;
r &= z;
}
@@ -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;
<warning descr="Condition 'result' at the left side of assignment expression is always 'true'. Can be simplified">result</warning> |= check1();
<warning descr="Condition 'result' at the left side of assignment expression is always 'true'. Can be simplified">result</warning> |= check2();
<warning descr="Condition 'result' at the left side of assignment expression is always 'true'. Can be simplified">result</warning> |= check3();
return result;
}
native boolean check1();
native boolean check2();
native boolean check3();
}
@@ -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(); }
}