Browse Source

Ensure that the root node of debugger tooltip can be re-evaluated

newNRvisualizers
David Srbecký 13 years ago
parent
commit
ae35b9e8ea
  1. 21
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
  2. 23
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs
  3. 4
      src/AddIns/Debugger/Debugger.Core/StackFrame.cs

21
src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

@ -710,18 +710,23 @@ namespace ICSharpCode.SharpDevelop.Services
{ {
if (!(IsDebugging && CurrentProcess.IsPaused)) if (!(IsDebugging && CurrentProcess.IsPaused))
return; return;
if (e.ResolveResult == null) var resolveResult = e.ResolveResult;
if (resolveResult == null)
return; return;
if (e.ResolveResult is LocalResolveResult || e.ResolveResult is MemberResolveResult || e.ResolveResult is InvocationResolveResult) { if (resolveResult is LocalResolveResult || resolveResult is MemberResolveResult || resolveResult is InvocationResolveResult) {
string text = string.Empty;
try { try {
text = new ResolveResultPrettyPrinter().Print(resolveResult);
} catch (NotImplementedException) {
}
Func<Value> getValue = delegate {
ExpressionEvaluationVisitor eval = new ExpressionEvaluationVisitor(CurrentStackFrame, EvalThread, CurrentStackFrame.AppDomain.Compilation); ExpressionEvaluationVisitor eval = new ExpressionEvaluationVisitor(CurrentStackFrame, EvalThread, CurrentStackFrame.AppDomain.Compilation);
Value result = eval.Convert(e.ResolveResult); return eval.Convert(resolveResult);
string text = new ResolveResultPrettyPrinter().Print(e.ResolveResult); };
e.SetToolTip(new DebuggerTooltipControl(ValueNode.GetTooltipFor(text, result))); try {
} catch (GetValueException ex) { var rootNode = new ValueNode(ClassBrowserIconService.LocalVariable, text, getValue);
e.SetToolTip(ex.Message); e.SetToolTip(new DebuggerTooltipControl(rootNode));
} catch (InvalidOperationException) { } catch (InvalidOperationException) {
return;
} }
} }
} }

23
src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs

@ -72,7 +72,7 @@ namespace Debugger.AddIn.TreeModel
cachedValue = this.getValue().GetPermanentReference(WindowsDebugger.EvalThread); cachedValue = this.getValue().GetPermanentReference(WindowsDebugger.EvalThread);
cachedValueProcess = cachedValue.Process; cachedValueProcess = cachedValue.Process;
cachedValueDebuggeeState = cachedValue.Process.DebuggeeState; cachedValueDebuggeeState = cachedValue.Process.DebuggeeState;
LoggingService.InfoFormatted("Evaluated node '{0}' in {1} ms (result cached for future use)", this.Name, watch.ElapsedMilliseconds); LoggingService.InfoFormatted("Evaluated node '{0}' in {1} ms (result cached)", this.Name, watch.ElapsedMilliseconds);
} }
return cachedValue; return cachedValue;
} }
@ -92,9 +92,8 @@ namespace Debugger.AddIn.TreeModel
} }
} }
/// <summary> /// <summary> Get the value of the node and update the UI text fields. </summary>
/// Get the value of the node and update the UI text fields. /// <remarks> This should be only called once so the Value is not cached. </remarks>
/// </summary>
void GetValueAndUpdateUI() void GetValueAndUpdateUI()
{ {
try { try {
@ -175,7 +174,6 @@ namespace Debugger.AddIn.TreeModel
this.Type = string.Empty; this.Type = string.Empty;
this.GetChildren = null; this.GetChildren = null;
#warning this.VisualizerCommands = null; #warning this.VisualizerCommands = null;
return;
} }
} }
@ -242,13 +240,6 @@ namespace Debugger.AddIn.TreeModel
return WindowsDebugger.CurrentStackFrame; return WindowsDebugger.CurrentStackFrame;
} }
public static TreeNode GetTooltipFor(string text, Value value)
{
if (value == null)
throw new ArgumentNullException("value");
return new ValueNode(ClassBrowserIconService.LocalVariable, text, () => value);
}
public static IEnumerable<TreeNode> GetLocalVariables() public static IEnumerable<TreeNode> GetLocalVariables()
{ {
var stackFrame = GetCurrentStackFrame(); var stackFrame = GetCurrentStackFrame();
@ -361,15 +352,13 @@ namespace Debugger.AddIn.TreeModel
} }
} }
/// <remarks> 'getValue' really should return cached value, because we do Eval to create indices. </remarks>
static IEnumerable<TreeNode> GetIListChildren(Func<Value> getValue) static IEnumerable<TreeNode> GetIListChildren(Func<Value> getValue)
{ {
Value list;
IProperty itemProp; IProperty itemProp;
int count = 0; int count = 0;
try { try {
// TODO: We want new list on reeval Value list = getValue();
// We need the list to survive generation of index via Eval
list = getValue().GetPermanentReference(WindowsDebugger.EvalThread);
IType iListType = list.Type.GetAllBaseTypeDefinitions().Where(t => t.FullName == typeof(IList).FullName).FirstOrDefault(); IType iListType = list.Type.GetAllBaseTypeDefinitions().Where(t => t.FullName == typeof(IList).FullName).FirstOrDefault();
itemProp = iListType.GetProperties(p => p.Name == "Item").Single(); itemProp = iListType.GetProperties(p => p.Name == "Item").Single();
// Do not get string representation since it can be printed in hex // Do not get string representation since it can be printed in hex
@ -380,7 +369,7 @@ namespace Debugger.AddIn.TreeModel
if (count == 0) { if (count == 0) {
return new [] { new TreeNode("(empty)", null) }; return new [] { new TreeNode("(empty)", null) };
} else { } else {
return Enumerable.Range(0, count).Select(i => new ValueNode(ClassBrowserIconService.Field, "[" + i + "]", () => list.GetPropertyValue(WindowsDebugger.EvalThread, itemProp, Eval.CreateValue(WindowsDebugger.EvalThread, i)))); return Enumerable.Range(0, count).Select(i => new ValueNode(ClassBrowserIconService.Field, "[" + i + "]", () => getValue().GetPropertyValue(WindowsDebugger.EvalThread, itemProp, Eval.CreateValue(WindowsDebugger.EvalThread, i))));
} }
} }

4
src/AddIns/Debugger/Debugger.Core/StackFrame.cs

@ -371,7 +371,9 @@ namespace Debugger
public Value GetLocalVariableValue(string name) public Value GetLocalVariableValue(string name)
{ {
var loc = GetLocalVariables(this.IP).Where(v => v.Name == name).FirstOrDefault(); var loc = GetLocalVariables(this.IP).Where(v => v.Name == name).FirstOrDefault();
return loc != null ? loc.GetValue(this) : null; if (loc == null)
throw new GetValueException("Local variable \"{0}\" not found", name);
return loc.GetValue(this);
} }
/// <summary> Gets value indicating whether this method should be stepped over according to current options </summary> /// <summary> Gets value indicating whether this method should be stepped over according to current options </summary>

Loading…
Cancel
Save