when debug infor for locals is not available allow evaluation of method arguments by their names

This commit is contained in:
Eugene Zhuravlev
2009-11-20 15:38:42 +03:00
parent e14729129e
commit 1949ef9dc7
3 changed files with 112 additions and 49 deletions
@@ -88,7 +88,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myPosition = position;
}
@Override public void visitCodeFragment(JavaCodeFragment codeFragment) {
@Override
public void visitCodeFragment(JavaCodeFragment codeFragment) {
myVisitedFragments.add(codeFragment);
ArrayList<Evaluator> evaluators = new ArrayList<Evaluator>();
@@ -109,12 +110,14 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myCurrentFragmentEvaluator = oldFragmentEvaluator;
}
@Override public void visitErrorElement(PsiErrorElement element) {
@Override
public void visitErrorElement(PsiErrorElement element) {
throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", element.getText())));
}
@Override public void visitAssignmentExpression(PsiAssignmentExpression expression) {
@Override
public void visitAssignmentExpression(PsiAssignmentExpression expression) {
PsiExpression rExpression = expression.getRExpression();
if(rExpression == null) throw new EvaluateRuntimeException(EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText())));
@@ -143,11 +146,13 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new AssignmentEvaluator(lEvaluator, rEvaluator);
}
@Override public void visitStatement(PsiStatement statement) {
@Override
public void visitStatement(PsiStatement statement) {
throw new EvaluateRuntimeException(EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.statement.not.supported", statement.getText())));
}
@Override public void visitBlockStatement(PsiBlockStatement statement) {
@Override
public void visitBlockStatement(PsiBlockStatement statement) {
PsiStatement[] statements = statement.getCodeBlock().getStatements();
Evaluator [] evaluators = new Evaluator[statements.length];
for (int i = 0; i < statements.length; i++) {
@@ -159,7 +164,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new BlockStatementEvaluator(evaluators);
}
@Override public void visitWhileStatement(PsiWhileStatement statement) {
@Override
public void visitWhileStatement(PsiWhileStatement statement) {
PsiStatement body = statement.getBody();
if(body == null) return;
body.accept(this);
@@ -175,7 +181,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new WhileStatementEvaluator(myResult, bodyEvaluator, label);
}
@Override public void visitForStatement(PsiForStatement statement) {
@Override
public void visitForStatement(PsiForStatement statement) {
PsiStatement initializer = statement.getInitialization();
Evaluator initializerEvaluator = null;
if(initializer != null){
@@ -209,7 +216,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new ForStatementEvaluator(initializerEvaluator, conditionEvaluator, updateEvaluator, bodyEvaluator, label);
}
@Override public void visitIfStatement(PsiIfStatement statement) {
@Override
public void visitIfStatement(PsiIfStatement statement) {
PsiStatement thenBranch = statement.getThenBranch();
if(thenBranch == null) return;
thenBranch.accept(this);
@@ -229,27 +237,32 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new IfStatementEvaluator(myResult, thenEvaluator, elseEvaluator);
}
@Override public void visitBreakStatement(PsiBreakStatement statement) {
@Override
public void visitBreakStatement(PsiBreakStatement statement) {
PsiIdentifier labelIdentifier = statement.getLabelIdentifier();
myResult = BreakContinueStatementEvaluator.createBreakEvaluator(labelIdentifier != null ? labelIdentifier.getText() : null);
}
@Override public void visitContinueStatement(PsiContinueStatement statement) {
@Override
public void visitContinueStatement(PsiContinueStatement statement) {
PsiIdentifier labelIdentifier = statement.getLabelIdentifier();
myResult = BreakContinueStatementEvaluator.createContinueEvaluator(labelIdentifier != null ? labelIdentifier.getText() : null);
}
@Override public void visitExpressionStatement(PsiExpressionStatement statement) {
@Override
public void visitExpressionStatement(PsiExpressionStatement statement) {
statement.getExpression().accept(this);
}
@Override public void visitExpression(PsiExpression expression) {
@Override
public void visitExpression(PsiExpression expression) {
if (LOG.isDebugEnabled()) {
LOG.debug("visitExpression " + expression);
}
}
@Override public void visitBinaryExpression(PsiBinaryExpression expression) {
@Override
public void visitBinaryExpression(PsiBinaryExpression expression) {
if (LOG.isDebugEnabled()) {
LOG.debug("visitBinaryExpression " + expression);
}
@@ -270,7 +283,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new BinaryExpressionEvaluator(lResult, myResult, opType, type.getCanonicalText());
}
@Override public void visitDeclarationStatement(PsiDeclarationStatement statement) {
@Override
public void visitDeclarationStatement(PsiDeclarationStatement statement) {
List<Evaluator> evaluators = new ArrayList<Evaluator>();
PsiElement[] declaredElements = statement.getDeclaredElements();
@@ -336,7 +350,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
}
}
@Override public void visitConditionalExpression(PsiConditionalExpression expression) {
@Override
public void visitConditionalExpression(PsiConditionalExpression expression) {
if (LOG.isDebugEnabled()) {
LOG.debug("visitConditionalExpression " + expression);
}
@@ -368,7 +383,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new ConditionalExpressionEvaluator(conditionEvaluator, thenEvaluator, elseEvaluator);
}
@Override public void visitReferenceExpression(PsiReferenceExpression expression) {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
if (LOG.isDebugEnabled()) {
LOG.debug("visitReferenceExpression " + expression);
}
@@ -386,11 +402,19 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
return;
}
// local variable
PsiVariable psiVar = (PsiVariable)element;
String localName = psiVar.getName();
final PsiVariable psiVar = (PsiVariable)element;
final String localName = psiVar.getName();
PsiClass variableClass = getContainingClass(psiVar);
if (getContextPsiClass() == null || getContextPsiClass().equals(variableClass)) {
myResult = new LocalVariableEvaluator(localName, ContextUtil.isJspImplicit(element));
final LocalVariableEvaluator localVarEvaluator = new LocalVariableEvaluator(localName, ContextUtil.isJspImplicit(element));
if (psiVar instanceof PsiParameter) {
final PsiParameter param = (PsiParameter)psiVar;
final PsiParameterList paramList = PsiTreeUtil.getParentOfType(param, PsiParameterList.class, true);
if (paramList != null) {
localVarEvaluator.setParameterIndex(paramList.getParameterIndex(param));
}
}
myResult = localVarEvaluator;
return;
}
// the expression references final var outside the context's class (in some of the outer classes)
@@ -451,7 +475,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
objectEvaluator = new ThisEvaluator(iterationCount);
}
myResult = new FieldEvaluator(objectEvaluator, FieldEvaluator.createClassFilter(fieldClass), psiField.getName());
} else {
}
else {
//let's guess what this could be
PsiElement nameElement = expression.getReferenceNameElement(); // get "b" part
String name;
@@ -497,7 +522,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
}
}
@Override public void visitSuperExpression(PsiSuperExpression expression) {
@Override
public void visitSuperExpression(PsiSuperExpression expression) {
if (LOG.isDebugEnabled()) {
LOG.debug("visitSuperExpression " + expression);
}
@@ -505,7 +531,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new SuperEvaluator(iterationCount);
}
@Override public void visitThisExpression(PsiThisExpression expression) {
@Override
public void visitThisExpression(PsiThisExpression expression) {
if (LOG.isDebugEnabled()) {
LOG.debug("visitThisExpression " + expression);
}
@@ -535,7 +562,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
return iterationCount;
}
@Override public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
@Override
public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
if (LOG.isDebugEnabled()) {
LOG.debug("visitInstanceOfExpression " + expression);
}
@@ -550,7 +578,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new InstanceofEvaluator(operandEvaluator, new TypeEvaluator(JVMNameUtil.getJVMQualifiedName(type)));
}
@Override public void visitParenthesizedExpression(PsiParenthesizedExpression expression) {
@Override
public void visitParenthesizedExpression(PsiParenthesizedExpression expression) {
if (LOG.isDebugEnabled()) {
LOG.debug("visitParenthesizedExpression " + expression);
}
@@ -560,7 +589,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
}
}
@Override public void visitPostfixExpression(PsiPostfixExpression expression) {
@Override
public void visitPostfixExpression(PsiPostfixExpression expression) {
expression.getOperand().accept(this);
PsiType type = expression.getType();
if(type == null) {
@@ -570,7 +600,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new PostfixOperationEvaluator(myResult, expression.getOperationSign().getTokenType(), type.getCanonicalText());
}
@Override public void visitPrefixExpression(final PsiPrefixExpression expression) {
@Override
public void visitPrefixExpression(final PsiPrefixExpression expression) {
final PsiType type = expression.getType();
if(type == null) {
throw new EvaluateRuntimeException(
@@ -714,7 +745,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new MethodEvaluator(objectEvaluator, contextClass, methodExpr.getReferenceName(), psiMethod != null ? JVMNameUtil.getJVMSignature(psiMethod) : null, argumentEvaluators);
}
@Override public void visitLiteralExpression(PsiLiteralExpression expression) {
@Override
public void visitLiteralExpression(PsiLiteralExpression expression) {
Object value = expression.getValue();
if(expression.getParsingError() != null) {
throw new EvaluateRuntimeException(EvaluateExceptionUtil.createEvaluateException(expression.getParsingError()));
@@ -722,7 +754,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new LiteralEvaluator(value, expression.getType().getCanonicalText());
}
@Override public void visitArrayAccessExpression(PsiArrayAccessExpression expression) {
@Override
public void visitArrayAccessExpression(PsiArrayAccessExpression expression) {
final PsiExpression indexExpression = expression.getIndexExpression();
if(indexExpression == null) {
throw new EvaluateRuntimeException(EvaluateExceptionUtil
@@ -735,13 +768,15 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new ArrayAccessEvaluator(arrayEvaluator, indexEvaluator);
}
@Override public void visitTypeCastExpression(PsiTypeCastExpression expression) {
@Override
public void visitTypeCastExpression(PsiTypeCastExpression expression) {
expression.getOperand().accept(this);
PsiType castType = expression.getCastType().getType();
myResult = new TypeCastEvaluator(myResult, castType.getCanonicalText(), castType instanceof PsiPrimitiveType);
}
@Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
@Override
public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
PsiType type = expression.getOperand().getType();
if (type instanceof PsiPrimitiveType) {
@@ -753,7 +788,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
}
}
@Override public void visitNewExpression(PsiNewExpression expression) {
@Override
public void visitNewExpression(PsiNewExpression expression) {
PsiType expressionPsiType = expression.getType();
if (expressionPsiType instanceof PsiArrayType) {
Evaluator dimensionEvaluator = null;
@@ -857,7 +893,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
}
}
@Override public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
@Override
public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
PsiExpression[] initializers = expression.getInitializers();
Evaluator[] evaluators = new Evaluator[initializers.length];
for (int idx = 0; idx < initializers.length; idx++) {
@@ -20,6 +20,7 @@
*/
package com.intellij.debugger.engine.evaluation.expression;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
@@ -28,13 +29,11 @@ import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.ui.impl.watch.LocalVariableDescriptorImpl;
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.Type;
import com.sun.jdi.Value;
import com.sun.jdi.*;
import java.util.List;
class LocalVariableEvaluator implements Evaluator {
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.evaluation.expression.LocalVariableEvaluator");
@@ -43,12 +42,17 @@ class LocalVariableEvaluator implements Evaluator {
private EvaluationContextImpl myContext;
private LocalVariableProxyImpl myEvaluatedVariable;
private final boolean myIsJspSpecial;
private int myParameterIndex = -1;
public LocalVariableEvaluator(String localVariableName, boolean isJspSpecial) {
myLocalVariableName = localVariableName;
myIsJspSpecial = isJspSpecial;
}
public void setParameterIndex(int parameterIndex) {
myParameterIndex = parameterIndex;
}
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
StackFrameProxyImpl frameProxy = context.getFrameProxy();
if (frameProxy == null) {
@@ -56,18 +60,40 @@ class LocalVariableEvaluator implements Evaluator {
}
try {
for(;;) {
LocalVariableProxyImpl local = frameProxy.visibleVariableByName(myLocalVariableName);
if (local != null) {
myEvaluatedVariable = local;
myContext = context;
return frameProxy.getValue(local);
ThreadReferenceProxyImpl threadProxy = null;
int lastFrameIndex = -1;
while (true) {
try {
LocalVariableProxyImpl local = frameProxy.visibleVariableByName(myLocalVariableName);
if (local != null) {
myEvaluatedVariable = local;
myContext = context;
return frameProxy.getValue(local);
}
}
catch (EvaluateException e) {
if (!(e.getCause() instanceof AbsentInformationException)) {
throw e;
}
if (myParameterIndex < 0) {
throw e;
}
final List<Value> values = frameProxy.getArgumentValues();
if (values.isEmpty() || myParameterIndex >= values.size()) {
throw e;
}
return values.get(myParameterIndex);
}
ThreadReferenceProxyImpl threadProxy = frameProxy.threadProxy();
if(myIsJspSpecial && frameProxy.getFrameIndex() < threadProxy.frameCount() - 1) {
if(frameProxy.getFrameIndex() < threadProxy.frameCount() - 1) {
frameProxy = threadProxy.frame(frameProxy.getFrameIndex() + 1);
if (myIsJspSpecial) {
if (threadProxy == null /* initialize it lazily */) {
threadProxy = frameProxy.threadProxy();
lastFrameIndex = threadProxy.frameCount() - 1;
}
final int currentFrameIndex = frameProxy.getFrameIndex();
if (currentFrameIndex < lastFrameIndex) {
frameProxy = threadProxy.frame(currentFrameIndex + 1);
continue;
}
}
@@ -251,7 +251,7 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
}
}
public Collection<Value> getArgumentValues() throws EvaluateException {
public List<Value> getArgumentValues() throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
try {
final StackFrame stackFrame = getStackFrame();
@@ -260,7 +260,7 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
try {
final Method method = StackFrame.class.getMethod("getArgumentValues");
//noinspection unchecked
return (Collection<Value>)method.invoke(stackFrame, ArrayUtil.EMPTY_OBJECT_ARRAY);
return (List<Value>)method.invoke(stackFrame, ArrayUtil.EMPTY_OBJECT_ARRAY);
}
catch (NoSuchMethodException ignored) {
}