IDEA-100057 Show exception object in debugger Variables when stopped on exception breakpoint

This commit is contained in:
Eugene Zhuravlev
2013-01-29 21:52:32 +01:00
parent c22c2bec50
commit dd71643f8e
6 changed files with 158 additions and 4 deletions
@@ -29,6 +29,7 @@ import com.sun.jdi.ThreadReference;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.request.EventRequest;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -108,6 +109,7 @@ public abstract class SuspendContextImpl implements SuspendContext {
}
@Nullable
public EventSet getEventSet() {
assertNotResumed();
return myEventSet;
@@ -40,11 +40,14 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.psi.*;
import com.intellij.ui.classFilter.ClassFilter;
import com.intellij.util.SmartList;
import com.sun.jdi.*;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventSet;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -332,16 +335,21 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils {
return elementsEqual(root1, root2);
}
@NotNull
public static List<Pair<Breakpoint, Event>> getEventDescriptors(SuspendContextImpl suspendContext) {
DebuggerManagerThreadImpl.assertIsManagerThread();
if(suspendContext == null || suspendContext.getEventSet() == null) {
if(suspendContext == null) {
return Collections.emptyList();
}
final List<Pair<Breakpoint, Event>> eventDescriptors = new ArrayList<Pair<Breakpoint, Event>>();
final EventSet events = suspendContext.getEventSet();
if(events == null) {
return Collections.emptyList();
}
final List<Pair<Breakpoint, Event>> eventDescriptors = new SmartList<Pair<Breakpoint, Event>>();
final RequestManagerImpl requestManager = suspendContext.getDebugProcess().getRequestsManager();
for (final Event event : suspendContext.getEventSet()) {
Requestor requestor = requestManager.findRequestor(event.request());
for (final Event event : events) {
final Requestor requestor = requestManager.findRequestor(event.request());
if (requestor instanceof Breakpoint) {
eventDescriptors.add(new Pair<Breakpoint, Event>((Breakpoint)requestor, event));
}
@@ -0,0 +1,56 @@
/*
* Copyright 2000-2013 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.ThrownExceptionValueDescriptorImpl;
import com.intellij.openapi.project.Project;
import com.sun.jdi.ObjectReference;
import org.jetbrains.annotations.NotNull;
public final class ThrownExceptionValueData extends DescriptorData<ThrownExceptionValueDescriptorImpl>{
@NotNull
private final ObjectReference myExceptionObj;
public ThrownExceptionValueData(@NotNull ObjectReference exceptionObj) {
myExceptionObj = exceptionObj;
}
protected ThrownExceptionValueDescriptorImpl createDescriptorImpl(Project project) {
return new ThrownExceptionValueDescriptorImpl(project, myExceptionObj);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ThrownExceptionValueData data = (ThrownExceptionValueData)o;
if (!myExceptionObj.equals(data.myExceptionObj)) return false;
return true;
}
@Override
public int hashCode() {
return myExceptionObj.hashCode();
}
public DisplayKey<ThrownExceptionValueDescriptorImpl> getDisplayKey() {
return new SimpleDisplayKey<ThrownExceptionValueDescriptorImpl>(myExceptionObj);
}
}
@@ -31,12 +31,14 @@ import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.LocalVariableProxyImpl;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.jdi.ThreadGroupReferenceProxyImpl;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.settings.ThreadsViewSettings;
import com.intellij.debugger.ui.breakpoints.Breakpoint;
import com.intellij.debugger.ui.impl.DebuggerTreeBase;
import com.intellij.debugger.ui.impl.tree.TreeBuilder;
import com.intellij.debugger.ui.impl.tree.TreeBuilderNode;
@@ -56,6 +58,8 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.SpeedSearchComparator;
import com.intellij.ui.TreeSpeedSearch;
import com.sun.jdi.*;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.ExceptionEvent;
import javax.swing.*;
import javax.swing.event.TreeModelEvent;
@@ -482,6 +486,19 @@ public abstract class DebuggerTree extends DebuggerTreeBase implements DataProvi
final DebuggerTreeNodeImpl methodReturnValueNode = myNodeManager.createNode(returnValueDescriptor, evaluationContext);
myChildren.add(1, methodReturnValueNode);
}
// add context exceptions
for (Pair<Breakpoint, Event> pair : DebuggerUtilsEx.getEventDescriptors(getSuspendContext())) {
final Event debugEvent = pair.getSecond();
if (debugEvent instanceof ExceptionEvent) {
final ObjectReference exception = ((ExceptionEvent)debugEvent).exception();
if (exception != null) {
final ValueDescriptorImpl exceptionDescriptor = myNodeManager.getThrownExceptionObjectDescriptor(stackDescriptor, exception);
final DebuggerTreeNodeImpl exceptionNode = myNodeManager.createNode(exceptionDescriptor, evaluationContext);
myChildren.add(1, exceptionNode);
}
}
}
}
catch (EvaluateException e) {
myChildren.clear();
@@ -172,6 +172,10 @@ public class NodeDescriptorFactoryImpl implements NodeDescriptorFactory {
return getDescriptor(parent, new MethodReturnValueData(method, value));
}
public ValueDescriptorImpl getThrownExceptionObjectDescriptor(NodeDescriptorImpl parent, ObjectReference exceptionObject) {
return getDescriptor(parent, new ThrownExceptionValueData(exceptionObject));
}
public ThreadDescriptorImpl getThreadDescriptor(NodeDescriptorImpl parent, ThreadReferenceProxyImpl thread) {
return getDescriptor(parent, new ThreadData(thread));
}
@@ -0,0 +1,67 @@
/*
* Copyright 2000-2013 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.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiExpression;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.Type;
import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
/**
* User: lex
* Date: Oct 8, 2003
* Time: 5:08:07 PM
*/
public class ThrownExceptionValueDescriptorImpl extends ValueDescriptorImpl{
@NotNull
private final ObjectReference myExceptionObj;
public ThrownExceptionValueDescriptorImpl(Project project, @NotNull ObjectReference exceptionObj) {
super(project);
myExceptionObj = exceptionObj;
}
public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException {
return myExceptionObj;
}
public String getName() {
return "Exception";
}
@NotNull
@Override
public Type getType() {
return myExceptionObj.referenceType();
}
public String calcValueName() {
return getName();
}
public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException {
throw new EvaluateException("Evaluation not supported for thrown exception object");
}
public boolean canSetValue() {
return false;
}
}