Browse Source
The old method was to keep a NRefactory expression for each node. The new method is create a lambda expression for each node. The main motivation for this change is to get ready for NR5 which does not allow any sharing of AST nodes. This would mean that we would have to create a complete AST for each node, which might get expensive for deeply nested nodes. Caching of already evaluated expression would also be more difficult with separate ASTs. ILSpy is based on NR5 so we need this solution for it right now. Another disadvantage was that every operation had to go though AST so we had to support it in the evaluator, we had to generate the AST, and we had to hope that nothing breaks on the way. This is particularly complex for types - with lambda expression we simply keep around the reference to the type or to whatever we need. Some things like "current exception object" do not exist in the AST so we had to hack around it. On the other had, it was nice to have accurate C# expression for all nodes - for pretty printing, editing, or saving/loading it.newNRvisualizers
57 changed files with 360 additions and 1437 deletions
@ -1,49 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Text; |
|
||||||
using Debugger.AddIn.TreeModel; |
|
||||||
using ICSharpCode.NRefactory; |
|
||||||
using ICSharpCode.SharpDevelop.Project; |
|
||||||
|
|
||||||
namespace ICSharpCode.SharpDevelop.Gui.Pads |
|
||||||
{ |
|
||||||
public class TextNode : TreeNode, ISetText |
|
||||||
{ |
|
||||||
public TextNode(TreeNode parent, string text, SupportedLanguage language) |
|
||||||
: base(parent) |
|
||||||
{ |
|
||||||
this.Name = text; |
|
||||||
this.Language = language; |
|
||||||
} |
|
||||||
|
|
||||||
public override bool CanSetText { |
|
||||||
get { |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public override bool SetText(string text) |
|
||||||
{ |
|
||||||
this.Text = text; |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public bool SetName(string name) |
|
||||||
{ |
|
||||||
this.Name = name; |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public SupportedLanguage Language { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public class ErrorInfoNode : ICorDebug.InfoNode |
|
||||||
{ |
|
||||||
public ErrorInfoNode(string name, string text) : base(null, name, text) |
|
||||||
{ |
|
||||||
IconImage = DebuggerResourceService.GetImage("Icons.16x16.Error"); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,25 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using ICSharpCode.SharpDevelop; |
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Linq; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.TreeModel |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Gets resources the way suitable for Debugger.AddIn.
|
|
||||||
/// </summary>
|
|
||||||
public static class DebuggerResourceService |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Gets image with given name from resources.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="resourceName">Resource name of the image.</param>
|
|
||||||
public static IImage GetImage(string resourceName) |
|
||||||
{ |
|
||||||
return new ResourceServiceImage(resourceName); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,12 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using System.Windows.Forms; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.TreeModel |
|
||||||
{ |
|
||||||
public interface IContextMenu |
|
||||||
{ |
|
||||||
ContextMenuStrip GetContextMenu(); |
|
||||||
} |
|
||||||
} |
|
@ -1,158 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using Debugger.Interop.CorDebug; |
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using Debugger.MetaData; |
|
||||||
using ICSharpCode.SharpDevelop.Debugging; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.TreeModel |
|
||||||
{ |
|
||||||
public class ICorDebug |
|
||||||
{ |
|
||||||
public class InfoNode: TreeNode |
|
||||||
{ |
|
||||||
List<TreeNode> children; |
|
||||||
|
|
||||||
public InfoNode(TreeNode parent, string name, string text) |
|
||||||
: this(parent, name, text, _ => null) |
|
||||||
{ |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public InfoNode(TreeNode parent, string name, string text, Func<TreeNode, List<TreeNode>> children) |
|
||||||
: base(parent) |
|
||||||
{ |
|
||||||
this.Name = name; |
|
||||||
this.Text = text; |
|
||||||
this.children = children(this); |
|
||||||
} |
|
||||||
|
|
||||||
public override IEnumerable<TreeNode> ChildNodes { |
|
||||||
get { return children; } |
|
||||||
} |
|
||||||
|
|
||||||
public void AddChild(string name, string text) |
|
||||||
{ |
|
||||||
if (children == null) { |
|
||||||
children = new List<TreeNode>(); |
|
||||||
} |
|
||||||
children.Add(new InfoNode(this, name, text)); |
|
||||||
} |
|
||||||
|
|
||||||
public void AddChild(string name, string text, Func<TreeNode, List<TreeNode>> subChildren) |
|
||||||
{ |
|
||||||
if (children == null) { |
|
||||||
children = new List<TreeNode>(); |
|
||||||
} |
|
||||||
children.Add(new InfoNode(this, name, text, p => subChildren(p))); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static InfoNode GetDebugInfoRoot(AppDomain appDomain, ICorDebugValue corValue) |
|
||||||
{ |
|
||||||
return new InfoNode(null, "ICorDebug", "", p => GetDebugInfo(p, appDomain, corValue)); |
|
||||||
} |
|
||||||
|
|
||||||
public static List<TreeNode> GetDebugInfo(TreeNode parent, AppDomain appDomain, ICorDebugValue corValue) |
|
||||||
{ |
|
||||||
List<TreeNode> items = new List<TreeNode>(); |
|
||||||
|
|
||||||
if (corValue is ICorDebugValue) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugValue", ""); |
|
||||||
info.AddChild("Address", corValue.GetAddress().ToString("X8")); |
|
||||||
info.AddChild("Type", ((CorElementType)corValue.GetTheType()).ToString()); |
|
||||||
info.AddChild("Size", corValue.GetSize().ToString()); |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugValue2) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugValue2", ""); |
|
||||||
ICorDebugValue2 corValue2 = (ICorDebugValue2)corValue; |
|
||||||
string fullname; |
|
||||||
try { |
|
||||||
fullname = DebugType.CreateFromCorType(appDomain, corValue2.GetExactType()).FullName; |
|
||||||
} catch (DebuggerException e) { |
|
||||||
fullname = e.Message; |
|
||||||
} |
|
||||||
info.AddChild("ExactType", fullname); |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugGenericValue) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugGenericValue", ""); |
|
||||||
try { |
|
||||||
byte[] bytes = ((ICorDebugGenericValue)corValue).GetRawValue(); |
|
||||||
for(int i = 0; i < bytes.Length; i += 8) { |
|
||||||
string val = ""; |
|
||||||
for(int j = i; j < bytes.Length && j < i + 8; j++) { |
|
||||||
val += bytes[j].ToString("X2") + " "; |
|
||||||
} |
|
||||||
info.AddChild("Value" + i.ToString("X2"), val); |
|
||||||
} |
|
||||||
} catch (ArgumentException) { |
|
||||||
info.AddChild("Value", "N/A"); |
|
||||||
} |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugReferenceValue) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugReferenceValue", ""); |
|
||||||
ICorDebugReferenceValue refValue = (ICorDebugReferenceValue)corValue; |
|
||||||
info.AddChild("IsNull", (refValue.IsNull() != 0).ToString()); |
|
||||||
if (refValue.IsNull() == 0) { |
|
||||||
info.AddChild("Value", refValue.GetValue().ToString("X8")); |
|
||||||
if (refValue.Dereference() != null) { |
|
||||||
info.AddChild("Dereference", "", p => GetDebugInfo(p, appDomain, refValue.Dereference())); |
|
||||||
} else { |
|
||||||
info.AddChild("Dereference", "N/A"); |
|
||||||
} |
|
||||||
} |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugHeapValue) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugHeapValue", ""); |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugHeapValue2) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugHeapValue2", ""); |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugObjectValue) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugObjectValue", ""); |
|
||||||
ICorDebugObjectValue objValue = (ICorDebugObjectValue)corValue; |
|
||||||
info.AddChild("Class", objValue.GetClass().GetToken().ToString("X8")); |
|
||||||
info.AddChild("IsValueClass", (objValue.IsValueClass() != 0).ToString()); |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugObjectValue2) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugObjectValue2", ""); |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugBoxValue) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugBoxValue", ""); |
|
||||||
ICorDebugBoxValue boxValue = (ICorDebugBoxValue)corValue; |
|
||||||
info.AddChild("Object", "", p => GetDebugInfo(p, appDomain, boxValue.GetObject())); |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugStringValue) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugStringValue", ""); |
|
||||||
ICorDebugStringValue stringValue = (ICorDebugStringValue)corValue; |
|
||||||
info.AddChild("Length", stringValue.GetLength().ToString()); |
|
||||||
info.AddChild("String", stringValue.GetString()); |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugArrayValue) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugArrayValue", ""); |
|
||||||
info.AddChild("...", "..."); |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
if (corValue is ICorDebugHandleValue) { |
|
||||||
InfoNode info = new InfoNode(parent, "ICorDebugHandleValue", ""); |
|
||||||
ICorDebugHandleValue handleValue = (ICorDebugHandleValue)corValue; |
|
||||||
info.AddChild("HandleType", handleValue.GetHandleType().ToString()); |
|
||||||
items.Add(info); |
|
||||||
} |
|
||||||
|
|
||||||
return items; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,32 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using Debugger.AddIn.Visualizers.Utils; |
|
||||||
using Debugger.MetaData; |
|
||||||
using ICSharpCode.NRefactory.Ast; |
|
||||||
using ICSharpCode.SharpDevelop.Debugging; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.TreeModel |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// IEnumerable node in the variable tree.
|
|
||||||
/// </summary>
|
|
||||||
public class IEnumerableNode : TreeNode |
|
||||||
{ |
|
||||||
Expression targetObject; |
|
||||||
Expression debugListExpression; |
|
||||||
|
|
||||||
public IEnumerableNode(TreeNode parent, Expression targetObject, DebugType itemType) |
|
||||||
: base(parent) |
|
||||||
{ |
|
||||||
this.targetObject = targetObject; |
|
||||||
|
|
||||||
this.Name = "IEnumerable"; |
|
||||||
this.Text = "Expanding will enumerate the IEnumerable"; |
|
||||||
DebugType debugListType; |
|
||||||
this.debugListExpression = DebuggerHelpers.CreateDebugListExpression(targetObject, itemType, out debugListType); |
|
||||||
this.childNodes = Utils.LazyGetItemsOfIList(this, this.debugListExpression); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,33 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using Debugger.AddIn.Visualizers.Utils; |
|
||||||
using ICSharpCode.NRefactory.Ast; |
|
||||||
using System.Collections; |
|
||||||
using System.Collections.Generic; |
|
||||||
using Debugger.MetaData; |
|
||||||
using ICSharpCode.SharpDevelop.Debugging; |
|
||||||
using ICSharpCode.SharpDevelop.Services; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.TreeModel |
|
||||||
{ |
|
||||||
public class IListNode : TreeNode |
|
||||||
{ |
|
||||||
Expression targetList; |
|
||||||
int listCount; |
|
||||||
|
|
||||||
public IListNode(TreeNode parent, Expression targetListObject) |
|
||||||
: base(parent) |
|
||||||
{ |
|
||||||
this.targetList = targetListObject; |
|
||||||
|
|
||||||
this.Name = "IList"; |
|
||||||
this.listCount = this.targetList.GetIListCount(); |
|
||||||
this.childNodes = Utils.LazyGetItemsOfIList(this, this.targetList); |
|
||||||
} |
|
||||||
|
|
||||||
public override bool HasChildNodes { |
|
||||||
get { return this.listCount > 0; } |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,12 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
namespace Debugger.AddIn.TreeModel |
|
||||||
{ |
|
||||||
public interface ISetText |
|
||||||
{ |
|
||||||
bool CanSetText { get; } |
|
||||||
|
|
||||||
bool SetText(string text); |
|
||||||
} |
|
||||||
} |
|
@ -1,31 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using ICSharpCode.SharpDevelop; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.TreeModel |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Description of SavedTreeNode.
|
|
||||||
/// </summary>
|
|
||||||
public class SavedTreeNode : TreeNode |
|
||||||
{ |
|
||||||
public override bool CanSetText { |
|
||||||
get { return true; } |
|
||||||
} |
|
||||||
|
|
||||||
public SavedTreeNode(IImage image, string fullname, string text) |
|
||||||
: base(null) |
|
||||||
{ |
|
||||||
base.IconImage = image; |
|
||||||
FullName = fullname; |
|
||||||
Text = text; |
|
||||||
} |
|
||||||
|
|
||||||
public override bool SetText(string newValue) { |
|
||||||
Text = newValue; |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,16 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.Visualizers |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Can provide individial items for a lazy collection, as well as total count of items.
|
|
||||||
/// </summary>
|
|
||||||
public interface IListValuesProvider<T> |
|
||||||
{ |
|
||||||
int GetCount(); |
|
||||||
T GetItemAt(int index); |
|
||||||
} |
|
||||||
} |
|
@ -1,85 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using Debugger.AddIn.Visualizers.Utils; |
|
||||||
using Debugger.MetaData; |
|
||||||
using ICSharpCode.NRefactory.Ast; |
|
||||||
using ICSharpCode.SharpDevelop.Services; |
|
||||||
using System.Reflection; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.Visualizers.GridVisualizer |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Item of a collection in the debugee, with lazy evaluated properties.
|
|
||||||
/// </summary>
|
|
||||||
public class ObjectValue |
|
||||||
{ |
|
||||||
/// <summary> Index of this item in the collection. </summary>
|
|
||||||
public int Index { get; private set; } |
|
||||||
|
|
||||||
// PermanentReference for one row.
|
|
||||||
public Value PermanentReference { get; private set; } |
|
||||||
|
|
||||||
private Dictionary<string, ObjectProperty> properties = new Dictionary<string, ObjectProperty>(); |
|
||||||
|
|
||||||
/// <summary> Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members </summary>
|
|
||||||
private Dictionary<string, MemberInfo> memberForNameMap; |
|
||||||
|
|
||||||
internal ObjectValue(int index, Dictionary<string, MemberInfo> memberFromNameMap) |
|
||||||
{ |
|
||||||
this.Index = index; |
|
||||||
this.memberForNameMap = memberFromNameMap; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns property with given name.
|
|
||||||
/// </summary>
|
|
||||||
public ObjectProperty this[string propertyName] |
|
||||||
{ |
|
||||||
get |
|
||||||
{ |
|
||||||
ObjectProperty property; |
|
||||||
// has property with name 'propertyName' already been evaluated?
|
|
||||||
if(!this.properties.TryGetValue(propertyName, out property)) |
|
||||||
{ |
|
||||||
if (this.PermanentReference == null) { |
|
||||||
throw new DebuggerVisualizerException("Cannot get member of this ObjectValue - ObjectValue.PermanentReference is null"); |
|
||||||
} |
|
||||||
MemberInfo memberInfo = this.memberForNameMap.GetValue(propertyName); |
|
||||||
if (memberInfo == null) { |
|
||||||
throw new DebuggerVisualizerException("Cannot get member value - no member found with name " + propertyName); |
|
||||||
} |
|
||||||
property = CreatePropertyFromValue(propertyName, this.PermanentReference.GetMemberValue(memberInfo)); |
|
||||||
this.properties.Add(propertyName, property); |
|
||||||
} |
|
||||||
return property; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static ObjectValue Create(Debugger.Value value, int index, Dictionary<string, MemberInfo> memberFromName) |
|
||||||
{ |
|
||||||
ObjectValue result = new ObjectValue(index, memberFromName); |
|
||||||
|
|
||||||
// remember PermanentReference for expanding IEnumerable
|
|
||||||
Value permanentReference = value.GetPermanentReference(); |
|
||||||
result.PermanentReference = permanentReference; |
|
||||||
|
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
private static ObjectProperty CreatePropertyFromValue(string propertyName, Value value) |
|
||||||
{ |
|
||||||
ObjectProperty property = new ObjectProperty(); |
|
||||||
property.Name = propertyName; |
|
||||||
// property.Expression = ?.Age
|
|
||||||
// - cannot use expression,
|
|
||||||
// if the value is returned from an enumerator, it has no meaningful expression
|
|
||||||
property.IsAtomic = value.Type.IsPrimitive; |
|
||||||
property.IsNull = value.IsNull; |
|
||||||
property.Value = value.IsNull ? "" : value.InvokeToString(); |
|
||||||
return property; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,50 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections; |
|
||||||
using System.Collections.Generic; |
|
||||||
|
|
||||||
using Debugger.AddIn.Visualizers.Utils; |
|
||||||
using Debugger.MetaData; |
|
||||||
using ICSharpCode.Core; |
|
||||||
using ICSharpCode.NRefactory.Ast; |
|
||||||
using ICSharpCode.SharpDevelop.Services; |
|
||||||
using System.Reflection; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.Visualizers.GridVisualizer |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Provides <see cref="ObjectValue"/>s for debugee objects implementing IEnumerable.
|
|
||||||
/// </summary>
|
|
||||||
/*public class EnumerableValuesProvider : GridValuesProvider |
|
||||||
{ |
|
||||||
public EnumerableValuesProvider(Expression targetObject, DebugType iEnumerableType, DebugType itemType) |
|
||||||
:base(targetObject, iEnumerableType, itemType) |
|
||||||
{ |
|
||||||
this.itemsSource = enumerateItems(); |
|
||||||
} |
|
||||||
|
|
||||||
private IEnumerable<ObjectValue> itemsSource; |
|
||||||
public IEnumerable<ObjectValue> ItemsSource |
|
||||||
{ |
|
||||||
get { return this.itemsSource; } |
|
||||||
} |
|
||||||
|
|
||||||
private IEnumerable<ObjectValue> enumerateItems() |
|
||||||
{ |
|
||||||
MethodInfo enumeratorMethod = collectionType.GetMethod("GetEnumerator"); |
|
||||||
Value enumerator = targetObject.Evaluate(WindowsDebugger.CurrentProcess).InvokeMethod(enumeratorMethod, null).GetPermanentReference(); |
|
||||||
|
|
||||||
MethodInfo moveNextMethod = enumerator.Type.GetMethod("MoveNext"); |
|
||||||
PropertyInfo currentproperty = enumerator.Type.GetInterface(typeof(IEnumerator).FullName).GetProperty("Current"); |
|
||||||
|
|
||||||
int index = 0; |
|
||||||
while ((bool)enumerator.InvokeMethod(moveNextMethod, null).PrimitiveValue) |
|
||||||
{ |
|
||||||
Value currentValue = enumerator.GetPropertyValue(currentproperty); |
|
||||||
yield return ObjectValue.Create(currentValue, index++, this.memberFromNameMap); |
|
||||||
} |
|
||||||
} |
|
||||||
}*/ |
|
||||||
} |
|
@ -1,42 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using Debugger.AddIn.Visualizers.Utils; |
|
||||||
using Debugger.MetaData; |
|
||||||
using ICSharpCode.NRefactory.Ast; |
|
||||||
using System.Reflection; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.Visualizers.GridVisualizer |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Provides <see cref="ObjectValue"/>s to be displayed in Grid visualizer.
|
|
||||||
/// Descandants implement getting values for IList and IEnumerable.
|
|
||||||
/// </summary>
|
|
||||||
public class GridValuesProvider |
|
||||||
{ |
|
||||||
/// <summary> Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members </summary>
|
|
||||||
protected Dictionary<string, MemberInfo> memberFromNameMap; |
|
||||||
|
|
||||||
protected Expression targetObject; |
|
||||||
protected DebugType itemType; |
|
||||||
|
|
||||||
public GridValuesProvider(Expression targetObject, DebugType itemType) |
|
||||||
{ |
|
||||||
this.targetObject = targetObject; |
|
||||||
this.itemType = itemType; |
|
||||||
|
|
||||||
this.memberFromNameMap = this.GetItemTypeMembers().MakeDictionary(memberInfo => memberInfo.Name); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets members that will be displayed as columns.
|
|
||||||
/// </summary>
|
|
||||||
public IList<MemberInfo> GetItemTypeMembers() |
|
||||||
{ |
|
||||||
var publicPropetiesAndFields = itemType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance); |
|
||||||
return publicPropetiesAndFields; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,59 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Linq; |
|
||||||
using System.Reflection; |
|
||||||
using Debugger.AddIn.Visualizers.Utils; |
|
||||||
using Debugger.MetaData; |
|
||||||
using ICSharpCode.Core; |
|
||||||
using ICSharpCode.NRefactory.Ast; |
|
||||||
using ICSharpCode.SharpDevelop.Services; |
|
||||||
|
|
||||||
namespace Debugger.AddIn.Visualizers.GridVisualizer |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Provides <see cref="ObjectValue"/>s for debugee objects implementing IList.
|
|
||||||
/// </summary>
|
|
||||||
public class ListValuesProvider : GridValuesProvider, IListValuesProvider<ObjectValue> |
|
||||||
{ |
|
||||||
int? listCount = null; |
|
||||||
/// <summary>
|
|
||||||
/// After evaluating how many items to clear debugger Expression cache,
|
|
||||||
/// so that the cache does not keep too many PermanentReferences.
|
|
||||||
/// </summary>
|
|
||||||
static readonly int ClearCacheThreshold = 50; |
|
||||||
|
|
||||||
public ListValuesProvider(Expression targetObject, DebugType listItemType) |
|
||||||
:base(targetObject, listItemType) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
public int GetCount() |
|
||||||
{ |
|
||||||
if (this.listCount == null) { |
|
||||||
this.listCount = this.targetObject.GetIListCount(); |
|
||||||
} |
|
||||||
return this.listCount.Value; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>When this reaches ClearCacheThreshold, the debugger Expression cache is cleared.</summary>
|
|
||||||
int itemClearCacheCounter = 0; |
|
||||||
|
|
||||||
public ObjectValue GetItemAt(int index) |
|
||||||
{ |
|
||||||
if (itemClearCacheCounter++ > ClearCacheThreshold) { |
|
||||||
// clear debugger Expression cache to avoid holding too many PermanentReferences
|
|
||||||
WindowsDebugger.CurrentProcess.ClearExpressionCache(); |
|
||||||
LoggingService.Info("Cleared debugger Expression cache."); |
|
||||||
itemClearCacheCounter = 0; |
|
||||||
} |
|
||||||
return ObjectValue.Create( |
|
||||||
targetObject.AppendIndexer(index).Evaluate(WindowsDebugger.CurrentProcess), |
|
||||||
//targetObject.AppendIndexer(index), // use Expression instead of value - possible only for IList though
|
|
||||||
index, |
|
||||||
this.memberFromNameMap); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,12 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
|
|
||||||
|
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Linq; |
|
||||||
using System; |
|
||||||
|
|
||||||
public enum TextVisualizerMode |
|
||||||
{ |
|
||||||
PlainText, |
|
||||||
Xml |
|
||||||
} |
|
Loading…
Reference in new issue