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
;
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
) {
33 store(element
, myResult
);
34 //for (PsiElement child : element.getChildren()) {
35 // store(child, null); //erase garbage
39 private static final Key
<Object
> VALUE
= Key
.create("VALUE");
40 private static Object
getStoredValue(PsiElement element
) {
41 if (element
== null) {
45 return element
.getUserData(VALUE
);
48 element
.putUserData(VALUE
, null);
51 static void store(PsiElement element
, Object value
) {
52 element
.putUserData(VALUE
, value
);
56 public void visitLiteralExpression(PsiLiteralExpression expression
) {
57 final Object value
= expression
.getValue();
58 myResult
= value
instanceof String ? myInterner
.intern((String
)value
) : value
;
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) {
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) {
87 if (condition
instanceof Boolean
) {
88 value
= ((Boolean
)condition
).booleanValue() ? then
: els
;
95 public void visitBinaryExpression(PsiBinaryExpression expression
) {
96 Object lOperandValue
= getStoredValue(expression
.getLOperand());
97 if (lOperandValue
== null) {
102 Object rOperandValue
= getStoredValue(expression
.getROperand());
103 if (rOperandValue
== null) {
108 PsiJavaToken operationSign
= expression
.getOperationSign();
109 final IElementType tokenType
= operationSign
.getTokenType();
112 if (tokenType
== JavaTokenType
.PLUS
) {
113 if (lOperandValue
instanceof String
|| rOperandValue
instanceof String
) {
114 value
= myInterner
.intern(lOperandValue
.toString() + rOperandValue
.toString());
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
);
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
);
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
;
175 if (rOperandValue
instanceof Boolean
&& !((Boolean
)rOperandValue
).booleanValue()) {
176 myResult
= Boolean
.FALSE
;
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
;
188 if (rOperandValue
instanceof Boolean
&& ((Boolean
)rOperandValue
).booleanValue()) {
189 myResult
= Boolean
.TRUE
;
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
);
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
);
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
);
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());
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());
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());
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());
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());
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());
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());
415 @Override public void visitPrefixExpression(PsiPrefixExpression expression
) {
416 PsiExpression operand
= expression
.getOperand();
417 Object operandValue
= getStoredValue(operand
);
418 if (operandValue
== null) {
422 IElementType tokenType
= expression
.getOperationSign().getTokenType();
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
);
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());
476 @Override public void visitParenthesizedExpression(PsiParenthesizedExpression expression
) {
477 myResult
= getStoredValue(expression
.getExpression());
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
)) {
493 PsiReferenceExpression qualifier
= (PsiReferenceExpression
) qualifierExpression
;
494 final PsiElement resolved
= qualifier
.resolve();
495 if (resolved
instanceof PsiPackage
) break;
496 if (!(resolved
instanceof PsiClass
)) {
500 qualifierExpression
= ((PsiReferenceExpression
) qualifierExpression
).getQualifierExpression();
502 PsiElement resolvedExpression
= expression
.resolve();
503 if (resolvedExpression
instanceof PsiVariable
) {
504 PsiVariable variable
= (PsiVariable
) resolvedExpression
;
506 if (myVisitedVars
!= null && myVisitedVars
.contains(variable
)) {
511 Set
<PsiVariable
> oldVisitedVars
= myVisitedVars
;
512 if (myVisitedVars
== null) { myVisitedVars
= new THashSet
<PsiVariable
>(); }
514 myVisitedVars
.add(variable
);
516 myResult
= variable
instanceof PsiVariableEx?
((PsiVariableEx
) variable
).computeConstantValue(myVisitedVars
) : null;
517 if (myResult
== null && myAuxEvaluator
!= null) myResult
= myAuxEvaluator
.computeExpression(expression
, this);
521 myVisitedVars
.remove(variable
);
522 myVisitedVars
= oldVisitedVars
;
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
,
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");