2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Class EvaluatorBuilderImpl
21 package com
.intellij
.debugger
.engine
.evaluation
.expression
;
23 import com
.intellij
.codeInsight
.daemon
.JavaErrorMessages
;
24 import com
.intellij
.codeInsight
.daemon
.impl
.analysis
.HighlightUtil
;
25 import com
.intellij
.debugger
.DebuggerBundle
;
26 import com
.intellij
.debugger
.SourcePosition
;
27 import com
.intellij
.debugger
.engine
.ContextUtil
;
28 import com
.intellij
.debugger
.engine
.DebuggerUtils
;
29 import com
.intellij
.debugger
.engine
.JVMName
;
30 import com
.intellij
.debugger
.engine
.JVMNameUtil
;
31 import com
.intellij
.debugger
.engine
.evaluation
.*;
32 import com
.intellij
.openapi
.diagnostic
.Logger
;
33 import com
.intellij
.openapi
.project
.Project
;
34 import com
.intellij
.psi
.*;
35 import com
.intellij
.psi
.impl
.JavaConstantExpressionEvaluator
;
36 import com
.intellij
.psi
.search
.GlobalSearchScope
;
37 import com
.intellij
.psi
.tree
.IElementType
;
38 import com
.intellij
.psi
.util
.PsiTreeUtil
;
39 import com
.intellij
.psi
.util
.PsiTypesUtil
;
40 import com
.intellij
.psi
.util
.TypeConversionUtil
;
41 import com
.intellij
.util
.IncorrectOperationException
;
42 import org
.jetbrains
.annotations
.Nullable
;
44 import java
.util
.ArrayList
;
45 import java
.util
.HashSet
;
46 import java
.util
.List
;
49 public class EvaluatorBuilderImpl
implements EvaluatorBuilder
{
50 private static final EvaluatorBuilderImpl ourInstance
= new EvaluatorBuilderImpl();
52 private EvaluatorBuilderImpl() {
55 public static EvaluatorBuilder
getInstance() {
59 public ExpressionEvaluator
build(final TextWithImports text
, final PsiElement contextElement
, final SourcePosition position
) throws EvaluateException
{
60 if (contextElement
== null) {
61 throw EvaluateExceptionUtil
.CANNOT_FIND_SOURCE_CLASS
;
64 final Project project
= contextElement
.getProject();
66 PsiCodeFragment codeFragment
= DefaultCodeFragmentFactory
.getInstance().createCodeFragment(text
, contextElement
, project
);
67 if(codeFragment
== null) {
68 throw EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", text
.getText()));
70 codeFragment
.forceResolveScope(GlobalSearchScope
.allScope(project
));
71 DebuggerUtils
.checkSyntax(codeFragment
);
73 return build(codeFragment
, position
);
76 public ExpressionEvaluator
build(final PsiElement codeFragment
, final SourcePosition position
) throws EvaluateException
{
77 return new Builder(position
).buildElement(codeFragment
);
80 private static class Builder
extends JavaElementVisitor
{
81 private static final Logger LOG
= Logger
.getInstance("#com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl");
82 private Evaluator myResult
= null;
83 private PsiClass myContextPsiClass
;
84 private CodeFragmentEvaluator myCurrentFragmentEvaluator
;
85 private final Set
<JavaCodeFragment
> myVisitedFragments
= new HashSet
<JavaCodeFragment
>();
87 private final SourcePosition myPosition
;
89 private Builder(@Nullable SourcePosition position
) {
90 myPosition
= position
;
94 public void visitCodeFragment(JavaCodeFragment codeFragment
) {
95 myVisitedFragments
.add(codeFragment
);
96 ArrayList
<Evaluator
> evaluators
= new ArrayList
<Evaluator
>();
98 CodeFragmentEvaluator oldFragmentEvaluator
= myCurrentFragmentEvaluator
;
99 myCurrentFragmentEvaluator
= new CodeFragmentEvaluator(oldFragmentEvaluator
);
101 for (PsiElement child
= codeFragment
.getFirstChild(); child
!= null; child
= child
.getNextSibling()) {
103 if(myResult
!= null) {
104 evaluators
.add(myResult
);
109 myCurrentFragmentEvaluator
.setStatements(evaluators
.toArray(new Evaluator
[evaluators
.size()]));
110 myResult
= myCurrentFragmentEvaluator
;
112 myCurrentFragmentEvaluator
= oldFragmentEvaluator
;
116 public void visitErrorElement(PsiErrorElement element
) {
117 throw new EvaluateRuntimeException(EvaluateExceptionUtil
118 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", element
.getText())));
122 public void visitAssignmentExpression(PsiAssignmentExpression expression
) {
123 final PsiExpression rExpression
= expression
.getRExpression();
124 if(rExpression
== null) {
125 throw new EvaluateRuntimeException(
126 EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", expression
.getText()))
130 rExpression
.accept(this);
131 Evaluator rEvaluator
= myResult
;
133 if(expression
.getOperationSign().getTokenType() != JavaTokenType
.EQ
) {
134 throw new EvaluateRuntimeException(
135 EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.operation.not.supported", expression
.getOperationSign().getText()))
139 final PsiExpression lExpression
= expression
.getLExpression();
141 final PsiType lType
= lExpression
.getType();
143 throw new EvaluateRuntimeException(
144 EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.unknown.expression.type", lExpression
.getText()))
148 if(!TypeConversionUtil
.areTypesAssignmentCompatible(lType
, rExpression
)) {
149 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.incompatible.types", expression
.getOperationSign().getText())));
151 lExpression
.accept(this);
152 Evaluator lEvaluator
= myResult
;
154 rEvaluator
= handleAssignmentBoxingAndPrimitiveTypeConversions(lType
, rExpression
.getType(), rEvaluator
);
156 myResult
= new AssignmentEvaluator(lEvaluator
, rEvaluator
);
159 // returns rEvaluator possibly wrapped with boxing/unboxing and casting evaluators
160 private static Evaluator
handleAssignmentBoxingAndPrimitiveTypeConversions(PsiType lType
, PsiType rType
, Evaluator rEvaluator
) {
161 final PsiType unboxedLType
= PsiPrimitiveType
.getUnboxedType(lType
);
163 if (unboxedLType
!= null) {
164 if (rType
instanceof PsiPrimitiveType
&& !PsiPrimitiveType
.NULL
.equals(rType
)) {
165 if (!rType
.equals(unboxedLType
)) {
166 rEvaluator
= new TypeCastEvaluator(rEvaluator
, unboxedLType
.getCanonicalText(), true);
168 rEvaluator
= new BoxingEvaluator(rEvaluator
);
172 // either primitive type or not unboxable type
173 if (lType
instanceof PsiPrimitiveType
) {
174 if (rType
instanceof PsiClassType
) {
175 rEvaluator
= new UnBoxingEvaluator(rEvaluator
);
177 final PsiPrimitiveType unboxedRType
= PsiPrimitiveType
.getUnboxedType(rType
);
178 final PsiType _rType
= unboxedRType
!= null? unboxedRType
: rType
;
179 if (_rType
instanceof PsiPrimitiveType
&& !PsiPrimitiveType
.NULL
.equals(_rType
)) {
180 if (!lType
.equals(_rType
)) {
181 rEvaluator
= new TypeCastEvaluator(rEvaluator
, lType
.getCanonicalText(), true);
190 public void visitStatement(PsiStatement statement
) {
191 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.statement.not.supported", statement
.getText())));
195 public void visitBlockStatement(PsiBlockStatement statement
) {
196 PsiStatement
[] statements
= statement
.getCodeBlock().getStatements();
197 Evaluator
[] evaluators
= new Evaluator
[statements
.length
];
198 for (int i
= 0; i
< statements
.length
; i
++) {
199 PsiStatement psiStatement
= statements
[i
];
200 psiStatement
.accept(this);
201 evaluators
[i
] = myResult
;
204 myResult
= new BlockStatementEvaluator(evaluators
);
208 public void visitWhileStatement(PsiWhileStatement statement
) {
209 PsiStatement body
= statement
.getBody();
210 if(body
== null) return;
212 Evaluator bodyEvaluator
= myResult
;
214 PsiExpression condition
= statement
.getCondition();
215 if(condition
== null) return;
216 condition
.accept(this);
218 if(statement
.getParent() instanceof PsiLabeledStatement
) {
219 label
= ((PsiLabeledStatement
)statement
.getParent()).getLabelIdentifier().getText();
221 myResult
= new WhileStatementEvaluator(myResult
, bodyEvaluator
, label
);
225 public void visitForStatement(PsiForStatement statement
) {
226 PsiStatement initializer
= statement
.getInitialization();
227 Evaluator initializerEvaluator
= null;
228 if(initializer
!= null){
229 initializer
.accept(this);
230 initializerEvaluator
= myResult
;
233 PsiExpression condition
= statement
.getCondition();
234 Evaluator conditionEvaluator
= null;
235 if(condition
!= null) {
236 condition
.accept(this);
237 conditionEvaluator
= myResult
;
240 PsiStatement update
= statement
.getUpdate();
241 Evaluator updateEvaluator
= null;
244 updateEvaluator
= myResult
;
247 PsiStatement body
= statement
.getBody();
248 if(body
== null) return;
250 Evaluator bodyEvaluator
= myResult
;
253 if(statement
.getParent() instanceof PsiLabeledStatement
) {
254 label
= ((PsiLabeledStatement
)statement
.getParent()).getLabelIdentifier().getText();
256 myResult
= new ForStatementEvaluator(initializerEvaluator
, conditionEvaluator
, updateEvaluator
, bodyEvaluator
, label
);
260 public void visitIfStatement(PsiIfStatement statement
) {
261 PsiStatement thenBranch
= statement
.getThenBranch();
262 if(thenBranch
== null) return;
263 thenBranch
.accept(this);
264 Evaluator thenEvaluator
= myResult
;
266 PsiStatement elseBranch
= statement
.getElseBranch();
267 Evaluator elseEvaluator
= null;
268 if(elseBranch
!= null){
269 elseBranch
.accept(this);
270 elseEvaluator
= myResult
;
273 PsiExpression condition
= statement
.getCondition();
274 if(condition
== null) return;
275 condition
.accept(this);
277 myResult
= new IfStatementEvaluator(myResult
, thenEvaluator
, elseEvaluator
);
281 public void visitBreakStatement(PsiBreakStatement statement
) {
282 PsiIdentifier labelIdentifier
= statement
.getLabelIdentifier();
283 myResult
= BreakContinueStatementEvaluator
.createBreakEvaluator(labelIdentifier
!= null ? labelIdentifier
.getText() : null);
287 public void visitContinueStatement(PsiContinueStatement statement
) {
288 PsiIdentifier labelIdentifier
= statement
.getLabelIdentifier();
289 myResult
= BreakContinueStatementEvaluator
.createContinueEvaluator(labelIdentifier
!= null ? labelIdentifier
.getText() : null);
293 public void visitExpressionStatement(PsiExpressionStatement statement
) {
294 statement
.getExpression().accept(this);
298 public void visitExpression(PsiExpression expression
) {
299 if (LOG
.isDebugEnabled()) {
300 LOG
.debug("visitExpression " + expression
);
305 public void visitBinaryExpression(PsiBinaryExpression expression
) {
306 if (LOG
.isDebugEnabled()) {
307 LOG
.debug("visitBinaryExpression " + expression
);
309 final PsiExpression lOperand
= expression
.getLOperand();
310 lOperand
.accept(this);
311 Evaluator lResult
= myResult
;
312 final PsiExpression rOperand
= expression
.getROperand();
313 if(rOperand
== null) {
314 throw new EvaluateRuntimeException(
315 EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", expression
.getText()))
318 rOperand
.accept(this);
319 Evaluator rResult
= myResult
;
320 IElementType opType
= expression
.getOperationSign().getTokenType();
321 PsiType expressionExpectedType
= expression
.getType();
322 if (expressionExpectedType
== null) {
323 throw new EvaluateRuntimeException(
324 EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.unknown.expression.type", expression
.getText()))
327 myResult
= createBinaryEvaluator(lResult
, lOperand
.getType(), rResult
, rOperand
.getType(), opType
, expressionExpectedType
);
331 // constructs binary evaluator handling unboxing and numeric promotion issues
332 private static BinaryExpressionEvaluator
createBinaryEvaluator(
333 Evaluator lResult
, final PsiType lType
, Evaluator rResult
, final PsiType rType
, final IElementType operation
, final PsiType expressionExpectedType
) {
334 // handle unboxing if neccesary
335 if (isUnboxingInBinaryExpressionApplicable(lType
, rType
, operation
)) {
336 if (rType
instanceof PsiClassType
) {
337 rResult
= new UnBoxingEvaluator(rResult
);
339 if (lType
instanceof PsiClassType
) {
340 lResult
= new UnBoxingEvaluator(lResult
);
343 if (isBinaryNumericPromotionApplicable(lType
, rType
, operation
)) {
344 PsiType _lType
= lType
;
345 final PsiPrimitiveType unboxedLType
= PsiPrimitiveType
.getUnboxedType(lType
);
346 if (unboxedLType
!= null) {
347 _lType
= unboxedLType
;
350 PsiType _rType
= rType
;
351 final PsiPrimitiveType unboxedRType
= PsiPrimitiveType
.getUnboxedType(rType
);
352 if (unboxedRType
!= null) {
353 _rType
= unboxedRType
;
356 // handle numeric promotion
357 if (PsiType
.DOUBLE
.equals(_lType
)) {
358 if (TypeConversionUtil
.areTypesConvertible(_rType
, PsiType
.DOUBLE
)) {
359 rResult
= new TypeCastEvaluator(rResult
, PsiType
.DOUBLE
.getCanonicalText(), true);
362 else if (PsiType
.DOUBLE
.equals(_rType
)) {
363 if (TypeConversionUtil
.areTypesConvertible(_lType
, PsiType
.DOUBLE
)) {
364 lResult
= new TypeCastEvaluator(lResult
, PsiType
.DOUBLE
.getCanonicalText(), true);
367 else if (PsiType
.FLOAT
.equals(_lType
)) {
368 if (TypeConversionUtil
.areTypesConvertible(_rType
, PsiType
.FLOAT
)) {
369 rResult
= new TypeCastEvaluator(rResult
, PsiType
.FLOAT
.getCanonicalText(), true);
372 else if (PsiType
.FLOAT
.equals(_rType
)) {
373 if (TypeConversionUtil
.areTypesConvertible(_lType
, PsiType
.FLOAT
)) {
374 lResult
= new TypeCastEvaluator(lResult
, PsiType
.FLOAT
.getCanonicalText(), true);
377 else if (PsiType
.LONG
.equals(_lType
)) {
378 if (TypeConversionUtil
.areTypesConvertible(_rType
, PsiType
.LONG
)) {
379 rResult
= new TypeCastEvaluator(rResult
, PsiType
.LONG
.getCanonicalText(), true);
382 else if (PsiType
.LONG
.equals(_rType
)) {
383 if (TypeConversionUtil
.areTypesConvertible(_lType
, PsiType
.LONG
)) {
384 lResult
= new TypeCastEvaluator(lResult
, PsiType
.LONG
.getCanonicalText(), true);
388 if (!PsiType
.INT
.equals(_lType
) && TypeConversionUtil
.areTypesConvertible(_lType
, PsiType
.INT
)) {
389 lResult
= new TypeCastEvaluator(lResult
, PsiType
.INT
.getCanonicalText(), true);
391 if (!PsiType
.INT
.equals(_rType
) && TypeConversionUtil
.areTypesConvertible(_rType
, PsiType
.INT
)) {
392 rResult
= new TypeCastEvaluator(rResult
, PsiType
.INT
.getCanonicalText(), true);
397 return new BinaryExpressionEvaluator(lResult
, rResult
, operation
, expressionExpectedType
.getCanonicalText());
400 private static boolean isBinaryNumericPromotionApplicable(PsiType lType
, PsiType rType
, IElementType opType
) {
401 if (lType
== null && rType
== null) {
404 if (opType
== JavaTokenType
.EQEQ
|| opType
== JavaTokenType
.NE
) {
405 if (PsiType
.NULL
.equals(lType
) || PsiType
.NULL
.equals(rType
)) {
408 if (lType
instanceof PsiClassType
&& rType
instanceof PsiClassType
) {
411 if (lType
instanceof PsiClassType
) {
412 return PsiPrimitiveType
.getUnboxedType(lType
) != null; // should be unboxable
414 if (rType
instanceof PsiClassType
) {
415 return PsiPrimitiveType
.getUnboxedType(rType
) != null; // should be unboxable
420 return opType
== JavaTokenType
.ASTERISK
||
421 opType
== JavaTokenType
.DIV
||
422 opType
== JavaTokenType
.PERC
||
423 opType
== JavaTokenType
.PLUS
||
424 opType
== JavaTokenType
.MINUS
||
425 opType
== JavaTokenType
.LT
||
426 opType
== JavaTokenType
.LE
||
427 opType
== JavaTokenType
.GT
||
428 opType
== JavaTokenType
.GE
||
429 opType
== JavaTokenType
.AND
||
430 opType
== JavaTokenType
.XOR
||
431 opType
== JavaTokenType
.OR
;
435 private static boolean isUnboxingInBinaryExpressionApplicable(PsiType lType
, PsiType rType
, IElementType opCode
) {
436 if (PsiType
.NULL
.equals(lType
) || PsiType
.NULL
.equals(rType
)) {
439 // handle '==' and '!=' separately
440 if (opCode
== JavaTokenType
.EQEQ
|| opCode
== JavaTokenType
.NE
) {
441 return (lType
instanceof PsiPrimitiveType
&& rType
instanceof PsiClassType
) ||
442 (lType
instanceof PsiClassType
&& rType
instanceof PsiPrimitiveType
);
444 // all other operations at least one should be of class type
445 return lType
instanceof PsiClassType
|| rType
instanceof PsiClassType
;
450 * @return promotion type to cast to or null if no casting needed
453 private static PsiType
calcUnaryNumericPromotionType(PsiPrimitiveType type
) {
454 if (PsiType
.BYTE
.equals(type
) || PsiType
.SHORT
.equals(type
) || PsiType
.CHAR
.equals(type
) || PsiType
.INT
.equals(type
)) {
461 public void visitDeclarationStatement(PsiDeclarationStatement statement
) {
462 List
<Evaluator
> evaluators
= new ArrayList
<Evaluator
>();
464 PsiElement
[] declaredElements
= statement
.getDeclaredElements();
465 for (PsiElement declaredElement
: declaredElements
) {
466 if (declaredElement
instanceof PsiLocalVariable
) {
467 if (myCurrentFragmentEvaluator
!= null) {
468 final PsiLocalVariable localVariable
= ((PsiLocalVariable
)declaredElement
);
470 final PsiType lType
= localVariable
.getType();
472 PsiElementFactory elementFactory
= JavaPsiFacade
.getInstance(localVariable
.getProject()).getElementFactory();
474 PsiExpression initialValue
= elementFactory
.createExpressionFromText(PsiTypesUtil
.getDefaultValueOfType(lType
), null);
475 Object value
= JavaConstantExpressionEvaluator
.computeConstantExpression(initialValue
, true);
476 myCurrentFragmentEvaluator
.setInitialValue(localVariable
.getName(), value
);
478 catch (IncorrectOperationException e
) {
481 catch (EvaluateException e
) {
482 throw new EvaluateRuntimeException(e
);
485 PsiExpression initializer
= localVariable
.getInitializer();
486 if (initializer
!= null) {
488 if (!TypeConversionUtil
.areTypesAssignmentCompatible(localVariable
.getType(), initializer
)) {
489 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
490 DebuggerBundle
.message("evaluation.error.incompatible.variable.initializer.type", localVariable
.getName())));
492 final PsiType rType
= initializer
.getType();
493 initializer
.accept(this);
494 Evaluator rEvaluator
= myResult
;
496 PsiExpression localVarReference
= elementFactory
.createExpressionFromText(localVariable
.getName(), initializer
);
498 localVarReference
.accept(this);
499 Evaluator lEvaluator
= myResult
;
500 rEvaluator
= handleAssignmentBoxingAndPrimitiveTypeConversions(localVarReference
.getType(), rType
, rEvaluator
);
502 Evaluator assignment
= new AssignmentEvaluator(lEvaluator
, rEvaluator
);
503 evaluators
.add(assignment
);
505 catch (IncorrectOperationException e
) {
511 throw new EvaluateRuntimeException(new EvaluateException(
512 DebuggerBundle
.message("evaluation.error.local.variable.declarations.not.supported"), null));
516 throw new EvaluateRuntimeException(new EvaluateException(
517 DebuggerBundle
.message("evaluation.error.unsupported.declaration", declaredElement
.getText()), null));
521 if(evaluators
.size() > 0) {
522 CodeFragmentEvaluator codeFragmentEvaluator
= new CodeFragmentEvaluator(myCurrentFragmentEvaluator
);
523 codeFragmentEvaluator
.setStatements(evaluators
.toArray(new Evaluator
[0]));
524 myResult
= codeFragmentEvaluator
;
531 public void visitConditionalExpression(PsiConditionalExpression expression
) {
532 if (LOG
.isDebugEnabled()) {
533 LOG
.debug("visitConditionalExpression " + expression
);
535 final PsiExpression thenExpression
= expression
.getThenExpression();
536 final PsiExpression elseExpression
= expression
.getElseExpression();
537 if (thenExpression
== null || elseExpression
== null){
538 throw new EvaluateRuntimeException(EvaluateExceptionUtil
539 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", expression
.getText())));
541 PsiExpression condition
= expression
.getCondition();
542 condition
.accept(this);
543 if (myResult
== null) {
544 throw new EvaluateRuntimeException(EvaluateExceptionUtil
545 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", condition
.getText())));
547 Evaluator conditionEvaluator
= myResult
;
548 thenExpression
.accept(this);
549 if (myResult
== null) {
550 throw new EvaluateRuntimeException(EvaluateExceptionUtil
551 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", thenExpression
.getText())));
553 Evaluator thenEvaluator
= myResult
;
554 elseExpression
.accept(this);
555 if (myResult
== null) {
556 throw new EvaluateRuntimeException(EvaluateExceptionUtil
557 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", elseExpression
.getText())));
559 Evaluator elseEvaluator
= myResult
;
560 myResult
= new ConditionalExpressionEvaluator(conditionEvaluator
, thenEvaluator
, elseEvaluator
);
564 public void visitReferenceExpression(PsiReferenceExpression expression
) {
565 if (LOG
.isDebugEnabled()) {
566 LOG
.debug("visitReferenceExpression " + expression
);
568 PsiExpression qualifier
= expression
.getQualifierExpression();
569 PsiElement element
= expression
.resolve();
571 if (element
instanceof PsiLocalVariable
|| element
instanceof PsiParameter
) {
573 final PsiFile containingFile
= element
.getContainingFile();
574 if(containingFile
instanceof PsiCodeFragment
&& myCurrentFragmentEvaluator
!= null && myVisitedFragments
.contains(((PsiCodeFragment
)containingFile
))) {
575 // psiVariable may live in PsiCodeFragment not only in debugger editors, for example Fabrique has such variables.
576 // So treat it as synthetic var only when this code fragment is located in DebuggerEditor,
577 // that's why we need to check that containing code fragment is the one we visited
578 myResult
= new SyntheticVariableEvaluator(myCurrentFragmentEvaluator
, ((PsiVariable
)element
).getName());
582 final PsiVariable psiVar
= (PsiVariable
)element
;
583 final String localName
= psiVar
.getName();
584 PsiClass variableClass
= getContainingClass(psiVar
);
585 if (getContextPsiClass() == null || getContextPsiClass().equals(variableClass
)) {
586 final LocalVariableEvaluator localVarEvaluator
= new LocalVariableEvaluator(localName
, ContextUtil
.isJspImplicit(element
));
587 if (psiVar
instanceof PsiParameter
) {
588 final PsiParameter param
= (PsiParameter
)psiVar
;
589 final PsiParameterList paramList
= PsiTreeUtil
.getParentOfType(param
, PsiParameterList
.class, true);
590 if (paramList
!= null) {
591 localVarEvaluator
.setParameterIndex(paramList
.getParameterIndex(param
));
594 myResult
= localVarEvaluator
;
597 // the expression references final var outside the context's class (in some of the outer classes)
598 int iterationCount
= 0;
599 PsiClass aClass
= getOuterClass(getContextPsiClass());
600 while (aClass
!= null && !aClass
.equals(variableClass
)) {
602 aClass
= getOuterClass(aClass
);
604 if (aClass
!= null) {
605 if(psiVar
.getInitializer() != null) {
606 Object value
= JavaPsiFacade
.getInstance(psiVar
.getProject()).getConstantEvaluationHelper().computeConstantExpression(psiVar
.getInitializer());
608 myResult
= new LiteralEvaluator(value
, psiVar
.getType().getCanonicalText());
612 Evaluator objectEvaluator
= new ThisEvaluator(iterationCount
);
613 //noinspection HardCodedStringLiteral
614 final PsiClass classAt
= myPosition
!= null? JVMNameUtil
.getClassAt(myPosition
) : null;
615 FieldEvaluator
.TargetClassFilter filter
= FieldEvaluator
.createClassFilter(classAt
!= null? classAt
: getContextPsiClass());
616 myResult
= new FieldEvaluator(objectEvaluator
, filter
, "val$" + localName
);
619 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
620 DebuggerBundle
.message("evaluation.error.local.variable.missing.from.class.closure", localName
))
623 else if (element
instanceof PsiField
) {
624 final PsiField psiField
= (PsiField
)element
;
625 final PsiClass fieldClass
= psiField
.getContainingClass();
626 if(fieldClass
== null) {
627 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
628 DebuggerBundle
.message("evaluation.error.cannot.resolve.field.class", psiField
.getName())));
630 Evaluator objectEvaluator
;
631 if (psiField
.hasModifierProperty(PsiModifier
.STATIC
)) {
632 objectEvaluator
= new TypeEvaluator(JVMNameUtil
.getContextClassJVMQualifiedName(SourcePosition
.createFromElement(psiField
)));
634 else if(qualifier
!= null) {
635 qualifier
.accept(this);
636 objectEvaluator
= myResult
;
638 else if (fieldClass
.equals(getContextPsiClass()) || getContextPsiClass().isInheritor(fieldClass
, true)) {
639 objectEvaluator
= new ThisEvaluator();
641 else { // myContextPsiClass != fieldClass && myContextPsiClass is not a subclass of fieldClass
642 int iterationCount
= 0;
643 PsiClass aClass
= getContextPsiClass();
644 while (aClass
!= null && !(aClass
.equals(fieldClass
) || aClass
.isInheritor(fieldClass
, true))) {
646 aClass
= getOuterClass(aClass
);
648 if (aClass
== null) {
649 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
650 DebuggerBundle
.message("evaluation.error.cannot.sources.for.field.class", psiField
.getName())));
652 objectEvaluator
= new ThisEvaluator(iterationCount
);
654 myResult
= new FieldEvaluator(objectEvaluator
, FieldEvaluator
.createClassFilter(fieldClass
), psiField
.getName());
657 //let's guess what this could be
658 PsiElement nameElement
= expression
.getReferenceNameElement(); // get "b" part
660 if (nameElement
instanceof PsiIdentifier
) {
661 name
= nameElement
.getText();
664 //noinspection HardCodedStringLiteral
665 final String elementDisplayString
= (nameElement
!= null ? nameElement
.getText() : "(null)");
666 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
667 DebuggerBundle
.message("evaluation.error.identifier.expected", elementDisplayString
)));
670 if(qualifier
!= null) {
671 final PsiElement qualifierTarget
= (qualifier
instanceof PsiReferenceExpression
) ?
((PsiReferenceExpression
)qualifier
).resolve() : null;
672 if (qualifierTarget
instanceof PsiClass
) {
673 // this is a call to a 'static' field
674 PsiClass psiClass
= (PsiClass
)qualifierTarget
;
675 final JVMName typeName
= JVMNameUtil
.getJVMQualifiedName(psiClass
);
676 myResult
= new FieldEvaluator(new TypeEvaluator(typeName
), FieldEvaluator
.createClassFilter(psiClass
), name
);
679 PsiType type
= qualifier
.getType();
681 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
682 DebuggerBundle
.message("evaluation.error.qualifier.type.unknown", qualifier
.getText()))
686 qualifier
.accept(this);
687 if (myResult
== null) {
688 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
689 DebuggerBundle
.message("evaluation.error.cannot.evaluate.qualifier", qualifier
.getText()))
693 myResult
= new FieldEvaluator(myResult
, FieldEvaluator
.createClassFilter(type
), name
);
697 myResult
= new LocalVariableEvaluator(name
, false);
703 public void visitSuperExpression(PsiSuperExpression expression
) {
704 if (LOG
.isDebugEnabled()) {
705 LOG
.debug("visitSuperExpression " + expression
);
707 final int iterationCount
= calcIterationCount(expression
.getQualifier());
708 myResult
= new SuperEvaluator(iterationCount
);
712 public void visitThisExpression(PsiThisExpression expression
) {
713 if (LOG
.isDebugEnabled()) {
714 LOG
.debug("visitThisExpression " + expression
);
716 final int iterationCount
= calcIterationCount(expression
.getQualifier());
717 myResult
= new ThisEvaluator(iterationCount
);
720 private int calcIterationCount(final PsiJavaCodeReferenceElement qualifier
) {
721 int iterationCount
= 0;
722 if (qualifier
!= null) {
723 PsiElement targetClass
= qualifier
.resolve();
724 if (targetClass
== null || getContextPsiClass() == null) {
725 throw new EvaluateRuntimeException(EvaluateExceptionUtil
726 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", qualifier
.getText())));
729 PsiClass aClass
= getContextPsiClass();
730 while (aClass
!= null && !aClass
.equals(targetClass
)) {
732 aClass
= getOuterClass(aClass
);
735 catch (Exception e
) {
736 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(e
));
739 return iterationCount
;
743 public void visitInstanceOfExpression(PsiInstanceOfExpression expression
) {
744 if (LOG
.isDebugEnabled()) {
745 LOG
.debug("visitInstanceOfExpression " + expression
);
747 PsiTypeElement checkType
= expression
.getCheckType();
748 if(checkType
== null) {
749 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", expression
.getText())));
751 PsiType type
= checkType
.getType();
752 expression
.getOperand().accept(this);
753 // ClassObjectEvaluator typeEvaluator = new ClassObjectEvaluator(type.getCanonicalText());
754 Evaluator operandEvaluator
= myResult
;
755 myResult
= new InstanceofEvaluator(operandEvaluator
, new TypeEvaluator(JVMNameUtil
.getJVMQualifiedName(type
)));
759 public void visitParenthesizedExpression(PsiParenthesizedExpression expression
) {
760 if (LOG
.isDebugEnabled()) {
761 LOG
.debug("visitParenthesizedExpression " + expression
);
763 PsiExpression expr
= expression
.getExpression();
770 public void visitPostfixExpression(PsiPostfixExpression expression
) {
771 if(expression
.getType() == null) {
772 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
773 DebuggerBundle
.message("evaluation.error.unknown.expression.type", expression
.getText()))
777 final PsiExpression operandExpression
= expression
.getOperand();
778 operandExpression
.accept(this);
780 final Evaluator operandEvaluator
= myResult
;
782 final IElementType operation
= expression
.getOperationSign().getTokenType();
783 final PsiType operandType
= operandExpression
.getType();
784 final @Nullable PsiType unboxedOperandType
= PsiPrimitiveType
.getUnboxedType(operandType
);
786 Evaluator incrementImpl
= createBinaryEvaluator(
787 operandEvaluator
, operandType
,
788 new LiteralEvaluator(Integer
.valueOf(1), "int"), PsiType
.INT
,
789 operation
== JavaTokenType
.PLUSPLUS ? JavaTokenType
.PLUS
: JavaTokenType
.MINUS
,
790 unboxedOperandType
!= null? unboxedOperandType
: operandType
792 if (unboxedOperandType
!= null) {
793 incrementImpl
= new BoxingEvaluator(incrementImpl
);
795 myResult
= new PostfixOperationEvaluator(operandEvaluator
, incrementImpl
);
799 public void visitPrefixExpression(final PsiPrefixExpression expression
) {
800 final PsiType expressionType
= expression
.getType();
801 if(expressionType
== null) {
802 throw new EvaluateRuntimeException(
803 EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.unknown.expression.type", expression
.getText()))
807 final PsiExpression operandExpression
= expression
.getOperand();
808 if (operandExpression
== null) {
809 throw new EvaluateRuntimeException(
810 EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.unknown.expression.operand", expression
.getText()))
814 operandExpression
.accept(this);
815 Evaluator operandEvaluator
= myResult
;
817 // handle unboxing issues
818 final PsiType operandType
= operandExpression
.getType();
820 final PsiType unboxedOperandType
= PsiPrimitiveType
.getUnboxedType(operandType
);
822 final IElementType operation
= expression
.getOperationSign().getTokenType();
824 if(operation
== JavaTokenType
.PLUSPLUS
|| operation
== JavaTokenType
.MINUSMINUS
) {
826 final BinaryExpressionEvaluator rightEval
= createBinaryEvaluator(
827 operandEvaluator
, operandType
,
828 new LiteralEvaluator(Integer
.valueOf(1), "int"), PsiType
.INT
,
829 operation
== JavaTokenType
.PLUSPLUS ? JavaTokenType
.PLUS
: JavaTokenType
.MINUS
,
830 unboxedOperandType
!= null? unboxedOperandType
: operandType
832 myResult
= new AssignmentEvaluator(operandEvaluator
, unboxedOperandType
!= null?
new BoxingEvaluator(rightEval
) : rightEval
);
834 catch (IncorrectOperationException e
) {
839 if (JavaTokenType
.PLUS
.equals(operation
) || JavaTokenType
.MINUS
.equals(operation
)|| JavaTokenType
.TILDE
.equals(operation
)) {
840 operandEvaluator
= handleUnaryNumericPromotion(operandType
, operandEvaluator
);
843 if (unboxedOperandType
!= null) {
844 operandEvaluator
= new UnBoxingEvaluator(operandEvaluator
);
847 myResult
= new UnaryExpressionEvaluator(operation
, expressionType
.getCanonicalText(), operandEvaluator
, expression
.getOperationSign().getText());
852 public void visitMethodCallExpression(PsiMethodCallExpression expression
) {
853 if (LOG
.isDebugEnabled()) {
854 LOG
.debug("visitMethodCallExpression " + expression
);
856 final PsiExpressionList argumentList
= expression
.getArgumentList();
857 final PsiExpression
[] argExpressions
= argumentList
.getExpressions();
858 List
<Evaluator
> argumentEvaluators
= new ArrayList
<Evaluator
>(argExpressions
.length
);
859 // evaluate arguments
860 for (PsiExpression psiExpression
: argExpressions
) {
861 psiExpression
.accept(this);
862 if (myResult
== null) {
863 // cannot build evaluator
864 throw new EvaluateRuntimeException(
865 EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", psiExpression
.getText()))
868 argumentEvaluators
.add(myResult
);
870 PsiReferenceExpression methodExpr
= expression
.getMethodExpression();
872 final JavaResolveResult resolveResult
= methodExpr
.advancedResolve(false);
873 final PsiMethod psiMethod
= (PsiMethod
)resolveResult
.getElement();
875 PsiExpression qualifier
= methodExpr
.getQualifierExpression();
876 Evaluator objectEvaluator
;
877 JVMName contextClass
= null;
879 if(psiMethod
!= null) {
880 PsiClass methodPsiClass
= psiMethod
.getContainingClass();
881 contextClass
= JVMNameUtil
.getJVMQualifiedName(methodPsiClass
);
882 if (psiMethod
.hasModifierProperty(PsiModifier
.STATIC
)) {
883 objectEvaluator
= new TypeEvaluator(contextClass
);
885 else if (qualifier
!= null ) {
886 qualifier
.accept(this);
887 objectEvaluator
= myResult
;
890 int iterationCount
= 0;
891 final PsiElement currentFileResolveScope
= resolveResult
.getCurrentFileResolveScope();
892 if (currentFileResolveScope
instanceof PsiClass
) {
893 PsiClass aClass
= getContextPsiClass();
894 while(aClass
!= null && !aClass
.equals(currentFileResolveScope
)) {
895 aClass
= getOuterClass(aClass
);
899 objectEvaluator
= new ThisEvaluator(iterationCount
);
904 if (qualifier
!= null) {
905 PsiType type
= qualifier
.getType();
908 contextClass
= JVMNameUtil
.getJVMQualifiedName(type
);
911 if (qualifier
instanceof PsiReferenceExpression
&& ((PsiReferenceExpression
)qualifier
).resolve() instanceof PsiClass
) {
912 // this is a call to a 'static' method
913 if (contextClass
== null && type
== null) {
914 throw new EvaluateRuntimeException(
915 EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.qualifier.type.unknown", qualifier
.getText()))
918 assert contextClass
!= null;
919 objectEvaluator
= new TypeEvaluator(contextClass
);
922 qualifier
.accept(this);
923 objectEvaluator
= myResult
;
927 objectEvaluator
= new ThisEvaluator();
928 contextClass
= JVMNameUtil
.getContextClassJVMQualifiedName(myPosition
);
929 if(contextClass
== null && myContextPsiClass
!= null) {
930 contextClass
= JVMNameUtil
.getJVMQualifiedName(myContextPsiClass
);
933 // throw new EvaluateRuntimeException(EvaluateExceptionUtil.createEvaluateException(
934 // DebuggerBundle.message("evaluation.error.method.not.found", methodExpr.getReferenceName()))
940 if (objectEvaluator
== null) {
941 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", expression
.getText())));
944 if (psiMethod
!= null && !psiMethod
.isConstructor()) {
945 if (psiMethod
.getReturnType() == null) {
946 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle
.message("evaluation.error.unknown.method.return.type", psiMethod
.getText())));
950 if (psiMethod
!= null) {
952 for (int i
= 0, parametersLength
= psiMethod
.getParameterList().getParameters().length
; i
< parametersLength
; i
++) {
953 PsiParameter parameter
= psiMethod
.getParameterList().getParameters()[i
];
954 final PsiType paramType
= parameter
.getType();
955 final PsiType realArgType
= argExpressions
[i
].getType();
956 if (TypeConversionUtil
.boxingConversionApplicable(paramType
, realArgType
)) {
957 final Evaluator argEval
= argumentEvaluators
.get(i
);
958 argumentEvaluators
.set(i
, (paramType
instanceof PsiPrimitiveType
)?
new UnBoxingEvaluator(argEval
) : new BoxingEvaluator(argEval
));
963 myResult
= new MethodEvaluator(objectEvaluator
, contextClass
, methodExpr
.getReferenceName(), psiMethod
!= null ? JVMNameUtil
.getJVMSignature(psiMethod
) : null, argumentEvaluators
);
967 public void visitLiteralExpression(PsiLiteralExpression expression
) {
968 Object value
= expression
.getValue();
969 if(expression
.getParsingError() != null) {
970 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(expression
.getParsingError()));
972 myResult
= new LiteralEvaluator(value
, expression
.getType().getCanonicalText());
976 public void visitArrayAccessExpression(PsiArrayAccessExpression expression
) {
977 final PsiExpression indexExpression
= expression
.getIndexExpression();
978 if(indexExpression
== null) {
979 throw new EvaluateRuntimeException(EvaluateExceptionUtil
980 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", expression
.getText())));
982 indexExpression
.accept(this);
983 final Evaluator indexEvaluator
= handleUnaryNumericPromotion(indexExpression
.getType(), myResult
);
985 expression
.getArrayExpression().accept(this);
986 Evaluator arrayEvaluator
= myResult
;
987 myResult
= new ArrayAccessEvaluator(arrayEvaluator
, indexEvaluator
);
992 * Handles unboxing and numeric promotion issues for
993 * - array diumention expressions
994 * - array index expression
995 * - unary +, -, and ~ operations
996 * @param operandExpressionType
997 * @param operandEvaluator @return operandEvaluator possibly 'wrapped' with neccesary unboxing and type-casting evaluators to make returning value
998 * sutable for mentioned contexts
1000 private static Evaluator
handleUnaryNumericPromotion(final PsiType operandExpressionType
, Evaluator operandEvaluator
) {
1001 final PsiPrimitiveType unboxedType
= PsiPrimitiveType
.getUnboxedType(operandExpressionType
);
1002 if (unboxedType
!= null && !PsiType
.BOOLEAN
.equals(unboxedType
)) {
1003 operandEvaluator
= new UnBoxingEvaluator(operandEvaluator
);
1006 // handle numeric promotion
1007 final PsiType _unboxedIndexType
= unboxedType
!= null? unboxedType
: operandExpressionType
;
1008 if (_unboxedIndexType
instanceof PsiPrimitiveType
) {
1009 final PsiType promotionType
= calcUnaryNumericPromotionType((PsiPrimitiveType
)_unboxedIndexType
);
1010 if (promotionType
!= null) {
1011 operandEvaluator
= new TypeCastEvaluator(operandEvaluator
, promotionType
.getCanonicalText(), true);
1014 return operandEvaluator
;
1017 @SuppressWarnings({"ConstantConditions"})
1019 public void visitTypeCastExpression(PsiTypeCastExpression expression
) {
1020 final PsiExpression operandExpr
= expression
.getOperand();
1021 operandExpr
.accept(this);
1022 Evaluator operandEvaluator
= myResult
;
1023 final PsiType castType
= expression
.getCastType().getType();
1024 final PsiType operandType
= operandExpr
.getType();
1026 if (!TypeConversionUtil
.areTypesConvertible(operandType
, castType
)) {
1027 throw new EvaluateRuntimeException(
1028 new EvaluateException(JavaErrorMessages
.message("inconvertible.type.cast", HighlightUtil
.formatType(operandType
), HighlightUtil
.formatType(castType
)))
1032 final boolean shouldPerformBoxingConversion
= TypeConversionUtil
.boxingConversionApplicable(castType
, operandType
);
1033 final boolean castingToPrimitive
= castType
instanceof PsiPrimitiveType
;
1034 if (shouldPerformBoxingConversion
&& castingToPrimitive
) {
1035 operandEvaluator
= new UnBoxingEvaluator(operandEvaluator
);
1038 final boolean performCastToWrapperClass
= shouldPerformBoxingConversion
&& !castingToPrimitive
;
1040 String castTypeName
= castType
.getCanonicalText();
1041 if (performCastToWrapperClass
) {
1042 final PsiPrimitiveType unboxedType
= PsiPrimitiveType
.getUnboxedType(castType
);
1043 if (unboxedType
!= null) {
1044 castTypeName
= unboxedType
.getCanonicalText();
1048 myResult
= new TypeCastEvaluator(operandEvaluator
, castTypeName
, castingToPrimitive
);
1050 if (performCastToWrapperClass
) {
1051 myResult
= new BoxingEvaluator(myResult
);
1056 public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression
) {
1057 PsiType type
= expression
.getOperand().getType();
1059 if (type
instanceof PsiPrimitiveType
) {
1060 final JVMName typeName
= JVMNameUtil
.getJVMRawText(((PsiPrimitiveType
)type
).getBoxedTypeName());
1061 myResult
= new FieldEvaluator(new TypeEvaluator(typeName
), FieldEvaluator
.TargetClassFilter
.ALL
, "TYPE");
1064 myResult
= new ClassObjectEvaluator(new TypeEvaluator(JVMNameUtil
.getJVMQualifiedName(type
)));
1069 public void visitNewExpression(PsiNewExpression expression
) {
1070 PsiType expressionPsiType
= expression
.getType();
1071 if (expressionPsiType
instanceof PsiArrayType
) {
1072 Evaluator dimensionEvaluator
= null;
1073 PsiExpression
[] dimensions
= expression
.getArrayDimensions();
1074 if (dimensions
.length
== 1){
1075 PsiExpression dimensionExpression
= dimensions
[0];
1076 dimensionExpression
.accept(this);
1077 if (myResult
!= null) {
1078 dimensionEvaluator
= handleUnaryNumericPromotion(dimensionExpression
.getType(), myResult
);
1081 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
1082 DebuggerBundle
.message("evaluation.error.invalid.array.dimension.expression", dimensionExpression
.getText())));
1085 else if (dimensions
.length
> 1){
1086 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
1087 DebuggerBundle
.message("evaluation.error.multi.dimensional.arrays.creation.not.supported"))
1091 Evaluator initializerEvaluator
= null;
1092 PsiArrayInitializerExpression arrayInitializer
= expression
.getArrayInitializer();
1093 if (arrayInitializer
!= null) {
1094 if (dimensionEvaluator
!= null) { // initializer already exists
1095 throw new EvaluateRuntimeException(EvaluateExceptionUtil
1096 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", expression
.getText())));
1098 arrayInitializer
.accept(this);
1099 if (myResult
!= null) {
1100 initializerEvaluator
= handleUnaryNumericPromotion(arrayInitializer
.getType(), myResult
);
1103 throw new EvaluateRuntimeException(EvaluateExceptionUtil
1104 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", arrayInitializer
.getText())));
1107 PsiExpression[] initializers = arrayInitializer.getInitializers();
1108 initializerEvaluators = new Evaluator[initializers.length];
1109 for (int idx = 0; idx < initializers.length; idx++) {
1110 PsiExpression initializer = initializers[idx];
1111 initializer.accept(this);
1112 if (myResult instanceof Evaluator) {
1113 initializerEvaluators[idx] = myResult;
1116 throw new EvaluateException("Invalid expression for array initializer: " + initializer.getText(), true);
1121 if (dimensionEvaluator
== null && initializerEvaluator
== null) {
1122 throw new EvaluateRuntimeException(EvaluateExceptionUtil
1123 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", expression
.getText())));
1125 myResult
= new NewArrayInstanceEvaluator(
1126 new TypeEvaluator(JVMNameUtil
.getJVMQualifiedName(expressionPsiType
)),
1128 initializerEvaluator
1131 else { // must be a class ref
1132 LOG
.assertTrue(expressionPsiType
instanceof PsiClassType
);
1133 PsiClass aClass
= ((PsiClassType
)expressionPsiType
).resolve();
1134 if(aClass
instanceof PsiAnonymousClass
) {
1135 throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(
1136 DebuggerBundle
.message("evaluation.error.anonymous.class.evaluation.not.supported"))
1139 PsiExpressionList argumentList
= expression
.getArgumentList();
1140 if (argumentList
== null) {
1141 throw new EvaluateRuntimeException(EvaluateExceptionUtil
1142 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", expression
.getText())));
1144 PsiExpression
[] argExpressions
= argumentList
.getExpressions();
1145 PsiMethod constructor
= expression
.resolveConstructor();
1146 if (constructor
== null && argExpressions
.length
> 0) {
1147 throw new EvaluateRuntimeException(new EvaluateException(
1148 DebuggerBundle
.message("evaluation.error.cannot.resolve.constructor", expression
.getText()), null));
1150 Evaluator
[] argumentEvaluators
= new Evaluator
[argExpressions
.length
];
1151 // evaluate arguments
1152 for (int idx
= 0; idx
< argExpressions
.length
; idx
++) {
1153 PsiExpression argExpression
= argExpressions
[idx
];
1154 argExpression
.accept(this);
1155 if (myResult
!= null) {
1156 argumentEvaluators
[idx
] = myResult
;
1159 throw new EvaluateRuntimeException(EvaluateExceptionUtil
1160 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", argExpression
.getText())));
1163 //noinspection HardCodedStringLiteral
1164 JVMName signature
= (constructor
!= null)? JVMNameUtil
.getJVMSignature(constructor
) : JVMNameUtil
.getJVMRawText("()V");
1165 myResult
= new NewClassInstanceEvaluator(
1166 new TypeEvaluator(JVMNameUtil
.getJVMQualifiedName(expressionPsiType
)),
1174 public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression
) {
1175 PsiExpression
[] initializers
= expression
.getInitializers();
1176 Evaluator
[] evaluators
= new Evaluator
[initializers
.length
];
1177 for (int idx
= 0; idx
< initializers
.length
; idx
++) {
1178 PsiExpression initializer
= initializers
[idx
];
1179 initializer
.accept(this);
1180 if (myResult
!= null) {
1181 evaluators
[idx
] = handleUnaryNumericPromotion(initializer
.getType(), myResult
);
1184 throw new EvaluateRuntimeException(EvaluateExceptionUtil
1185 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", initializer
.getText())));
1188 myResult
= new ArrayInitializerEvaluator(evaluators
);
1191 private PsiClass
getOuterClass(PsiClass aClass
) {
1192 if(aClass
== null) return null;
1193 return PsiTreeUtil
.getContextOfType(aClass
, PsiClass
.class, true);
1196 private PsiClass
getContainingClass(PsiVariable variable
) {
1197 PsiElement element
= PsiTreeUtil
.getParentOfType(variable
.getParent(), PsiClass
.class, false);
1198 return element
== null ?
getContextPsiClass() : (PsiClass
)element
;
1201 public PsiClass
getContextPsiClass() {
1202 return myContextPsiClass
;
1205 protected ExpressionEvaluator
buildElement(final PsiElement element
) throws EvaluateException
{
1206 LOG
.assertTrue(element
.isValid());
1208 myContextPsiClass
= PsiTreeUtil
.getContextOfType(element
, PsiClass
.class, false);
1210 element
.accept(this);
1212 catch (EvaluateRuntimeException e
) {
1215 if (myResult
== null) {
1216 throw EvaluateExceptionUtil
1217 .createEvaluateException(DebuggerBundle
.message("evaluation.error.invalid.expression", element
.toString()));
1219 return new ExpressionEvaluatorImpl(myResult
);