customizable value calculation
[fedora-idea.git] / source / com / intellij / psi / impl / ConstantExpressionVisitor.java
blobdba09dae077f32df134b8facc4a8d1cf04de50e2
1 package com.intellij.psi.impl;
3 import com.intellij.openapi.util.Key;
4 import com.intellij.psi.*;
5 import com.intellij.psi.tree.IElementType;
6 import com.intellij.psi.util.ConstantEvaluationOverflowException;
7 import com.intellij.psi.util.ConstantExpressionUtil;
8 import com.intellij.util.containers.StringInterner;
9 import gnu.trove.THashSet;
11 import java.util.Set;
12 import java.util.concurrent.ConcurrentMap;
14 class ConstantExpressionVisitor extends JavaElementVisitor implements PsiConstantEvaluationHelper.AuxEvaluator {
15 private final StringInterner myInterner = new StringInterner();
17 private Set<PsiVariable> myVisitedVars;
18 private final boolean myThrowExceptionOnOverflow;
20 private Object myResult;
22 private final PsiConstantEvaluationHelper.AuxEvaluator myAuxEvaluator;
24 ConstantExpressionVisitor(Set<PsiVariable> visitedVars, boolean throwExceptionOnOverflow, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) {
25 myVisitedVars = visitedVars;
26 myThrowExceptionOnOverflow = throwExceptionOnOverflow;
27 myAuxEvaluator = auxEvaluator;
30 Object handle(PsiElement element) {
31 myResult = null;
32 element.accept(this);
33 store(element, myResult);
34 //for (PsiElement child : element.getChildren()) {
35 // store(child, null); //erase garbage
36 //}
37 return myResult;
39 private static final Key<Object> VALUE = Key.create("VALUE");
40 private static Object getStoredValue(PsiElement element) {
41 if (element == null) {
42 return null;
44 try {
45 return element.getUserData(VALUE);
47 finally {
48 element.putUserData(VALUE, null);
51 static void store(PsiElement element, Object value) {
52 element.putUserData(VALUE, value);
55 @Override
56 public void visitLiteralExpression(PsiLiteralExpression expression) {
57 final Object value = expression.getValue();
58 myResult = value instanceof String ? myInterner.intern((String)value) : value;
61 @Override
62 public void visitTypeCastExpression(PsiTypeCastExpression expression) {
63 final PsiTypeElement castTypeElement = expression.getCastType();
65 PsiExpression operand = expression.getOperand();
66 Object opValue = getStoredValue(operand);
67 if(castTypeElement == null || opValue == null) {
68 myResult = null;
69 return;
72 PsiType castType = castTypeElement.getType();
73 myResult = ConstantExpressionUtil.computeCastTo(opValue, castType);
76 @Override public void visitConditionalExpression(PsiConditionalExpression expression) {
77 Object then = getStoredValue(expression.getThenExpression());
78 Object els = getStoredValue(expression.getElseExpression());
79 Object condition = getStoredValue(expression.getCondition());
80 if (then == null || els == null) {
81 myResult = null;
82 return;
85 Object value = null;
87 if (condition instanceof Boolean) {
88 value = ((Boolean)condition).booleanValue() ? then : els;
91 myResult = value;
94 @Override
95 public void visitBinaryExpression(PsiBinaryExpression expression) {
96 Object lOperandValue = getStoredValue(expression.getLOperand());
97 if (lOperandValue == null) {
98 myResult = null;
99 return;
102 Object rOperandValue = getStoredValue(expression.getROperand());
103 if (rOperandValue == null) {
104 myResult = null;
105 return;
108 PsiJavaToken operationSign = expression.getOperationSign();
109 final IElementType tokenType = operationSign.getTokenType();
111 Object value = null;
112 if (tokenType == JavaTokenType.PLUS) {
113 if (lOperandValue instanceof String || rOperandValue instanceof String) {
114 value = myInterner.intern(lOperandValue.toString() + rOperandValue.toString());
116 else {
117 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
118 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
120 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
121 if (lOperandValue instanceof Double || rOperandValue instanceof Double) {
122 value = new Double(((Number)lOperandValue).doubleValue() + ((Number)rOperandValue).doubleValue());
123 checkRealNumberOverflow(value, lOperandValue, rOperandValue,expression);
125 else if (lOperandValue instanceof Float || rOperandValue instanceof Float) {
126 value = new Float(((Number)lOperandValue).floatValue() + ((Number)rOperandValue).floatValue());
127 checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression);
129 else if (lOperandValue instanceof Long || rOperandValue instanceof Long) {
130 final long l = ((Number)lOperandValue).longValue();
131 final long r = ((Number)rOperandValue).longValue();
132 value = Long.valueOf(l + r);
133 checkAdditionOverflow(((Long)value).longValue() >= 0, l >= 0, r >= 0, expression);
135 else {
136 final int l = ((Number)lOperandValue).intValue();
137 final int r = ((Number)rOperandValue).intValue();
138 value = Integer.valueOf(l + r);
139 checkAdditionOverflow(((Integer)value).intValue() >= 0, l >= 0, r >= 0, expression);
144 else if (tokenType == JavaTokenType.MINUS) {
145 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
146 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
147 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
148 if (lOperandValue instanceof Double || rOperandValue instanceof Double) {
149 value = new Double(((Number)lOperandValue).doubleValue() - ((Number)rOperandValue).doubleValue());
150 checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression);
152 else if (lOperandValue instanceof Float || rOperandValue instanceof Float) {
153 value = new Float(((Number)lOperandValue).floatValue() - ((Number)rOperandValue).floatValue());
154 checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression);
156 else if (lOperandValue instanceof Long || rOperandValue instanceof Long) {
157 final long l = ((Number)lOperandValue).longValue();
158 final long r = ((Number)rOperandValue).longValue();
159 value = Long.valueOf(l - r);
160 checkAdditionOverflow(((Long)value).longValue() >= 0, l >= 0, r < 0, expression);
162 else {
163 final int l = ((Number)lOperandValue).intValue();
164 final int r = ((Number)rOperandValue).intValue();
165 value = Integer.valueOf(l - r);
166 checkAdditionOverflow(((Integer)value).intValue() >= 0, l >= 0, r < 0, expression);
170 else if (tokenType == JavaTokenType.ANDAND) {
171 if (lOperandValue instanceof Boolean && !((Boolean)lOperandValue).booleanValue()) {
172 myResult = Boolean.FALSE;
173 return;
175 if (rOperandValue instanceof Boolean && !((Boolean)rOperandValue).booleanValue()) {
176 myResult = Boolean.FALSE;
177 return;
179 if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) {
180 value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() && ((Boolean)rOperandValue).booleanValue());
183 else if (tokenType == JavaTokenType.OROR) {
184 if (lOperandValue instanceof Boolean && ((Boolean)lOperandValue).booleanValue()) {
185 myResult = Boolean.TRUE;
186 return;
188 if (rOperandValue instanceof Boolean && ((Boolean)rOperandValue).booleanValue()) {
189 myResult = Boolean.TRUE;
190 return;
192 if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) {
193 value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() || ((Boolean)rOperandValue).booleanValue());
196 else if (tokenType == JavaTokenType.LT) {
197 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
198 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
199 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
200 value = Boolean.valueOf(((Number)lOperandValue).doubleValue() < ((Number)rOperandValue).doubleValue());
203 else if (tokenType == JavaTokenType.LE) {
204 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
205 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
206 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
207 value = Boolean.valueOf(((Number)lOperandValue).doubleValue() <= ((Number)rOperandValue).doubleValue());
210 else if (tokenType == JavaTokenType.GT) {
211 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
212 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
213 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
214 value = Boolean.valueOf(((Number)lOperandValue).doubleValue() > ((Number)rOperandValue).doubleValue());
217 else if (tokenType == JavaTokenType.GE) {
218 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
219 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
220 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
221 value = Boolean.valueOf(((Number)lOperandValue).doubleValue() >= ((Number)rOperandValue).doubleValue());
224 else if (tokenType == JavaTokenType.EQEQ) {
225 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
226 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
227 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
228 value = Boolean.valueOf(((Number)lOperandValue).doubleValue() == ((Number)rOperandValue).doubleValue());
230 else if (lOperandValue instanceof String && rOperandValue instanceof String) {
231 value = Boolean.valueOf(lOperandValue == rOperandValue);
233 else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) {
234 value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() == ((Boolean)rOperandValue).booleanValue());
237 else if (tokenType == JavaTokenType.NE) {
238 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
239 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
240 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
241 value = Boolean.valueOf(((Number)lOperandValue).doubleValue() != ((Number)rOperandValue).doubleValue());
243 else if (lOperandValue instanceof String && rOperandValue instanceof String) {
244 value = Boolean.valueOf(lOperandValue != rOperandValue);
246 else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) {
247 value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() != ((Boolean)rOperandValue).booleanValue());
250 else if (tokenType == JavaTokenType.ASTERISK) {
251 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
252 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
253 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
254 if (lOperandValue instanceof Double || rOperandValue instanceof Double) {
255 value = new Double(((Number)lOperandValue).doubleValue() * ((Number)rOperandValue).doubleValue());
256 checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression);
258 else if (lOperandValue instanceof Float || rOperandValue instanceof Float) {
259 value = new Float(((Number)lOperandValue).floatValue() * ((Number)rOperandValue).floatValue());
260 checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression);
262 else if (lOperandValue instanceof Long || rOperandValue instanceof Long) {
263 final long l = ((Number)lOperandValue).longValue();
264 final long r = ((Number)rOperandValue).longValue();
265 value = Long.valueOf(l * r);
266 checkMultiplicationOverflow(((Long)value).longValue(), l, r, expression);
268 else {
269 final int l = ((Number)lOperandValue).intValue();
270 final int r = ((Number)rOperandValue).intValue();
271 value = Integer.valueOf(l * r);
272 checkMultiplicationOverflow(((Integer)value).intValue(), l, r, expression);
276 else if (tokenType == JavaTokenType.DIV) {
277 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
278 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
279 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
280 if (lOperandValue instanceof Double || rOperandValue instanceof Double) {
281 value = new Double(((Number)lOperandValue).doubleValue() / ((Number)rOperandValue).doubleValue());
282 checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression);
284 else if (lOperandValue instanceof Float || rOperandValue instanceof Float) {
285 value = new Float(((Number)lOperandValue).floatValue() / ((Number)rOperandValue).floatValue());
286 checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression);
288 else if (lOperandValue instanceof Long || rOperandValue instanceof Long) {
289 final long r = ((Number)rOperandValue).longValue();
290 final long l = ((Number)lOperandValue).longValue();
291 checkDivisionOverflow(l, r, Long.MIN_VALUE, expression);
292 value = r == 0 ? null : Long.valueOf(l / r);
294 else {
295 final int r = ((Number)rOperandValue).intValue();
296 final int l = ((Number)lOperandValue).intValue();
297 checkDivisionOverflow(l, r, Integer.MIN_VALUE, expression);
298 value = r == 0 ? null : Integer.valueOf(l / r);
302 else if (tokenType == JavaTokenType.PERC) {
303 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
304 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
305 if (lOperandValue instanceof Number && rOperandValue instanceof Number) {
306 double rVal = ((Number)rOperandValue).doubleValue();
307 if (myThrowExceptionOnOverflow && rVal == 0) throw new ConstantEvaluationOverflowException(expression);
308 if (lOperandValue instanceof Double || rOperandValue instanceof Double) {
309 value = new Double(((Number)lOperandValue).doubleValue() % ((Number)rOperandValue).doubleValue());
310 checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression);
312 else if (lOperandValue instanceof Float || rOperandValue instanceof Float) {
313 value = new Float(((Number)lOperandValue).floatValue() % ((Number)rOperandValue).floatValue());
314 checkRealNumberOverflow(value, lOperandValue, rOperandValue, expression);
316 else if (lOperandValue instanceof Long || rOperandValue instanceof Long) {
317 final long l = ((Number)lOperandValue).longValue();
318 final long r = ((Number)rOperandValue).longValue();
319 checkDivisionOverflow(l, r, Long.MIN_VALUE, expression);
320 value = r == 0 ? null : Long.valueOf(l % r);
322 else {
323 final int l = ((Number)lOperandValue).intValue();
324 final int r = ((Number)rOperandValue).intValue();
325 checkDivisionOverflow(l, r, Integer.MIN_VALUE, expression);
326 value = r == 0 ? null : Integer.valueOf(l % r);
330 else if (tokenType == JavaTokenType.LTLT) {
331 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
332 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
333 if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) {
334 if (lOperandValue instanceof Long) {
335 value = Long.valueOf(((Number)lOperandValue).longValue() << ((Number)rOperandValue).longValue());
337 else {
338 value = Integer.valueOf(((Number)lOperandValue).intValue() << ((Number)rOperandValue).intValue());
342 else if (tokenType == JavaTokenType.GTGT) {
343 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
344 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
345 if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) {
346 if (lOperandValue instanceof Long) {
347 value = Long.valueOf(((Number)lOperandValue).longValue() >> ((Number)rOperandValue).longValue());
349 else {
350 value = Integer.valueOf(((Number)lOperandValue).intValue() >> ((Number)rOperandValue).intValue());
354 else if (tokenType == JavaTokenType.GTGTGT) {
355 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
356 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
357 if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) {
358 if (lOperandValue instanceof Long) {
359 value = Long.valueOf(((Number)lOperandValue).longValue() >>> ((Number)rOperandValue).longValue());
361 else {
362 value = Integer.valueOf(((Number)lOperandValue).intValue() >>> ((Number)rOperandValue).intValue());
366 else if (tokenType == JavaTokenType.AND) {
367 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
368 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
369 if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) {
370 if (lOperandValue instanceof Long || rOperandValue instanceof Long) {
371 value = Long.valueOf(((Number)lOperandValue).longValue() & ((Number)rOperandValue).longValue());
373 else {
374 value = Integer.valueOf(((Number)lOperandValue).intValue() & ((Number)rOperandValue).intValue());
377 else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) {
378 value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() && ((Boolean)rOperandValue).booleanValue());
381 else if (tokenType == JavaTokenType.OR) {
382 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
383 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
384 if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) {
385 if (lOperandValue instanceof Long || rOperandValue instanceof Long) {
386 value = Long.valueOf(((Number)lOperandValue).longValue() | ((Number)rOperandValue).longValue());
388 else {
389 value = Integer.valueOf(((Number)lOperandValue).intValue() | ((Number)rOperandValue).intValue());
392 else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) {
393 value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() || ((Boolean)rOperandValue).booleanValue());
396 else if (tokenType == JavaTokenType.XOR) {
397 if (lOperandValue instanceof Character) lOperandValue = Integer.valueOf(((Character)lOperandValue).charValue());
398 if (rOperandValue instanceof Character) rOperandValue = Integer.valueOf(((Character)rOperandValue).charValue());
399 if (isIntegral(lOperandValue) && isIntegral(rOperandValue)) {
400 if (lOperandValue instanceof Long || rOperandValue instanceof Long) {
401 value = Long.valueOf(((Number)lOperandValue).longValue() ^ ((Number)rOperandValue).longValue());
403 else {
404 value = Integer.valueOf(((Number)lOperandValue).intValue() ^ ((Number)rOperandValue).intValue());
407 else if (lOperandValue instanceof Boolean && rOperandValue instanceof Boolean) {
408 value = Boolean.valueOf(((Boolean)lOperandValue).booleanValue() ^ ((Boolean)rOperandValue).booleanValue());
412 myResult = value;
415 @Override public void visitPrefixExpression(PsiPrefixExpression expression) {
416 PsiExpression operand = expression.getOperand();
417 Object operandValue = getStoredValue(operand);
418 if (operandValue == null) {
419 myResult = null;
420 return;
422 IElementType tokenType = expression.getOperationSign().getTokenType();
423 Object value = null;
424 if (tokenType == JavaTokenType.MINUS) {
425 if (operandValue instanceof Character) operandValue = Integer.valueOf(((Character)operandValue).charValue());
426 if (operandValue instanceof Number) {
427 if (operandValue instanceof Double) {
428 value = new Double(-((Number)operandValue).doubleValue());
429 checkRealNumberOverflow(value, null, null, expression);
431 else if (operandValue instanceof Float) {
432 value = new Float(-((Number)operandValue).floatValue());
433 checkRealNumberOverflow(value, null, null, expression);
435 else if (operandValue instanceof Long) {
436 value = Long.valueOf(-((Number)operandValue).longValue());
437 if (myThrowExceptionOnOverflow
438 && !(operand instanceof PsiLiteralExpression)
439 && ((Number)operandValue).longValue() == Long.MIN_VALUE) {
440 throw new ConstantEvaluationOverflowException(expression);
443 else {
444 value = Integer.valueOf(-((Number)operandValue).intValue());
445 if (myThrowExceptionOnOverflow
446 && !(operand instanceof PsiLiteralExpression)
447 && ((Number)operandValue).intValue() == Integer.MIN_VALUE) {
448 throw new ConstantEvaluationOverflowException(expression);
453 else if (tokenType == JavaTokenType.PLUS) {
454 if (operandValue instanceof Character) operandValue = Integer.valueOf(((Character)operandValue).charValue());
455 if (operandValue instanceof Number) {
456 value = operandValue;
459 else if (tokenType == JavaTokenType.TILDE) {
460 if (operandValue instanceof Character) operandValue = Integer.valueOf(((Character)operandValue).charValue());
461 if (isIntegral(operandValue)) {
462 value = operandValue instanceof Long
463 ? Long.valueOf(~((Number)operandValue).longValue())
464 : Integer.valueOf(~((Number)operandValue).intValue());
467 else if (tokenType == JavaTokenType.EXCL) {
468 if (operandValue instanceof Boolean) {
469 value = Boolean.valueOf(!((Boolean)operandValue).booleanValue());
473 myResult = value;
476 @Override public void visitParenthesizedExpression(PsiParenthesizedExpression expression) {
477 myResult = getStoredValue(expression.getExpression());
480 @Override
481 public void visitMethodCallExpression(final PsiMethodCallExpression expression) {
482 myResult = myAuxEvaluator != null? myAuxEvaluator.computeExpression(expression, this) : null;
485 @Override public void visitReferenceExpression(PsiReferenceExpression expression) {
486 PsiExpression qualifierExpression = expression.getQualifierExpression();
487 while (qualifierExpression != null) {
488 if (!(qualifierExpression instanceof PsiReferenceExpression)) {
489 myResult = null;
490 return;
493 PsiReferenceExpression qualifier = (PsiReferenceExpression) qualifierExpression;
494 final PsiElement resolved = qualifier.resolve();
495 if (resolved instanceof PsiPackage) break;
496 if (!(resolved instanceof PsiClass)) {
497 myResult = null;
498 return;
500 qualifierExpression = ((PsiReferenceExpression) qualifierExpression).getQualifierExpression();
502 PsiElement resolvedExpression = expression.resolve();
503 if (resolvedExpression instanceof PsiVariable) {
504 PsiVariable variable = (PsiVariable) resolvedExpression;
505 // avoid cycles
506 if (myVisitedVars != null && myVisitedVars.contains(variable)) {
507 myResult = null;
508 return;
511 Set<PsiVariable> oldVisitedVars = myVisitedVars;
512 if (myVisitedVars == null) { myVisitedVars = new THashSet<PsiVariable>(); }
514 myVisitedVars.add(variable);
515 try {
516 myResult = variable instanceof PsiVariableEx? ((PsiVariableEx) variable).computeConstantValue(myVisitedVars) : null;
517 if (myResult == null && myAuxEvaluator != null) myResult = myAuxEvaluator.computeExpression(expression, this);
518 return;
520 finally {
521 myVisitedVars.remove(variable);
522 myVisitedVars = oldVisitedVars;
526 myResult = null;
529 private static boolean isIntegral(Object o) {
530 return o instanceof Long || o instanceof Integer || o instanceof Short || o instanceof Byte || o instanceof Character;
533 private void checkDivisionOverflow(long l, final long r, long minValue, PsiBinaryExpression expression) {
534 if (!myThrowExceptionOnOverflow) return;
535 if (r == 0) throw new ConstantEvaluationOverflowException(expression);
536 if (r == -1 && l == minValue) throw new ConstantEvaluationOverflowException(expression);
539 private void checkMultiplicationOverflow(long result, long l, long r, PsiExpression expression) {
540 if (!myThrowExceptionOnOverflow) return;
541 if (r == 0 || l == 0) return;
542 if (result / r != l || ((l < 0) ^ (r < 0) != (result < 0))) throw new ConstantEvaluationOverflowException(expression);
545 private void checkAdditionOverflow(boolean resultPositive,
546 boolean lPositive,
547 boolean rPositive, PsiBinaryExpression expression) {
548 if (!myThrowExceptionOnOverflow) return;
549 boolean overflow = lPositive == rPositive && lPositive != resultPositive;
550 if (overflow) throw new ConstantEvaluationOverflowException(expression);
553 private void checkRealNumberOverflow(Object result,
554 Object lOperandValue,
555 Object rOperandValue, PsiExpression expression) {
556 if (!myThrowExceptionOnOverflow) return;
557 if (lOperandValue instanceof Float && ((Float) lOperandValue).isInfinite()) return;
558 if (lOperandValue instanceof Double && ((Double) lOperandValue).isInfinite()) return;
559 if (rOperandValue instanceof Float && ((Float) rOperandValue).isInfinite()) return;
560 if (rOperandValue instanceof Double && ((Double) rOperandValue).isInfinite()) return;
562 if (result instanceof Float && ((Float) result).isInfinite()) throw new ConstantEvaluationOverflowException(expression);
563 if (result instanceof Double && ((Double) result).isInfinite()) throw new ConstantEvaluationOverflowException(expression);
566 public Object computeExpression(final PsiExpression expression, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) {
567 return ConstantExpressionEvaluator.computeConstantExpression(expression, myVisitedVars, myThrowExceptionOnOverflow, auxEvaluator);
570 public ConcurrentMap<PsiElement, Object> getCacheMap(final boolean overflow) {
571 throw new AssertionError("should not be called");