autoboxing & numeric promotion support for debugger evaluators: fixes in implicit...
[fedora-idea.git] / java / debugger / impl / src / com / intellij / debugger / engine / evaluation / expression / EvaluatorBuilderImpl.java
blob4ba6980802226d269dffb68e9e88d2fe4eca15a8
1 /*
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
19 * @author Jeka
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;
47 import java.util.Set;
49 public class EvaluatorBuilderImpl implements EvaluatorBuilder {
50 private static final EvaluatorBuilderImpl ourInstance = new EvaluatorBuilderImpl();
52 private EvaluatorBuilderImpl() {
55 public static EvaluatorBuilder getInstance() {
56 return ourInstance;
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>();
86 @Nullable
87 private final SourcePosition myPosition;
89 private Builder(@Nullable SourcePosition position) {
90 myPosition = position;
93 @Override
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()) {
102 child.accept(this);
103 if(myResult != null) {
104 evaluators.add(myResult);
106 myResult = null;
109 myCurrentFragmentEvaluator.setStatements(evaluators.toArray(new Evaluator[evaluators.size()]));
110 myResult = myCurrentFragmentEvaluator;
112 myCurrentFragmentEvaluator = oldFragmentEvaluator;
115 @Override
116 public void visitErrorElement(PsiErrorElement element) {
117 throw new EvaluateRuntimeException(EvaluateExceptionUtil
118 .createEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", element.getText())));
121 @Override
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();
142 if(lType == null) {
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);
171 else {
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);
186 return rEvaluator;
189 @Override
190 public void visitStatement(PsiStatement statement) {
191 throw new EvaluateRuntimeException(EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.statement.not.supported", statement.getText())));
194 @Override
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;
202 myResult = null;
204 myResult = new BlockStatementEvaluator(evaluators);
207 @Override
208 public void visitWhileStatement(PsiWhileStatement statement) {
209 PsiStatement body = statement.getBody();
210 if(body == null) return;
211 body.accept(this);
212 Evaluator bodyEvaluator = myResult;
214 PsiExpression condition = statement.getCondition();
215 if(condition == null) return;
216 condition.accept(this);
217 String label = null;
218 if(statement.getParent() instanceof PsiLabeledStatement) {
219 label = ((PsiLabeledStatement)statement.getParent()).getLabelIdentifier().getText();
221 myResult = new WhileStatementEvaluator(myResult, bodyEvaluator, label);
224 @Override
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;
242 if(update != null){
243 update.accept(this);
244 updateEvaluator = myResult;
247 PsiStatement body = statement.getBody();
248 if(body == null) return;
249 body.accept(this);
250 Evaluator bodyEvaluator = myResult;
252 String label = null;
253 if(statement.getParent() instanceof PsiLabeledStatement) {
254 label = ((PsiLabeledStatement)statement.getParent()).getLabelIdentifier().getText();
256 myResult = new ForStatementEvaluator(initializerEvaluator, conditionEvaluator, updateEvaluator, bodyEvaluator, label);
259 @Override
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);
280 @Override
281 public void visitBreakStatement(PsiBreakStatement statement) {
282 PsiIdentifier labelIdentifier = statement.getLabelIdentifier();
283 myResult = BreakContinueStatementEvaluator.createBreakEvaluator(labelIdentifier != null ? labelIdentifier.getText() : null);
286 @Override
287 public void visitContinueStatement(PsiContinueStatement statement) {
288 PsiIdentifier labelIdentifier = statement.getLabelIdentifier();
289 myResult = BreakContinueStatementEvaluator.createContinueEvaluator(labelIdentifier != null ? labelIdentifier.getText() : null);
292 @Override
293 public void visitExpressionStatement(PsiExpressionStatement statement) {
294 statement.getExpression().accept(this);
297 @Override
298 public void visitExpression(PsiExpression expression) {
299 if (LOG.isDebugEnabled()) {
300 LOG.debug("visitExpression " + expression);
304 @Override
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);
387 else {
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) {
402 return false;
404 if (opType == JavaTokenType.EQEQ || opType == JavaTokenType.NE) {
405 if (PsiType.NULL.equals(lType) || PsiType.NULL.equals(rType)) {
406 return false;
408 if (lType instanceof PsiClassType && rType instanceof PsiClassType) {
409 return false;
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
417 return true;
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)) {
437 return false;
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;
449 * @param type
450 * @return promotion type to cast to or null if no casting needed
452 @Nullable
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)) {
455 return PsiType.INT;
457 return null;
460 @Override
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();
473 try {
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) {
479 LOG.error(e);
481 catch (EvaluateException e) {
482 throw new EvaluateRuntimeException(e);
485 PsiExpression initializer = localVariable.getInitializer();
486 if (initializer != null) {
487 try {
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) {
506 LOG.error(e);
510 else {
511 throw new EvaluateRuntimeException(new EvaluateException(
512 DebuggerBundle.message("evaluation.error.local.variable.declarations.not.supported"), null));
515 else {
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;
525 } else {
526 myResult = null;
530 @Override
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);
563 @Override
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) {
572 //synthetic variable
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());
579 return;
581 // local variable
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;
595 return;
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)) {
601 iterationCount++;
602 aClass = getOuterClass(aClass);
604 if (aClass != null) {
605 if(psiVar.getInitializer() != null) {
606 Object value = JavaPsiFacade.getInstance(psiVar.getProject()).getConstantEvaluationHelper().computeConstantExpression(psiVar.getInitializer());
607 if(value != null) {
608 myResult = new LiteralEvaluator(value, psiVar.getType().getCanonicalText());
609 return;
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);
617 return;
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))) {
645 iterationCount++;
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());
656 else {
657 //let's guess what this could be
658 PsiElement nameElement = expression.getReferenceNameElement(); // get "b" part
659 String name;
660 if (nameElement instanceof PsiIdentifier) {
661 name = nameElement.getText();
663 else {
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);
678 else {
679 PsiType type = qualifier.getType();
680 if(type == null) {
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);
696 else {
697 myResult = new LocalVariableEvaluator(name, false);
702 @Override
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);
711 @Override
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())));
728 try {
729 PsiClass aClass = getContextPsiClass();
730 while (aClass != null && !aClass.equals(targetClass)) {
731 iterationCount++;
732 aClass = getOuterClass(aClass);
735 catch (Exception e) {
736 throw new EvaluateRuntimeException(EvaluateExceptionUtil.createEvaluateException(e));
739 return iterationCount;
742 @Override
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)));
758 @Override
759 public void visitParenthesizedExpression(PsiParenthesizedExpression expression) {
760 if (LOG.isDebugEnabled()) {
761 LOG.debug("visitParenthesizedExpression " + expression);
763 PsiExpression expr = expression.getExpression();
764 if (expr != null){
765 expr.accept(this);
769 @Override
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);
798 @Override
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();
819 @Nullable
820 final PsiType unboxedOperandType = PsiPrimitiveType.getUnboxedType(operandType);
822 final IElementType operation = expression.getOperationSign().getTokenType();
824 if(operation == JavaTokenType.PLUSPLUS || operation == JavaTokenType.MINUSMINUS) {
825 try {
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) {
835 LOG.error(e);
838 else {
839 if (JavaTokenType.PLUS.equals(operation) || JavaTokenType.MINUS.equals(operation)|| JavaTokenType.TILDE.equals(operation)) {
840 operandEvaluator = handleUnaryNumericPromotion(operandType, operandEvaluator);
842 else {
843 if (unboxedOperandType != null) {
844 operandEvaluator = new UnBoxingEvaluator(operandEvaluator);
847 myResult = new UnaryExpressionEvaluator(operation, expressionType.getCanonicalText(), operandEvaluator, expression.getOperationSign().getText());
851 @Override
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;
889 else {
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);
896 iterationCount++;
899 objectEvaluator = new ThisEvaluator(iterationCount);
902 else {
903 //trying to guess
904 if (qualifier != null) {
905 PsiType type = qualifier.getType();
907 if (type != null) {
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);
921 else {
922 qualifier.accept(this);
923 objectEvaluator = myResult;
926 else {
927 objectEvaluator = new ThisEvaluator();
928 contextClass = JVMNameUtil.getContextClassJVMQualifiedName(myPosition);
929 if(contextClass == null && myContextPsiClass != null) {
930 contextClass = JVMNameUtil.getJVMQualifiedName(myContextPsiClass);
932 //else {
933 // throw new EvaluateRuntimeException(EvaluateExceptionUtil.createEvaluateException(
934 // DebuggerBundle.message("evaluation.error.method.not.found", methodExpr.getReferenceName()))
935 // );
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) {
951 // handle autoboxing
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);
966 @Override
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());
975 @Override
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"})
1018 @Override
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);
1055 @Override
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");
1063 else {
1064 myResult = new ClassObjectEvaluator(new TypeEvaluator(JVMNameUtil.getJVMQualifiedName(type)));
1068 @Override
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);
1080 else {
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);
1102 else {
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;
1115 else {
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)),
1127 dimensionEvaluator,
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;
1158 else {
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)),
1167 signature,
1168 argumentEvaluators
1173 @Override
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);
1183 else {
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);
1209 try {
1210 element.accept(this);
1212 catch (EvaluateRuntimeException e) {
1213 throw e.getCause();
1215 if (myResult == null) {
1216 throw EvaluateExceptionUtil
1217 .createEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", element.toString()));
1219 return new ExpressionEvaluatorImpl(myResult);