mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-03 15:50:52 +07:00
IDEA-182699 Numeric overflow: add an option to ignore if left bitwise shift result makes number negative
This commit is contained in:
@@ -3,13 +3,19 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.ConstantEvaluationOverflowException;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author cdr
|
||||
@@ -17,6 +23,15 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class NumericOverflowInspection extends AbstractBaseJavaLocalInspectionTool {
|
||||
private static final Key<String> HAS_OVERFLOW_IN_CHILD = Key.create("HAS_OVERFLOW_IN_CHILD");
|
||||
|
||||
public boolean ignoreLeftShiftWithNegativeResult = true;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
return new SingleCheckboxOptionsPanel("Ignore '<<' operation which results in negative value", this,
|
||||
"ignoreLeftShiftWithNegativeResult");
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -48,14 +63,35 @@ public class NumericOverflowInspection extends AbstractBaseJavaLocalInspectionTo
|
||||
|
||||
@Override
|
||||
public void visitExpression(PsiExpression expression) {
|
||||
boolean info = hasOverflow(expression, holder.getProject());
|
||||
if (info) {
|
||||
boolean hasOverflow = hasOverflow(expression, holder.getProject());
|
||||
if (hasOverflow && (!ignoreLeftShiftWithNegativeResult || !isLeftShiftWithNegativeResult(expression, holder.getProject()))) {
|
||||
holder.registerProblem(expression, JavaErrorMessages.message("numeric.overflow.in.expression"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isLeftShiftWithNegativeResult(PsiExpression expression, Project project) {
|
||||
PsiBinaryExpression binOp = ObjectUtils.tryCast(PsiUtil.skipParenthesizedExprDown(expression), PsiBinaryExpression.class);
|
||||
if (binOp == null || !binOp.getOperationTokenType().equals(JavaTokenType.LTLT)) return false;
|
||||
PsiConstantEvaluationHelper helper = JavaPsiFacade.getInstance(project).getConstantEvaluationHelper();
|
||||
Object lOperandValue = helper.computeConstantExpression(binOp.getLOperand());
|
||||
Object rOperandValue = helper.computeConstantExpression(binOp.getROperand());
|
||||
if (lOperandValue instanceof Character) lOperandValue = (int)((Character)lOperandValue).charValue();
|
||||
if (rOperandValue instanceof Character) rOperandValue = (int)((Character)rOperandValue).charValue();
|
||||
if (!(lOperandValue instanceof Number) || !(rOperandValue instanceof Number)) return false;
|
||||
if (lOperandValue instanceof Long) {
|
||||
long l = ((Number)lOperandValue).longValue();
|
||||
long r = ((Number)rOperandValue).longValue();
|
||||
return Long.numberOfLeadingZeros(l) - (r & 0x3F) == 0;
|
||||
}
|
||||
else {
|
||||
int l = ((Number)lOperandValue).intValue();
|
||||
int r = ((Number)rOperandValue).intValue();
|
||||
return Integer.numberOfLeadingZeros(l) - (r & 0x1F) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasOverflow(PsiExpression expr, @NotNull Project project) {
|
||||
if (!TypeConversionUtil.isNumericType(expr.getType())) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user