show values of method arguments even if degug info for local vars is not available (jdk 1.6+ only)

This commit is contained in:
Eugene Zhuravlev
2009-10-23 18:47:02 +04:00
parent d3a2f74a88
commit d72bd645a3
6 changed files with 214 additions and 27 deletions
@@ -0,0 +1,49 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.debugger.impl.descriptors.data;
import com.intellij.debugger.ui.impl.watch.ArgumentValueDescriptorImpl;
import com.intellij.openapi.project.Project;
import com.sun.jdi.Value;
public class ArgValueData extends DescriptorData<ArgumentValueDescriptorImpl>{
private final int myIndex;
private final Value myValue;
public ArgValueData(int index, Value value) {
super();
myIndex = index;
myValue = value;
}
protected ArgumentValueDescriptorImpl createDescriptorImpl(Project project) {
return new ArgumentValueDescriptorImpl(project, myIndex, myValue);
}
public boolean equals(Object object) {
if(!(object instanceof ArgValueData)) return false;
return myIndex == ((ArgValueData)object).myIndex;
}
public int hashCode() {
return myIndex;
}
public DisplayKey<ArgumentValueDescriptorImpl> getDisplayKey() {
return new SimpleDisplayKey<ArgumentValueDescriptorImpl>(myIndex);
}
}
@@ -25,10 +25,13 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.jdi.StackFrameProxy;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ArrayUtil;
import com.sun.jdi.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
@@ -248,6 +251,34 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
}
}
public Collection<Value> getArgumentValues() throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
try {
final StackFrame stackFrame = getStackFrame();
if (stackFrame != null) {
//return stackFrame.getArgumentValues();
try {
final Method method = StackFrame.class.getMethod("getArgumentValues");
//noinspection unchecked
return (Collection<Value>)method.invoke(stackFrame, ArrayUtil.EMPTY_OBJECT_ARRAY);
}
catch (NoSuchMethodException ignored) {
}
catch (InvocationTargetException e) {
throw new EvaluateException("", e.getCause());
}
catch (IllegalAccessException e) {
LOG.error(e);
}
}
return Collections.emptyList();
}
catch (InvalidStackFrameException e) {
clearCaches();
return getArgumentValues();
}
}
private Map<LocalVariable, Value> getAllValues() throws EvaluateException{
DebuggerManagerThreadImpl.assertIsManagerThread();
checkValid();
@@ -51,7 +51,9 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.ui.tree.TreeModelAdapter;
import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.Value;
import javax.swing.event.TreeModelEvent;
import javax.swing.tree.TreeModel;
@@ -116,34 +118,54 @@ public class FrameDebuggerTree extends DebuggerTree {
super(stackNode);
}
protected void buildVariables(final StackFrameDescriptorImpl stackDescriptor, final EvaluationContextImpl evaluationContext)
throws EvaluateException {
protected void buildVariables(final StackFrameDescriptorImpl stackDescriptor, final EvaluationContextImpl evaluationContext) throws EvaluateException {
final SourcePosition sourcePosition = getDebuggerContext().getSourcePosition();
if (sourcePosition == null) {
return;
}
final Map<String, LocalVariableProxyImpl> visibleVariables = getVisibleVariables(stackDescriptor);
final Pair<Set<String>, Set<TextWithImports>> usedVars =
ApplicationManager.getApplication().runReadAction(new Computable<Pair<Set<String>, Set<TextWithImports>>>() {
public Pair<Set<String>, Set<TextWithImports>> compute() {
return findReferencedVars(visibleVariables.keySet(), sourcePosition);
try {
final Map<String, LocalVariableProxyImpl> visibleVariables = getVisibleVariables(stackDescriptor);
final Pair<Set<String>, Set<TextWithImports>> usedVars =
ApplicationManager.getApplication().runReadAction(new Computable<Pair<Set<String>, Set<TextWithImports>>>() {
public Pair<Set<String>, Set<TextWithImports>> compute() {
return findReferencedVars(visibleVariables.keySet(), sourcePosition);
}
});
// add locals
if (myAutoWatchMode) {
for (String var : usedVars.first) {
final LocalVariableDescriptorImpl descriptor = myNodeManager.getLocalVariableDescriptor(stackDescriptor, visibleVariables.get(var));
myChildren.add(myNodeManager.createNode(descriptor, evaluationContext));
}
});
// add locals
if (myAutoWatchMode) {
for (String var : usedVars.first) {
final LocalVariableDescriptorImpl descriptor = myNodeManager.getLocalVariableDescriptor(stackDescriptor, visibleVariables.get(var));
myChildren.add(myNodeManager.createNode(descriptor, evaluationContext));
}
else {
super.buildVariables(stackDescriptor, evaluationContext);
}
// add expressions
final EvaluationContextImpl evalContextCopy = evaluationContext.createEvaluationContext(evaluationContext.getThisObject());
evalContextCopy.setAutoLoadClasses(false);
for (TextWithImports text : usedVars.second) {
myChildren.add(myNodeManager.createNode(myNodeManager.getWatchItemDescriptor(stackDescriptor, text, null), evalContextCopy));
}
}
else {
super.buildVariables(stackDescriptor, evaluationContext);
}
// add expressions
final EvaluationContextImpl evalContextCopy = evaluationContext.createEvaluationContext(evaluationContext.getThisObject());
evalContextCopy.setAutoLoadClasses(false);
for (TextWithImports text : usedVars.second) {
myChildren.add(myNodeManager.createNode(myNodeManager.getWatchItemDescriptor(stackDescriptor, text, null), evalContextCopy));
catch (EvaluateException e) {
if (e.getCause() instanceof AbsentInformationException) {
final StackFrameProxyImpl frame = stackDescriptor.getFrameProxy();
if (frame == null) {
throw e;
}
final Collection<Value> argValues = frame.getArgumentValues();
int index = 0;
for (Value argValue : argValues) {
final ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(stackDescriptor, index++, argValue);
final DebuggerTreeNodeImpl variableNode = myNodeManager.createNode(descriptor, evaluationContext);
myChildren.add(variableNode);
}
myChildren.add(myNodeManager.createMessageNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE));
}
else {
throw e;
}
}
}
}
@@ -0,0 +1,80 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.debugger.ui.impl.watch;
import com.intellij.debugger.DebuggerContext;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.ContextUtil;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiParameterList;
import com.intellij.psi.util.PsiTreeUtil;
import com.sun.jdi.PrimitiveValue;
import com.sun.jdi.Value;
public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{
private final int myIndex;
private final Value myValue;
private String myName;
public ArgumentValueDescriptorImpl(Project project, int index, Value value) {
super(project);
myIndex = index;
myValue = value;
myName = "arg" + String.valueOf(index);
setLvalue(true);
}
public boolean isPrimitive() {
return myValue instanceof PrimitiveValue;
}
public Value calcValue(final EvaluationContextImpl evaluationContext) throws EvaluateException {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
final SourcePosition position = ContextUtil.getSourcePosition(evaluationContext);
if (position != null) {
final PsiMethod method = PsiTreeUtil.getParentOfType(position.getElementAt(), PsiMethod.class);
if (method != null) {
final PsiParameterList params = method.getParameterList();
if (myIndex < params.getParametersCount()) {
final PsiParameter param = params.getParameters()[myIndex];
myName = param.getName();
}
}
}
}
});
return myValue;
}
public String getName() {
return myName;
}
public String calcValueName() {
return getName();
}
public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException {
return null;
}
}
@@ -538,13 +538,14 @@ public abstract class DebuggerTree extends DebuggerTreeBase implements DataProvi
updateUI(true);
}
protected void buildVariables(final StackFrameDescriptorImpl stackDescriptor, final EvaluationContextImpl evaluationContext)
throws EvaluateException {
protected void buildVariables(final StackFrameDescriptorImpl stackDescriptor, final EvaluationContextImpl evaluationContext) throws EvaluateException {
final StackFrameProxyImpl frame = stackDescriptor.getFrameProxy();
for (final LocalVariableProxyImpl local : frame.visibleVariables()) {
final LocalVariableDescriptorImpl localVariableDescriptor = myNodeManager.getLocalVariableDescriptor(stackDescriptor, local);
final DebuggerTreeNodeImpl variableNode = myNodeManager.createNode(localVariableDescriptor, evaluationContext);
myChildren.add(variableNode);
if (frame != null) {
for (final LocalVariableProxyImpl local : frame.visibleVariables()) {
final LocalVariableDescriptorImpl localVariableDescriptor = myNodeManager.getLocalVariableDescriptor(stackDescriptor, local);
final DebuggerTreeNodeImpl variableNode = myNodeManager.createNode(localVariableDescriptor, evaluationContext);
myChildren.add(variableNode);
}
}
}
}
@@ -152,6 +152,10 @@ public class NodeDescriptorFactoryImpl implements NodeDescriptorFactory {
return getDescriptor(parent, new LocalData((LocalVariableProxyImpl)local));
}
public ArgumentValueDescriptorImpl getArgumentValueDescriptor(NodeDescriptor parent, int index, Value value) {
return getDescriptor(parent, new ArgValueData(index, value));
}
public StackFrameDescriptorImpl getStackFrameDescriptor(NodeDescriptorImpl parent, StackFrameProxyImpl frameProxy) {
return getDescriptor(parent, new StackFrameData(frameProxy));
}