diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java
index 6b659386fbfe..3f18663a7573 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java
@@ -78,13 +78,15 @@ public class PointlessBitwiseExpressionInspection extends BaseInspection {
if (expression instanceof PsiPolyadicExpression) {
return calculateReplacementExpression((PsiPolyadicExpression)expression, ct);
}
- if (expression instanceof PsiPrefixExpression) {
- PsiPrefixExpression prefixExpression = (PsiPrefixExpression)expression;
- if (prefixExpression.getOperationTokenType().equals(TILDE)) {
- PsiExpression decremented = extractDecrementedValue(prefixExpression.getOperand());
- if (decremented != null) {
- return "-" + ct.text(decremented, ParenthesesUtils.PREFIX_PRECEDENCE);
- }
+ PsiExpression complemented = unwrapComplement(expression);
+ if (complemented != null) {
+ PsiExpression decremented = extractDecrementedValue(complemented);
+ if (decremented != null) {
+ return "-" + ct.text(decremented, ParenthesesUtils.PREFIX_PRECEDENCE);
+ }
+ PsiExpression twiceComplemented = unwrapComplement(complemented);
+ if (twiceComplemented != null) {
+ return ct.text(twiceComplemented);
}
}
return "";
@@ -133,8 +135,8 @@ public class PointlessBitwiseExpressionInspection extends BaseInspection {
}
}
else {
- PsiExpression left = unwrapNegation(previousOperand);
- PsiExpression right = unwrapNegation(operand);
+ PsiExpression left = optionallyUnwrapComplement(previousOperand);
+ PsiExpression right = optionallyUnwrapComplement(operand);
if (EquivalenceChecker.getCanonicalPsiEquivalence().expressionsAreEquivalent(left, right)) {
if (tokenType.equals(AND)) {
return getText(expression, previousOperand, operand, PsiType.LONG.equals(expression.getType()) ? "0L" : "0", ct);
@@ -231,8 +233,16 @@ public class PointlessBitwiseExpressionInspection extends BaseInspection {
@Override
public void visitPrefixExpression(PsiPrefixExpression expression) {
super.visitPrefixExpression(expression);
- if (expression.getOperationTokenType().equals(TILDE) && extractDecrementedValue(expression.getOperand()) != null) {
+ PsiExpression complemented = unwrapComplement(expression);
+ if (complemented == null) return;
+ if (extractDecrementedValue(complemented) != null) {
registerError(expression, expression);
+ } else {
+ PsiExpression twiceComplemented = unwrapComplement(complemented);
+ if (twiceComplemented != null && unwrapComplement(twiceComplemented) == null) {
+ // In case of triple or more complements report innermost only to avoid overlapping reports
+ registerError(expression, expression);
+ }
}
}
@@ -277,7 +287,7 @@ public class PointlessBitwiseExpressionInspection extends BaseInspection {
PsiExpression previousExpression = null;
for (PsiExpression operand : operands) {
if (isZero(operand) || isAllOnes(operand) ||
- (areEquivalentModuloNegation(previousExpression, operand) && !SideEffectChecker.mayHaveSideEffects(operand))) {
+ (areEquivalentModuloComplement(previousExpression, operand) && !SideEffectChecker.mayHaveSideEffects(operand))) {
return true;
}
previousExpression = operand;
@@ -285,8 +295,9 @@ public class PointlessBitwiseExpressionInspection extends BaseInspection {
return false;
}
- private boolean areEquivalentModuloNegation(PsiExpression op1, PsiExpression op2) {
- return EquivalenceChecker.getCanonicalPsiEquivalence().expressionsAreEquivalent(unwrapNegation(op1), unwrapNegation(op2));
+ private boolean areEquivalentModuloComplement(PsiExpression op1, PsiExpression op2) {
+ return EquivalenceChecker.getCanonicalPsiEquivalence().expressionsAreEquivalent(
+ optionallyUnwrapComplement(op1), optionallyUnwrapComplement(op2));
}
private boolean shiftExpressionIsPointless(PsiExpression[] operands) {
@@ -299,12 +310,17 @@ public class PointlessBitwiseExpressionInspection extends BaseInspection {
}
}
- private static PsiExpression unwrapNegation(PsiExpression op) {
- PsiExpression deparenthesized = PsiUtil.skipParenthesizedExprDown(op);
- if (deparenthesized instanceof PsiPrefixExpression && ((PsiPrefixExpression)deparenthesized).getOperationTokenType().equals(TILDE)) {
- return ((PsiPrefixExpression)deparenthesized).getOperand();
+ private static PsiExpression optionallyUnwrapComplement(PsiExpression op) {
+ PsiExpression unwrapped = unwrapComplement(op);
+ return unwrapped == null ? op : unwrapped;
+ }
+
+ private static PsiExpression unwrapComplement(PsiExpression op) {
+ op = PsiUtil.skipParenthesizedExprDown(op);
+ if (op instanceof PsiPrefixExpression && ((PsiPrefixExpression)op).getOperationTokenType().equals(TILDE)) {
+ return ((PsiPrefixExpression)op).getOperand();
}
- return op;
+ return null;
}
private boolean isZero(PsiExpression expression) {
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bitwise/pointless_bitwise_expression/PointlessBitwiseExpression.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bitwise/pointless_bitwise_expression/PointlessBitwiseExpression.java
index f94a7750038f..85b70114676a 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bitwise/pointless_bitwise_expression/PointlessBitwiseExpression.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bitwise/pointless_bitwise_expression/PointlessBitwiseExpression.java
@@ -93,4 +93,11 @@ public class PointlessBitwiseExpression {
int r8 = x | ~x;
long r9 = y ^ ~y;
}
+
+ void testDoubleTilde(int x, long y) {
+ int r1 = ~~x;
+ long r2 = ~~~y;
+ int r3 = ~(~(x));
+ long r4 = ~(~(~(~y)));
+ }
}