private static boolean hasOverflow(PsiExpression expr, @NotNull Project project) { if (!TypeConversionUtil.isNumericType(expr.getType())) return false; boolean overflow = false; try { if (expr.getUserData(HAS_OVERFLOW_IN_CHILD) == null) { JavaPsiFacade.getInstance(project).getConstantEvaluationHelper().computeConstantExpression(expr, true); } else { overflow = true; } } catch (ConstantEvaluationOverflowException e) { overflow = true; } finally { PsiElement parent = expr.getParent(); if (overflow && parent instanceof PsiExpression) { parent.putUserData(HAS_OVERFLOW_IN_CHILD, ""); } } return overflow; }
private void checkAdditionOverflow(boolean resultPositive, boolean lPositive, boolean rPositive, PsiElement expression) { if (!myThrowExceptionOnOverflow) return; boolean overflow = lPositive == rPositive && lPositive != resultPositive; if (overflow) throw new ConstantEvaluationOverflowException(expression); }
private void checkRealNumberOverflow(Object result, Object lOperandValue, Object rOperandValue, PsiElement expression) { if (!myThrowExceptionOnOverflow) return; if (lOperandValue instanceof Float && ((Float) lOperandValue).isInfinite()) return; if (lOperandValue instanceof Double && ((Double) lOperandValue).isInfinite()) return; if (rOperandValue instanceof Float && ((Float) rOperandValue).isInfinite()) return; if (rOperandValue instanceof Double && ((Double) rOperandValue).isInfinite()) return; if (result instanceof Float && ((Float) result).isInfinite()) throw new ConstantEvaluationOverflowException(expression); if (result instanceof Double && ((Double) result).isInfinite()) throw new ConstantEvaluationOverflowException(expression); }
@Override public void visitPolyadicExpression(@NotNull PsiPolyadicExpression expression) { super.visitPolyadicExpression(expression); final IElementType tokenType = expression.getOperationTokenType(); if (!tokenType.equals(JavaTokenType.ASTERISK) && !tokenType.equals(JavaTokenType.LTLT)) { return; } final PsiType type = expression.getType(); if (!isNonLongInteger(type)) { return; } if (expression.getOperands().length < 2 || expression.getLastChild() instanceof PsiErrorElement) { return; } final PsiExpression context = getContainingExpression(expression); if (context == null) { return; } final PsiType contextType = ExpectedTypeUtils.findExpectedType(context, true); if (contextType == null) { return; } if (!contextType.equals(PsiType.LONG)) { return; } if (ignoreNonOverflowingCompileTimeConstants) { try { if (ExpressionUtils.computeConstantExpression(expression, true) != null) { return; } } catch (ConstantEvaluationOverflowException ignore) { } } registerError(expression, tokenType); }
public boolean satisfiedBy(PsiElement element) { if (!(element instanceof PsiPolyadicExpression)) { return false; } if (element instanceof PsiLiteralExpression || element instanceof PsiClassObjectAccessExpression) { return false; } final PsiPolyadicExpression expression = (PsiPolyadicExpression)element; final PsiType expressionType = expression.getType(); if (expressionType == null || expressionType.equalsToText(JAVA_LANG_STRING)) { // intention disabled for string concatenations because of performance issues on // relatively common large string expressions. return false; } final PsiExpression[] operands = expression.getOperands(); for (PsiExpression operand : operands) { if (operand == null) { return false; } final PsiType type = operand.getType(); if (type == null || type.equalsToText(JAVA_LANG_STRING)) { return false; } } if (!PsiUtil.isConstantExpression(expression)) { return false; } try { final Object value = ExpressionUtils.computeConstantExpression(expression, true); if (value == null) { return false; } } catch (ConstantEvaluationOverflowException ignore) { return false; } final PsiElement parent = element.getParent(); return !(parent instanceof PsiExpression) || !PsiUtil.isConstantExpression((PsiExpression)parent); }
public boolean satisfiedBy(PsiElement element) { if (!(element instanceof PsiPolyadicExpression)) { return false; } if (element instanceof PsiLiteralExpression || element instanceof PsiClassObjectAccessExpression) { return false; } final PsiPolyadicExpression expression = (PsiPolyadicExpression)element; final PsiType expressionType = expression.getType(); if (expressionType == null || expressionType.equalsToText("java.lang.String")) { // intention disabled for string concatenations because of performance issues on // relatively common large string expressions. return false; } final PsiExpression[] operands = expression.getOperands(); for (PsiExpression operand : operands) { if (operand == null) { return false; } final PsiType type = operand.getType(); if (type == null || type.equalsToText("java.lang.String")) { return false; } } if (!PsiUtil.isConstantExpression(expression)) { return false; } try { final Object value = ExpressionUtils.computeConstantExpression(expression, true); if (value == null) { return false; } } catch (ConstantEvaluationOverflowException ignore) { return false; } final PsiElement parent = element.getParent(); return !(parent instanceof PsiExpression) || !PsiUtil.isConstantExpression((PsiExpression)parent); }
@Override public void visitPrefixExpression(PsiPrefixExpression expression) { PsiExpression operand = expression.getOperand(); Object operandValue = getStoredValue(operand); if (operandValue == null) { myResult = null; return; } IElementType tokenType = expression.getOperationTokenType(); Object value = null; if (tokenType == JavaTokenType.MINUS) { if (operandValue instanceof Character) operandValue = Integer.valueOf(((Character)operandValue).charValue()); if (operandValue instanceof Number) { if (operandValue instanceof Double) { value = new Double(-((Number)operandValue).doubleValue()); checkRealNumberOverflow(value, null, null, expression); } else if (operandValue instanceof Float) { value = new Float(-((Number)operandValue).floatValue()); checkRealNumberOverflow(value, null, null, expression); } else if (operandValue instanceof Long) { value = Long.valueOf(-((Number)operandValue).longValue()); if (myThrowExceptionOnOverflow && !(operand instanceof PsiLiteralExpression) && ((Number)operandValue).longValue() == Long.MIN_VALUE) { throw new ConstantEvaluationOverflowException(expression); } } else { value = Integer.valueOf(-((Number)operandValue).intValue()); if (myThrowExceptionOnOverflow && !(operand instanceof PsiLiteralExpression) && ((Number)operandValue).intValue() == Integer.MIN_VALUE) { throw new ConstantEvaluationOverflowException(expression); } } } } else if (tokenType == JavaTokenType.PLUS) { if (operandValue instanceof Character) operandValue = Integer.valueOf(((Character)operandValue).charValue()); if (operandValue instanceof Number) { value = operandValue; } } else if (tokenType == JavaTokenType.TILDE) { if (operandValue instanceof Character) operandValue = Integer.valueOf(((Character)operandValue).charValue()); if (isIntegral(operandValue)) { value = operandValue instanceof Long ? Long.valueOf(~((Number)operandValue).longValue()) : Integer.valueOf(~((Number)operandValue).intValue()); } } else if (tokenType == JavaTokenType.EXCL) { if (operandValue instanceof Boolean) { value = Boolean.valueOf(!((Boolean)operandValue).booleanValue()); } } myResult = value; }
private void checkDivisionOverflow(long l, final long r, long minValue, PsiElement expression) { if (!myThrowExceptionOnOverflow) return; if (r == 0) throw new ConstantEvaluationOverflowException(expression); if (r == -1 && l == minValue) throw new ConstantEvaluationOverflowException(expression); }
private void checkMultiplicationOverflow(long result, long l, long r, PsiElement expression) { if (!myThrowExceptionOnOverflow) return; if (r == 0 || l == 0) return; if (result / r != l || ((l < 0) ^ (r < 0) != (result < 0))) throw new ConstantEvaluationOverflowException(expression); }
@Override public void visitBinaryExpression( @NotNull PsiBinaryExpression expression) { super.visitBinaryExpression(expression); final IElementType tokenType = expression.getOperationTokenType(); if (!tokenType.equals(JavaTokenType.ASTERISK) && !tokenType.equals(JavaTokenType.LTLT)) { return; } final PsiType type = expression.getType(); if (!isNonLongInteger(type)) { return; } final PsiExpression rhs = expression.getROperand(); if (rhs == null) { return; } final PsiType rhsType = rhs.getType(); if (!isNonLongInteger(rhsType)) { return; } final PsiExpression context = getContainingExpression(expression); if (context == null) { return; } final PsiType contextType = ExpectedTypeUtils.findExpectedType(context, true); if (contextType == null) { return; } if (!contextType.equals(PsiType.LONG)) { return; } try { final Object result = ExpressionUtils.computeConstantExpression(expression, true); if (ignoreNonOverflowingCompileTimeConstants && result != null) { return; } } catch (ConstantEvaluationOverflowException ignore) { } registerError(expression); }