<commit_before>package com.siyeh.ig.bugs;

import com.intellij.codeInspection.InspectionManager;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.ConstantExpressionUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.ExpressionInspection;
import com.siyeh.ig.GroupNames;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.WellFormednessUtils;

public class IncompatibleMaskInspection extends ExpressionInspection{
    public String getID(){
        return "IncompatibleBitwiseMaskOperation";
    }

    public String getDisplayName(){
        return "Incompatible bitwise mask operation";
    }

    public String getGroupDisplayName(){
        return GroupNames.BUGS_GROUP_NAME;
    }

    public boolean isEnabledByDefault(){
        return true;
    }

    public String buildErrorString(PsiElement location){
        final PsiBinaryExpression binaryExpression =
                (PsiBinaryExpression) location;
        final PsiJavaToken operationSign = binaryExpression.getOperationSign();
        final IElementType tokenType = operationSign.getTokenType();
        if(tokenType.equals(JavaTokenType.EQEQ)){
            return "#ref is always false #loc";
        } else{
            return "#ref is always true #loc";
        }
    }

    public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager,
                                               boolean onTheFly){
        return new IncompatibleMaskVisitor(this, inspectionManager, onTheFly);
    }

    private static class IncompatibleMaskVisitor extends BaseInspectionVisitor{
        private IncompatibleMaskVisitor(BaseInspection inspection,
                                        InspectionManager inspectionManager,
                                        boolean isOnTheFly){
            super(inspection, inspectionManager, isOnTheFly);
        }

        public void visitBinaryExpression(PsiBinaryExpression expression){
            super.visitBinaryExpression(expression);
            if(!WellFormednessUtils.isWellFormed(expression)){
                return;
            }
            if(!ComparisonUtils.isEqualityComparison(expression)){
                return;
            }
            final PsiType expressionType = expression.getType();
            if(expressionType == null){
                return;
            }
            final PsiExpression rhs = expression.getROperand();
            final PsiExpression strippedRhs = stripExpression(rhs);
            if(strippedRhs == null){
                return;
            }
            final PsiExpression lhs = expression.getLOperand();
            final PsiExpression strippedLhs = stripExpression(lhs);
            if(strippedLhs == null){
                return;
            }
            if(isConstantMask(strippedLhs) &&
                       PsiUtil.isConstantExpression(strippedRhs)){
                if(isIncompatibleMask((PsiBinaryExpression) strippedLhs,
                                      strippedRhs)){
                    registerError(expression);
                }
            } else if(isConstantMask(strippedRhs) &&
                              PsiUtil.isConstantExpression(strippedLhs)){
                if(isIncompatibleMask((PsiBinaryExpression) strippedRhs,
                                      strippedLhs)){
                    registerError(expression);
                }
            }
        }
    }

    private static PsiExpression stripExpression(PsiExpression exp){
        if(exp == null){
            return null;
        }
        if(exp instanceof PsiParenthesizedExpression){
            final PsiExpression body =
                    ((PsiParenthesizedExpression) exp).getExpression();
            return stripExpression(body);
        }
        return exp;
    }

    private static boolean isIncompatibleMask(PsiBinaryExpression maskExpression,
                                              PsiExpression constantExpression){
        final PsiJavaToken sign = maskExpression.getOperationSign();
        final IElementType tokenType = sign.getTokenType();
        final Object constantValue =
                ConstantExpressionUtil.computeCastTo(constantExpression,
                                                     PsiType.LONG);
        if(constantValue == null){
            return false;
        }
        final long constantLongValue = ((Long) constantValue).longValue();

        final long constantMaskValue;
        final PsiExpression maskRhs = maskExpression.getROperand();
        final PsiExpression maskLhs = maskExpression.getLOperand();
        if(PsiUtil.isConstantExpression(maskRhs)){
            final Object rhsValue =
                    ConstantExpressionUtil.computeCastTo(maskRhs, PsiType.LONG);
            constantMaskValue = ((Long) rhsValue).longValue();
        } else{
            final Object lhsValue =
                    ConstantExpressionUtil.computeCastTo(maskLhs, PsiType.LONG);
            constantMaskValue = ((Long) lhsValue).longValue();
        }

        if(tokenType.equals(JavaTokenType.OR)){
            if((constantMaskValue | constantLongValue) != constantLongValue){
                return true;
            }
        }
        if(tokenType.equals(JavaTokenType.AND)){
            if((constantMaskValue | constantLongValue) != constantMaskValue){
                return true;
            }
        }
        return false;
    }

    private static boolean isConstantMask(PsiExpression expression){
        if(expression == null){
            return false;
        }
        if(!(expression instanceof PsiBinaryExpression)){
            return false;
        }

        final PsiBinaryExpression binaryExpression =
                (PsiBinaryExpression) expression;<commit_msg>IDEADEV-740<commit_after>package com.siyeh.ig.bugs;

import com.intellij.codeInspection.InspectionManager;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.ConstantExpressionUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.ExpressionInspection;
import com.siyeh.ig.GroupNames;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.WellFormednessUtils;

public class IncompatibleMaskInspection extends ExpressionInspection{
    public String getID(){
        return "IncompatibleBitwiseMaskOperation";
    }

    public String getDisplayName(){
        return "Incompatible bitwise mask operation";
    }

    public String getGroupDisplayName(){
        return GroupNames.BUGS_GROUP_NAME;
    }

    public boolean isEnabledByDefault(){
        return true;
    }

    public String buildErrorString(PsiElement location){
        final PsiBinaryExpression binaryExpression =
                (PsiBinaryExpression) location;
        final PsiJavaToken operationSign = binaryExpression.getOperationSign();
        final IElementType tokenType = operationSign.getTokenType();
        if(tokenType.equals(JavaTokenType.EQEQ)){
            return "#ref is always false #loc";
        } else{
            return "#ref is always true #loc";
        }
    }

    public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager,
                                               boolean onTheFly){
        return new IncompatibleMaskVisitor(this, inspectionManager, onTheFly);
    }

    private static class IncompatibleMaskVisitor extends BaseInspectionVisitor{
        private IncompatibleMaskVisitor(BaseInspection inspection,
                                        InspectionManager inspectionManager,
                                        boolean isOnTheFly){
            super(inspection, inspectionManager, isOnTheFly);
        }

        public void visitBinaryExpression(PsiBinaryExpression expression){
            super.visitBinaryExpression(expression);
            if(!WellFormednessUtils.isWellFormed(expression)){
                return;
            }
            if(!ComparisonUtils.isEqualityComparison(expression)){
                return;
            }
            final PsiType expressionType = expression.getType();
            if(expressionType == null){
                return;
            }
            final PsiExpression rhs = expression.getROperand();
            final PsiExpression strippedRhs = stripExpression(rhs);
            if(strippedRhs == null){
                return;
            }
            final PsiExpression lhs = expression.getLOperand();
            final PsiExpression strippedLhs = stripExpression(lhs);
            if(strippedLhs == null){
                return;
            }
            if(isConstantMask(strippedLhs) &&
                       PsiUtil.isConstantExpression(strippedRhs)){
                if(isIncompatibleMask((PsiBinaryExpression) strippedLhs,
                                      strippedRhs)){
                    registerError(expression);
                }
            } else if(isConstantMask(strippedRhs) &&
                              PsiUtil.isConstantExpression(strippedLhs)){
                if(isIncompatibleMask((PsiBinaryExpression) strippedRhs,
                                      strippedLhs)){
                    registerError(expression);
                }
            }
        }
    }

    private static PsiExpression stripExpression(PsiExpression exp){
        if(exp == null){
            return null;
        }
        if(exp instanceof PsiParenthesizedExpression){
            final PsiExpression body =
                    ((PsiParenthesizedExpression) exp).getExpression();
            return stripExpression(body);
        }
        return exp;
    }

    private static boolean isIncompatibleMask(PsiBinaryExpression maskExpression,
                                              PsiExpression constantExpression){
        final PsiJavaToken sign = maskExpression.getOperationSign();
        final IElementType tokenType = sign.getTokenType();
        final Object constantValue =
                ConstantExpressionUtil.computeCastTo(constantExpression,
                                                     PsiType.LONG);
        if(constantValue == null){
            return false;
        }
        final long constantLongValue = ((Long) constantValue).longValue();

        final long constantMaskValue;
        final PsiExpression maskRhs = maskExpression.getROperand();
        final PsiExpression maskLhs = maskExpression.getLOperand();
        if(PsiUtil.isConstantExpression(maskRhs)){
            final Object rhsValue =
                    ConstantExpressionUtil.computeCastTo(maskRhs, PsiType.LONG);
            if (rhsValue == null) {
                return false; // Might indeed be the case with "null" literal whoes constant value evaluates to null. Check out (a|null) case.
            }
            constantMaskValue = ((Long) rhsValue).longValue();
        } else{
            final Object lhsValue =
                    ConstantExpressionUtil.computeCastTo(maskLhs, PsiType.LONG);
            constantMaskValue = ((Long) lhsValue).longValue();
        }

        if(tokenType.equals(JavaTokenType.OR)){
            if((constantMaskValue | constantLongValue) != constantLongValue){
                return true;
            }
        }
        if(tokenType.equals(JavaTokenType.AND)){
            if((constantMaskValue | constantLongValue) != constantMaskValue){
                return true;
            }
        }
        return false;
    }

    private static boolean isConstantMask(PsiExpression expression){
        if(expression == null){
            return false;
        }
        if(!(expression instanceof PsiBinaryExpression)){
            return false;
        }

        final PsiBinaryExpression binaryExpression =
                (PsiBinaryExpression) expression;
{'fraction_non_alphanumeric': 0.07455443059158229, 'fraction_numerical': 0.0002510250188268764, 'mean_word_length': 2.0113378684807257, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5530739', 'n_tokens_mistral': 2849, 'n_tokens_neox': 2768, 'n_words': 568}