@Override
    public void visitJSBinaryExpression(@NotNull JSBinaryExpression expression) {
      super.visitJSBinaryExpression(expression);
      final IElementType sign = expression.getOperationSign();
      if (!bitwiseTokens.contains(sign)) {
        return;
      }

      final JSExpression rhs = expression.getROperand();
      if (rhs == null) {
        return;
      }

      final JSExpression lhs = expression.getLOperand();

      final boolean isPointless;
      if (JSTokenTypes.AND.equals(sign)) {
        isPointless = andExpressionIsPointless(lhs, rhs);
      } else if (JSTokenTypes.OR.equals(sign)) {
        isPointless = orExpressionIsPointless(lhs, rhs);
      } else if (JSTokenTypes.XOR.equals(sign)) {
        isPointless = xorExpressionIsPointless(lhs, rhs);
      } else if (JSTokenTypes.LTLT.equals(sign)
          || JSTokenTypes.GTGT.equals(sign)
          || JSTokenTypes.GTGTGT.equals(sign)) {
        isPointless = shiftExpressionIsPointless(rhs);
      } else {
        isPointless = false;
      }
      if (isPointless) {
        registerError(expression, expression);
      }
    }
  @Override
  public String getTextForElement(PsiElement element) {
    final JSAssignmentExpression exp = (JSAssignmentExpression) element;
    final JSBinaryExpression rhs = (JSBinaryExpression) exp.getROperand();
    assert (rhs != null);
    final IElementType sign = rhs.getOperationSign();

    return this.getText(BinaryOperatorUtils.getOperatorText(sign));
  }
  @Override
  public void processIntention(@NotNull PsiElement element) throws IncorrectOperationException {
    final JSBinaryExpression exp = (JSBinaryExpression) element;
    final JSExpression lhs = exp.getLOperand();
    final JSExpression rhs = exp.getROperand();
    final IElementType sign = exp.getOperationSign();
    final String negatedOperator = ComparisonUtils.getNegatedOperatorText(sign);
    final String lhsText = lhs.getText();

    assert (rhs != null);

    JSElementFactory.replaceExpressionWithNegatedExpressionString(
        exp, lhsText + negatedOperator + rhs.getText());
  }
  @Override
  public void processIntention(@NotNull PsiElement element) throws IncorrectOperationException {
    final JSAssignmentExpression exp = (JSAssignmentExpression) element;
    final JSBinaryExpression rhs = (JSBinaryExpression) exp.getROperand();
    final JSExpression lhs = exp.getLOperand();

    assert (rhs != null);

    final IElementType sign = rhs.getOperationSign();
    final String operand = BinaryOperatorUtils.getOperatorText(sign);
    final JSExpression rhsrhs = rhs.getROperand();

    assert (rhsrhs != null);

    JSElementFactory.replaceExpression(exp, lhs.getText() + operand + '=' + rhsrhs.getText());
  }
    @Override
    public boolean satisfiedBy(@NotNull PsiElement element) {
      if (!(element instanceof JSAssignmentExpression)) {
        return false;
      }
      if (ErrorUtil.containsError(element)) {
        return false;
      }
      final JSAssignmentExpression assignment = (JSAssignmentExpression) element;
      final IElementType tokenType = assignment.getOperationSign();
      if (!JSTokenTypes.EQ.equals(tokenType)) {
        return false;
      }
      JSExpression lhs = assignment.getLOperand();
      final JSExpression rhs = assignment.getROperand();

      if (lhs instanceof JSDefinitionExpression) {
        lhs = ((JSDefinitionExpression) lhs).getExpression();
      }
      if (lhs == null || rhs == null) {
        return false;
      }
      if (!(rhs instanceof JSBinaryExpression)) {
        return false;
      }
      final JSBinaryExpression binaryRhs = (JSBinaryExpression) rhs;
      final JSExpression rhsRhs = binaryRhs.getROperand();
      final JSExpression rhsLhs = binaryRhs.getLOperand();

      if (rhsRhs == null) {
        return false;
      }

      final IElementType rhsTokenType = binaryRhs.getOperationSign();

      if (JSTokenTypes.OROR.equals(rhsTokenType) || JSTokenTypes.ANDAND.equals(rhsTokenType)) {
        return false;
      }
      if (SideEffectChecker.mayHaveSideEffects(lhs)) {
        return false;
      }
      return EquivalenceChecker.expressionsAreEquivalent(lhs, rhsLhs);
    }
  @Override
  public String getTextForElement(PsiElement element) {
    final JSBinaryExpression expression = (JSBinaryExpression) element;
    String operatorText = "";
    String negatedOperatorText = "";

    if (expression != null) {
      final IElementType sign = expression.getOperationSign();

      operatorText = ComparisonUtils.getOperatorText(sign);
      negatedOperatorText = ComparisonUtils.getNegatedOperatorText(sign);
    }

    if (operatorText.equals(negatedOperatorText)) {
      return this.getSuffixedDisplayName("equals", operatorText);
    } else {
      return this.getSuffixedDisplayName("not-equals", operatorText, negatedOperatorText);
    }
  }
 String calculateReplacementExpression(JSExpression expression) {
   final JSBinaryExpression exp = (JSBinaryExpression) expression;
   final JSExpression lhs = exp.getLOperand();
   final JSExpression rhs = exp.getROperand();
   final IElementType tokenType = exp.getOperationSign();
   assert rhs != null;
   if (tokenType.equals(JSTokenTypes.AND)) {
     if (isZero(lhs) || isAllOnes(rhs)) {
       return lhs.getText();
     } else {
       return rhs.getText();
     }
   } else if (tokenType.equals(JSTokenTypes.OR)) {
     if (isZero(lhs) || isAllOnes(rhs)) {
       return rhs.getText();
     } else {
       return lhs.getText();
     }
   } else if (tokenType.equals(JSTokenTypes.XOR)) {
     if (isAllOnes(lhs)) {
       return '~' + rhs.getText();
     } else if (isAllOnes(rhs)) {
       return '~' + lhs.getText();
     } else if (isZero(rhs)) {
       return lhs.getText();
     } else {
       return rhs.getText();
     }
   } else if (tokenType.equals(JSTokenTypes.LTLT)
       || tokenType.equals(JSTokenTypes.GTGT)
       || tokenType.equals(JSTokenTypes.GTGTGT)) {
     return lhs.getText();
   } else {
     return "";
   }
 }
 @Override
 public void invoke(
     @NotNull Project project,
     @NotNull PsiFile psiFile,
     @Nullable("is null when called from inspection") Editor editor,
     @NotNull PsiElement element,
     @NotNull PsiElement end)
     throws IncorrectOperationException {
   //        PsiElement element = descriptor.getPsiElement();
   JSBinaryExpression binary = PsiTreeUtil.getParentOfType(element, JSBinaryExpression.class);
   JSBinaryExpression binaryClone = (JSBinaryExpression) binary.copy();
   binaryClone.getLOperand().replace(binary.getLOperand().getLastChild());
   ASTNode negate = JSChangeUtil.createStatementFromText(project, "!(true)");
   JSParenthesizedExpression paren =
       PsiTreeUtil.getChildOfType(
           negate.getPsi().getFirstChild(), JSParenthesizedExpression.class);
   paren.getInnerExpression().replace(binaryClone);
   binary.replace(negate.getPsi());
 }