/* * Copyright 2000-2009 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.psi.impl; import com.intellij.openapi.util.Key; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.ConstantEvaluationOverflowException; import com.intellij.psi.util.ConstantExpressionUtil; import com.intellij.util.containers.StringInterner; import gnu.trove.THashSet; import java.util.Set; import java.util.concurrent.ConcurrentMap; class ConstantExpressionVisitor extends JavaElementVisitor implements PsiConstantEvaluationHelper.AuxEvaluator { private final StringInterner myInterner = new StringInterner(); private Set<PsiVariable> myVisitedVars; private final boolean myThrowExceptionOnOverflow; private Object myResult; private final PsiConstantEvaluationHelper.AuxEvaluator myAuxEvaluator; ConstantExpressionVisitor(Set<PsiVariable> visitedVars, boolean throwExceptionOnOverflow, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) { myVisitedVars = visitedVars; myThrowExceptionOnOverflow = throwExceptionOnOverflow; myAuxEvaluator = auxEvaluator; } Object handle(PsiElement element) { myResult = null; element.accept(this); store(element, myResult); return myResult; } private static final Key<Object> VALUE = Key.create("VALUE"); private static Object getStoredValue(PsiElement element) { if (element == null) { return null; } try { return element.getUserData(VALUE); } finally { element.putUserData(VALUE, null); } } static void store(PsiElement element, Object value) { element.putUserData(VALUE, value); } @Override public void visitLiteralExpression(PsiLiteralExpression expression) { final Object value = expression.getValue(); myResult = value instanceof String ? myInterner.intern((String)value) : value; } @Override public void visitTypeCastExpression(PsiTypeCastExpression expression) { final PsiTypeElement castTypeElement = expression.getCastType(); PsiExpression operand = expression.getOperand(); Object opValue = getStoredValue(operand); if(castTypeElement == null || opValue == null) { myResult = null; return; } PsiType castType = castTypeElement.getType(); myResult = ConstantExpressionUtil.computeCastTo(opValue, castType); } @Override public void visitConditionalExpression(PsiConditionalExpression expression) { Object then = getStoredValue(expression.getThenExpression()); Object els = getStoredValue(expression.getElseExpression()); Object condition = getStoredValue(expression.getCondition()); if (then == null || els == null) { myResult = null; return; } Object value = null; if (condition instanceof Boolean) { value = ((Boolean)condition).booleanValue() ? then : els; } myResult = value; } @Override public void visitPolyadicExpression(PsiPolyadicExpression expression) { PsiExpression[] operands = expression.getOperands(); Object lValue = getStoredValue(operands[0]); if (lValue == null) { myResult = null; return; } IElementType tokenType = expression.getOperationTokenType(); for (int i = 1; i < operands.length; i++) { PsiExpression operand = operands[i]; Object rValue = getStoredValue(operand); if (rValue == null) { myResult = null; break; } myResult = compute(lValue, rValue, tokenType, expression); if (myResult == null) { break; } lValue = myResult; } if (myResult instanceof String) { myResult = myInterner.intern((String)myResult); } } private Object compute(Object lOperandValue, Object rOperandValue, IElementType tokenType, PsiElement expression) { Object value = null; if (tokenType == JavaTokenType.PLUS) { if (lOperandValue instanceof String || rOperandValue instanceof String) { String l = lOperandValue.toString(); String r = rOperandValue.toString(); value = l + r; } else { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { if (lOperandValue instanceof Double || rOperandValue instanceof Double) { value = new Double(((Number)lOperandValue).doubleValue() + ((Number)rOperandValue).doubleValue()); checkRealNumberOverflow(value, lOperandValue, rOperandValue,expression); } else if (lOperandValue instanceof Float || rOperandValue instanceof Float) { value = new Float(((Number)lOperandValue).floatValue() + ((Number)rOperandValue).floatValue()); checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression); } else if (lOperandValue instanceof Long || rOperandValue instanceof Long) { final long l = ((Number)lOperandValue).longValue(); final long r = ((Number)rOperandValue).longValue(); value = Long.valueOf(l + r); checkAdditionOverflow(((Long)value).longValue() >= 0, l >= 0, r >= 0, expression); } else { final int l = ((Number)lOperandValue).intValue(); final int r = ((Number)rOperandValue).intValue(); value = Integer.valueOf(l + r); checkAdditionOverflow(((Integer)value).intValue() >= 0, l >= 0, r >= 0, expression); } } } } else if (tokenType == JavaTokenType.MINUS) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { if (lOperandValue instanceof Double || rOperandValue instanceof Double) { value = new Double(((Number)lOperandValue).doubleValue() - ((Number)rOperandValue).doubleValue()); checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression); } else if (lOperandValue instanceof Float || rOperandValue instanceof Float) { value = new Float(((Number)lOperandValue).floatValue() - ((Number)rOperandValue).floatValue()); checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression); } else if (lOperandValue instanceof Long || rOperandValue instanceof Long) { final long l = ((Number)lOperandValue).longValue(); final long r = ((Number)rOperandValue).longValue(); value = Long.valueOf(l - r); checkAdditionOverflow(((Long)value).longValue() >= 0, l >= 0, r < 0, expression); } else { final int l = ((Number)lOperandValue).intValue(); final int r = ((Number)rOperandValue).intValue(); value = Integer.valueOf(l - r); checkAdditionOverflow(((Integer)value).intValue() >= 0, l >= 0, r < 0, expression); } } } else if (tokenType == JavaTokenType.ANDAND) { if (lOperandValue instanceof Boolean && !((Boolean)lOperandValue).booleanValue()) { value = Boolean.FALSE; } else if (rOperandValue instanceof Boolean && !((Boolean)rOperandValue).booleanValue()) { value = Boolean.FALSE; } else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) { value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() && ((Boolean)rOperandValue).booleanValue()); } } else if (tokenType == JavaTokenType.OROR) { if (lOperandValue instanceof Boolean && ((Boolean)lOperandValue).booleanValue()) { value = Boolean.TRUE; } else if (rOperandValue instanceof Boolean && ((Boolean)rOperandValue).booleanValue()) { value = Boolean.TRUE; } else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) { value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() || ((Boolean)rOperandValue).booleanValue()); } } else if (tokenType == JavaTokenType.LT) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { value = Boolean.valueOf(((Number)lOperandValue).doubleValue() < ((Number)rOperandValue).doubleValue()); } } else if (tokenType == JavaTokenType.LE) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { value = Boolean.valueOf(((Number)lOperandValue).doubleValue() <= ((Number)rOperandValue).doubleValue()); } } else if (tokenType == JavaTokenType.GT) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { value = Boolean.valueOf(((Number)lOperandValue).doubleValue() > ((Number)rOperandValue).doubleValue()); } } else if (tokenType == JavaTokenType.GE) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { value = Boolean.valueOf(((Number)lOperandValue).doubleValue() >= ((Number)rOperandValue).doubleValue()); } } else if (tokenType == JavaTokenType.EQEQ) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { value = Boolean.valueOf(((Number)lOperandValue).doubleValue() == ((Number)rOperandValue).doubleValue()); } else if (lOperandValue instanceof String && rOperandValue instanceof String) { value = Boolean.valueOf(lOperandValue == rOperandValue); } else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) { value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() == ((Boolean)rOperandValue).booleanValue()); } } else if (tokenType == JavaTokenType.NE) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { value = Boolean.valueOf(((Number)lOperandValue).doubleValue() != ((Number)rOperandValue).doubleValue()); } else if (lOperandValue instanceof String && rOperandValue instanceof String) { value = Boolean.valueOf(lOperandValue != rOperandValue); } else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) { value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() != ((Boolean)rOperandValue).booleanValue()); } } else if (tokenType == JavaTokenType.ASTERISK) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { if (lOperandValue instanceof Double || rOperandValue instanceof Double) { value = new Double(((Number)lOperandValue).doubleValue() * ((Number)rOperandValue).doubleValue()); checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression); } else if (lOperandValue instanceof Float || rOperandValue instanceof Float) { value = new Float(((Number)lOperandValue).floatValue() * ((Number)rOperandValue).floatValue()); checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression); } else if (lOperandValue instanceof Long || rOperandValue instanceof Long) { final long l = ((Number)lOperandValue).longValue(); final long r = ((Number)rOperandValue).longValue(); value = Long.valueOf(l * r); checkMultiplicationOverflow(((Long)value).longValue(), l, r, expression); } else { final int l = ((Number)lOperandValue).intValue(); final int r = ((Number)rOperandValue).intValue(); value = Integer.valueOf(l * r); checkMultiplicationOverflow(((Integer)value).intValue(), l, r, expression); } } } else if (tokenType == JavaTokenType.DIV) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { if (lOperandValue instanceof Double || rOperandValue instanceof Double) { value = new Double(((Number)lOperandValue).doubleValue() / ((Number)rOperandValue).doubleValue()); checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression); } else if (lOperandValue instanceof Float || rOperandValue instanceof Float) { value = new Float(((Number)lOperandValue).floatValue() / ((Number)rOperandValue).floatValue()); checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression); } else if (lOperandValue instanceof Long || rOperandValue instanceof Long) { final long r = ((Number)rOperandValue).longValue(); final long l = ((Number)lOperandValue).longValue(); checkDivisionOverflow(l, r, Long.MIN_VALUE, expression); value = r == 0 ? null : Long.valueOf(l / r); } else { final int r = ((Number)rOperandValue).intValue(); final int l = ((Number)lOperandValue).intValue(); checkDivisionOverflow(l, r, Integer.MIN_VALUE, expression); value = r == 0 ? null : Integer.valueOf(l / r); } } } else if (tokenType == JavaTokenType.PERC) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (lOperandValue instanceof Number && rOperandValue instanceof Number) { double rVal = ((Number)rOperandValue).doubleValue(); if (myThrowExceptionOnOverflow && rVal == 0) throw new ConstantEvaluationOverflowException(expression); if (lOperandValue instanceof Double || rOperandValue instanceof Double) { value = new Double(((Number)lOperandValue).doubleValue() % ((Number)rOperandValue).doubleValue()); checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression); } else if (lOperandValue instanceof Float || rOperandValue instanceof Float) { value = new Float(((Number)lOperandValue).floatValue() % ((Number)rOperandValue).floatValue()); checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression); } else if (lOperandValue instanceof Long || rOperandValue instanceof Long) { final long l = ((Number)lOperandValue).longValue(); final long r = ((Number)rOperandValue).longValue(); checkDivisionOverflow(l, r, Long.MIN_VALUE, expression); value = r == 0 ? null : Long.valueOf(l % r); } else { final int l = ((Number)lOperandValue).intValue(); final int r = ((Number)rOperandValue).intValue(); checkDivisionOverflow(l, r, Integer.MIN_VALUE, expression); value = r == 0 ? null : Integer.valueOf(l % r); } } } else if (tokenType == JavaTokenType.LTLT) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) { if (lOperandValue instanceof Long) { value = Long.valueOf(((Number)lOperandValue).longValue() << ((Number)rOperandValue).longValue()); } else { value = Integer.valueOf(((Number)lOperandValue).intValue() << ((Number)rOperandValue).intValue()); } } } else if (tokenType == JavaTokenType.GTGT) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) { if (lOperandValue instanceof Long) { value = Long.valueOf(((Number)lOperandValue).longValue() >> ((Number)rOperandValue).longValue()); } else { value = Integer.valueOf(((Number)lOperandValue).intValue() >> ((Number)rOperandValue).intValue()); } } } else if (tokenType == JavaTokenType.GTGTGT) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) { if (lOperandValue instanceof Long) { value = Long.valueOf(((Number)lOperandValue).longValue() >>> ((Number)rOperandValue).longValue()); } else { value = Integer.valueOf(((Number)lOperandValue).intValue() >>> ((Number)rOperandValue).intValue()); } } } else if (tokenType == JavaTokenType.AND) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) { if (lOperandValue instanceof Long || rOperandValue instanceof Long) { value = Long.valueOf(((Number)lOperandValue).longValue() & ((Number)rOperandValue).longValue()); } else { value = Integer.valueOf(((Number)lOperandValue).intValue() & ((Number)rOperandValue).intValue()); } } else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) { value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() && ((Boolean)rOperandValue).booleanValue()); } } else if (tokenType == JavaTokenType.OR) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) { if (lOperandValue instanceof Long || rOperandValue instanceof Long) { value = Long.valueOf(((Number)lOperandValue).longValue() | ((Number)rOperandValue).longValue()); } else { value = Integer.valueOf(((Number)lOperandValue).intValue() | ((Number)rOperandValue).intValue()); } } else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) { value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() || ((Boolean)rOperandValue).booleanValue()); } } else if (tokenType == JavaTokenType.XOR) { if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue()); if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue()); if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) { if (lOperandValue instanceof Long || rOperandValue instanceof Long) { value = Long.valueOf(((Number)lOperandValue).longValue() ^ ((Number)rOperandValue).longValue()); } else { value = Integer.valueOf(((Number)lOperandValue).intValue() ^ ((Number)rOperandValue).intValue()); } } else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) { value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() ^ ((Boolean)rOperandValue).booleanValue()); } } return value; } @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; } @Override public void visitParenthesizedExpression(PsiParenthesizedExpression expression) { myResult = getStoredValue(expression.getExpression()); } @Override public void visitMethodCallExpression(final PsiMethodCallExpression expression) { myResult = myAuxEvaluator != null? myAuxEvaluator.computeExpression(expression, this) : null; } @Override public void visitReferenceExpression(PsiReferenceExpression expression) { PsiExpression qualifierExpression = expression.getQualifierExpression(); while (qualifierExpression != null) { if (!(qualifierExpression instanceof PsiReferenceExpression)) { myResult = null; return; } PsiReferenceExpression qualifier = (PsiReferenceExpression) qualifierExpression; final PsiElement resolved = qualifier.resolve(); if (resolved instanceof PsiPackage) break; if (!(resolved instanceof PsiClass)) { myResult = null; return; } qualifierExpression = ((PsiReferenceExpression) qualifierExpression).getQualifierExpression(); } PsiElement resolvedExpression = expression.resolve(); if (resolvedExpression instanceof PsiVariable) { PsiVariable variable = (PsiVariable) resolvedExpression; // avoid cycles if (myVisitedVars != null && myVisitedVars.contains(variable)) { myResult = null; return; } Set<PsiVariable> oldVisitedVars = myVisitedVars; if (myVisitedVars == null) { myVisitedVars = new THashSet<PsiVariable>(); } myVisitedVars.add(variable); try { myResult = variable instanceof PsiVariableEx? ((PsiVariableEx) variable).computeConstantValue(myVisitedVars) : null; if (myResult == null && myAuxEvaluator != null) myResult = myAuxEvaluator.computeExpression(expression, this); return; } finally { myVisitedVars.remove(variable); myVisitedVars = oldVisitedVars; } } myResult = null; } private static boolean isIntegral(Object o) { return o instanceof Long || o instanceof Integer || o instanceof Short || o instanceof Byte || o instanceof Character; } 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); } 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 Object computeExpression(final PsiExpression expression, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) { return JavaConstantExpressionEvaluator.computeConstantExpression(expression, myVisitedVars, myThrowExceptionOnOverflow, auxEvaluator); } @Override public ConcurrentMap<PsiElement, Object> getCacheMap(final boolean overflow) { throw new AssertionError("should not be called"); } }