diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
index 6f3c568f27..7858f8536c 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
@@ -121,7 +121,16 @@
DebuggerEventForm.cs
+
+
+
+
+
+
+
+
+
DebuggeeExceptionForm.cs
@@ -167,7 +176,6 @@
-
@@ -195,11 +203,9 @@
-
-
-
+
@@ -309,9 +315,11 @@
+
+
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/DebuggerVisualizerException.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Common/DebuggerVisualizerException.cs
similarity index 94%
rename from src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/DebuggerVisualizerException.cs
rename to src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Common/DebuggerVisualizerException.cs
index cc86d867f2..b1a7efb017 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/DebuggerVisualizerException.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Common/DebuggerVisualizerException.cs
@@ -6,7 +6,7 @@
//
using System;
-namespace Debugger.AddIn.Visualizers.Graph
+namespace Debugger.AddIn.Visualizers
{
///
/// Description of DebuggerVisualizerException.
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Common/IEvaluate.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Common/IEvaluate.cs
new file mode 100644
index 0000000000..bcccf43ac6
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Common/IEvaluate.cs
@@ -0,0 +1,27 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+
+namespace Debugger.AddIn.Visualizers
+{
+ ///
+ /// Object that has its state partially uninitialized,
+ /// and can initialize its state fully on demand.
+ ///
+ public interface IEvaluate
+ {
+ ///
+ /// On-demand evaluation of internal state.
+ ///
+ void Evaluate();
+
+ ///
+ /// Is this object fully evaluated?
+ ///
+ bool IsEvaluated { get; }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Common/ObjectPropertyComparer.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Common/ObjectPropertyComparer.cs
new file mode 100644
index 0000000000..e3fb83d9f8
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Common/ObjectPropertyComparer.cs
@@ -0,0 +1,31 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+
+namespace Debugger.AddIn.Visualizers.Common
+{
+ ///
+ /// Provides sort ordering on ObjectProperties.
+ ///
+ class ObjectPropertyComparer : IComparer
+ {
+ public int Compare(ObjectProperty prop1, ObjectProperty prop2)
+ {
+ // order by IsAtomic, Name
+ int comparedAtomic = prop2.IsAtomic.CompareTo(prop1.IsAtomic);
+ if (comparedAtomic != 0)
+ {
+ return comparedAtomic;
+ }
+ else
+ {
+ return prop1.Name.CompareTo(prop2.Name);
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedEdge.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedEdge.cs
index 481801c3a1..6327cadcb4 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedEdge.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedEdge.cs
@@ -4,6 +4,7 @@
//
// $Revision$
//
+using Debugger.AddIn.Visualizers.Utils;
using System;
using System.Collections.Generic;
using System.Windows;
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs
index 35f5d63f93..5ce5b17f24 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs
@@ -16,11 +16,11 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
///
public class PositionedNode
{
- private ObjectNode objectNode;
+ private ObjectGraphNode objectNode;
///
/// Underlying ObjectNode.
///
- public ObjectNode ObjectNode
+ public ObjectGraphNode ObjectNode
{
get { return objectNode; }
}
@@ -51,7 +51,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
/// Creates new PositionedNode.
///
/// Underlying ObjectNode.
- public PositionedNode(ObjectNode objectNode)
+ public PositionedNode(ObjectGraphNode objectNode)
{
this.objectNode = objectNode;
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs
index d2f022e550..5240da4267 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs
@@ -24,8 +24,8 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
PositionedGraph resultGraph = null;
- Dictionary treeNodeFor = new Dictionary();
- Dictionary seenNodes = new Dictionary();
+ Dictionary treeNodeFor = new Dictionary();
+ Dictionary seenNodes = new Dictionary();
public TreeLayouter()
{
@@ -41,8 +41,8 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
layoutDirection = direction;
resultGraph = new PositionedGraph();
- treeNodeFor = new Dictionary();
- seenNodes = new Dictionary();
+ treeNodeFor = new Dictionary();
+ seenNodes = new Dictionary();
TreeNode tree = buildTreeRecursive(objectGraph.Root, expandedNodes);
calculateNodePosRecursive(tree, 0, 0);
@@ -53,7 +53,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
return resultGraph;
}
- private TreeNode buildTreeRecursive(ObjectNode objectGraphNode, ExpandedNodes expandedNodes)
+ private TreeNode buildTreeRecursive(ObjectGraphNode objectGraphNode, ExpandedNodes expandedNodes)
{
seenNodes.Add(objectGraphNode, null);
@@ -64,11 +64,13 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
treeNodeFor[objectGraphNode] = newTreeNode;
double subtreeSize = 0;
- foreach (ObjectGraphProperty property in objectGraphNode.Properties)
+ foreach (AbstractNode absNode in objectGraphNode.Content.Childs)
{
+ ObjectGraphProperty property = ((PropertyNode)absNode).Property;
+
if (property.TargetNode != null)
{
- ObjectNode neighbor = property.TargetNode;
+ ObjectGraphNode neighbor = property.TargetNode;
TreeNode targetTreeNode = null;
bool newEdgeIsTreeEdge = false;
if (seenNodes.ContainsKey(neighbor))
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNode.cs
index 39a723e3a7..a43c7f6133 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNode.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNode.cs
@@ -19,7 +19,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
///
public abstract class TreeNode : PositionedNode
{
- public static TreeNode Create(LayoutDirection direction, ObjectNode objectNode)
+ public static TreeNode Create(LayoutDirection direction, ObjectGraphNode objectNode)
{
switch (direction) {
case LayoutDirection.TopBottom: return new TreeNodeTB(objectNode);
@@ -31,7 +31,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
public double HorizontalMargin { get; set; }
public double VerticalMargin { get; set; }
- protected TreeNode(ObjectNode objectNode) : base(objectNode)
+ protected TreeNode(ObjectGraphNode objectNode) : base(objectNode)
{
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeLR.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeLR.cs
index 916ea5eb4e..86ad93870c 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeLR.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeLR.cs
@@ -14,7 +14,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
///
public class TreeNodeLR: TreeNode
{
- public TreeNodeLR(ObjectNode objectNode) : base(objectNode)
+ public TreeNodeLR(ObjectGraphNode objectNode) : base(objectNode)
{
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeTB.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeTB.cs
index ce09a53ff8..d2950bac2c 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeTB.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeTB.cs
@@ -14,7 +14,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
///
public class TreeNodeTB : TreeNode
{
- public TreeNodeTB(ObjectNode objectNode) : base(objectNode)
+ public TreeNodeTB(ObjectGraphNode objectNode) : base(objectNode)
{
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/NamedEdge.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/NamedEdge.cs
index 49a5ad5ca1..95980df74a 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/NamedEdge.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/NamedEdge.cs
@@ -6,7 +6,7 @@
//
using System;
-namespace Debugger.AddIn.Visualizers.Graph
+namespace Debugger.AddIn.Visualizers
{
///
/// Named edge connecting 2 objects of same type.
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraph.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraph.cs
index a668b6aa7e..7078174e66 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraph.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraph.cs
@@ -18,22 +18,22 @@ namespace Debugger.AddIn.Visualizers.Graph
///
/// Root of the graph.
///
- public ObjectNode Root { get; internal set; }
+ public ObjectGraphNode Root { get; internal set; }
///
/// Adds node to the graph.
///
/// node to be added
- internal void AddNode(ObjectNode node)
+ internal void AddNode(ObjectGraphNode node)
{
_nodes.Add(node);
}
- private List _nodes = new List();
+ private List _nodes = new List();
///
/// All nodes in the graph.
///
- public IEnumerable Nodes
+ public IEnumerable Nodes
{
get { return _nodes; }
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs
index 8dcc6724bc..6d913edff3 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs
@@ -50,20 +50,15 @@ namespace Debugger.AddIn.Visualizers.Graph
///
public ObjectGraph ResultGraph { get { return this.resultGraph; } }
- ///
- /// System.Runtime.CompilerServices.GetHashCode method, for obtaining non-overriden hash codes from debuggee.
- ///
- private MethodInfo hashCodeMethod;
-
///
/// Given hash code, lookup already existing node(s) with this hash code.
///
- private Lookup objectNodesForHashCode = new Lookup();
+ private Lookup objectNodesForHashCode = new Lookup();
///
/// Binding flags for getting member expressions.
///
- private readonly Debugger.MetaData.BindingFlags _bindingFlags =
+ private readonly Debugger.MetaData.BindingFlags memberBindingFlags =
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Field | BindingFlags.GetProperty;
///
@@ -73,9 +68,6 @@ namespace Debugger.AddIn.Visualizers.Graph
public ObjectGraphBuilder(WindowsDebugger debuggerService)
{
this.debuggerService = debuggerService;
-
- DebugType typeRuntimeHelpers = DebugType.Create(debuggerService.DebuggedProcess, null, "System.Runtime.CompilerServices.RuntimeHelpers");
- this.hashCodeMethod = typeRuntimeHelpers.GetMember("GetHashCode", BindingFlags.Public | BindingFlags.Static | BindingFlags.Method | BindingFlags.IncludeSuperType) as MethodInfo;
}
///
@@ -97,19 +89,19 @@ namespace Debugger.AddIn.Visualizers.Graph
{
//resultGraph.Root = buildGraphRecursive(debuggerService.GetValueFromName(expression).GetPermanentReference(), expandedNodes);
resultGraph.Root = createNewNode(debuggerService.GetValueFromName(expression).GetPermanentReference());
- loadNodeProperties(resultGraph.Root);
- loadChildrenRecursive(resultGraph.Root, expandedNodes);
+ loadContent(resultGraph.Root);
+ loadNeighborsRecursive(resultGraph.Root, expandedNodes);
}
return resultGraph;
}
- public ObjectNode ObtainNodeForExpression(Expression expr, out bool createdNewNode)
+ public ObjectGraphNode ObtainNodeForExpression(Expression expr, out bool createdNewNode)
{
- return ObtainNodeForValue(getPermanentReference(expr), out createdNewNode);
+ return ObtainNodeForValue(expr.GetPermanentReference(), out createdNewNode);
}
- public ObjectNode ObtainNodeForExpression(Expression expr)
+ public ObjectGraphNode ObtainNodeForExpression(Expression expr)
{
bool createdNewNode; // ignore (caller is not interested, otherwise he would use the other overload)
return ObtainNodeForExpression(expr, out createdNewNode);
@@ -120,62 +112,67 @@ namespace Debugger.AddIn.Visualizers.Graph
///
/// Value for which to obtain the node/
/// True if new node was created, false if existing node was returned.
- public ObjectNode ObtainNodeForValue(Value value, out bool createdNew)
+ public ObjectGraphNode ObtainNodeForValue(Value value, out bool createdNew)
{
createdNew = false;
- ObjectNode nodeForValue = getExistingNodeForValue(value);
+ ObjectGraphNode nodeForValue = getExistingNodeForValue(value);
if (nodeForValue == null)
{
// if no node for memberValue exists, create it
nodeForValue = createNewNode(value);
- loadNodeProperties(nodeForValue);
+ loadContent(nodeForValue);
createdNew = true;
}
return nodeForValue;
}
///
- /// Fills node contents by adding properties.
+ /// Fills node Content property tree.
///
///
- private void loadNodeProperties(ObjectNode thisNode)
+ private void loadContent(ObjectGraphNode thisNode)
{
+ NestedNode contentRoot = new NestedNode(NestedNodeType.ThisNode);
+ thisNode.Content = contentRoot;
+
// take all properties for this value (type = value's real type)
- foreach(Expression memberExpr in thisNode.PermanentReference.Expression.AppendObjectMembers(thisNode.PermanentReference.Type, _bindingFlags))
+ foreach(Expression memberExpr in thisNode.PermanentReference.Expression.AppendObjectMembers(thisNode.PermanentReference.Type, this.memberBindingFlags))
{
checkIsOfSupportedType(memberExpr);
string memberName = memberExpr.CodeTail;
- if (isOfAtomicType(memberExpr))
+ if (memberExpr.IsOfAtomicType())
{
- // atomic members are added to the list of node's "properties"
- string memberValueAsString = memberExpr.Evaluate(debuggerService.DebuggedProcess).AsString;
- thisNode.AddAtomicProperty(memberName, memberValueAsString, memberExpr);
+ // properties are now lazy-evaluated
+ // string memberValueAsString = memberExpr.Evaluate(debuggerService.DebuggedProcess).InvokeToString();
+ AddAtomicPropertyChild(contentRoot, memberName, memberExpr);
}
else
{
- // for object members, complex properties are added
- ObjectNode targetNode = null;
- bool memberIsNull = isNull(memberExpr);
- thisNode.AddComplexProperty(memberName, "", memberExpr, targetNode, memberIsNull);
+ ObjectGraphNode targetNode = null;
+ bool memberIsNull = memberExpr.IsNull();
+ AddComplexPropertyChild(contentRoot, memberName, memberExpr, targetNode, memberIsNull);
}
}
}
///
- /// Creates child nodes of this node for each complex property and connects them to property.TargetNode.
+ /// For each complex property of this node, create s neighbor graph node if needed and connects the neighbor to ObjectProperty.TargetNode.
///
///
///
- private void loadChildrenRecursive(ObjectNode thisNode, ExpandedNodes expandedNodes)
+ private void loadNeighborsRecursive(ObjectGraphNode thisNode, ExpandedNodes expandedNodes)
{
foreach(ObjectGraphProperty complexProperty in thisNode.ComplexProperties)
{
Expression memberExpr = complexProperty.Expression;
- ObjectNode targetNode = null;
+ ObjectGraphNode targetNode = null;
+ // we are only evaluating expanded nodes here
+ // (we have to do this to know the "shape" of the graph)
+ // property laziness makes sense, as we are not evaluating atomic and non-expanded properties out of user's view
if (!complexProperty.IsNull && expandedNodes.IsExpanded(memberExpr.Code))
{
- Value memberValue = getPermanentReference(memberExpr);
+ Value memberValue = memberExpr.GetPermanentReference();
bool createdNew;
// get existing node (loop) or create new
@@ -183,7 +180,7 @@ namespace Debugger.AddIn.Visualizers.Graph
if (createdNew)
{
// if member node is new, recursively build its subtree
- loadChildrenRecursive(targetNode, expandedNodes);
+ loadNeighborsRecursive(targetNode, expandedNodes);
}
}
else
@@ -199,10 +196,10 @@ namespace Debugger.AddIn.Visualizers.Graph
///
/// Value, has to be valid.
/// New empty object node representing the value.
- private ObjectNode createNewNode(Value permanentReference)
+ private ObjectGraphNode createNewNode(Value permanentReference)
{
- ObjectNode newNode = new ObjectNode();
- newNode.HashCode = invokeGetHashCode(permanentReference);
+ ObjectGraphNode newNode = new ObjectGraphNode();
+ newNode.HashCode = permanentReference.InvokeDefaultGetHashCode();
resultGraph.AddNode(newNode);
// remember this node's hashcode for quick lookup
@@ -220,11 +217,11 @@ namespace Debugger.AddIn.Visualizers.Graph
///
/// Valid value representing an instance.
///
- private ObjectNode getExistingNodeForValue(Value value)
+ private ObjectGraphNode getExistingNodeForValue(Value value)
{
- int objectHashCode = invokeGetHashCode(value);
+ int objectHashCode = value.InvokeDefaultGetHashCode();
// are there any nodes with the same hash code?
- LookupValueCollection nodesWithSameHashCode = objectNodesForHashCode[objectHashCode];
+ LookupValueCollection nodesWithSameHashCode = objectNodesForHashCode[objectHashCode];
if (nodesWithSameHashCode == null)
{
return null;
@@ -234,28 +231,30 @@ namespace Debugger.AddIn.Visualizers.Graph
// if there is a node with same hash code, check if it has also the same address
// (hash codes are not uniqe - http://stackoverflow.com/questions/750947/-net-unique-object-identifier)
ulong objectAddress = value.GetObjectAddress();
- ObjectNode nodeWithSameAddress = nodesWithSameHashCode.Find(
+ ObjectGraphNode nodeWithSameAddress = nodesWithSameHashCode.Find(
node => { return node.PermanentReference.GetObjectAddress() == objectAddress; } );
return nodeWithSameAddress;
}
}
///
- /// Invokes GetHashCode on given value.
+ /// Adds primitive property.
///
- /// Valid value.
- /// Hash code of the object in the debugee.
- private int invokeGetHashCode(Value value)
+ public void AddAtomicPropertyChild(NestedNode node, string name, Expression expression)
{
- // David: I had hard time finding out how to invoke static method
- // value.InvokeMethod is nice for instance methods.
- // what about MethodInfo.Invoke() ?
- // also, there could be an overload that takes 1 parameter instead of array
- string defaultHashCode = Eval.InvokeMethod(this.hashCodeMethod, null, new Value[]{value}).AsString;
-
- //MethodInfo method = value.Type.GetMember("GetHashCode", BindingFlags.Method | BindingFlags.IncludeSuperType) as MethodInfo;
- //string hashCode = value.InvokeMethod(method, null).AsString;
- return int.Parse(defaultHashCode);
+ // add child with no value (will be lazy-evaluated later)
+ node.AddChild(new PropertyNode(new ObjectGraphProperty
+ { Name = name, Value = "", Expression = expression, IsAtomic = true, TargetNode = null }));
+ }
+
+ ///
+ /// Adds complex property.
+ ///
+ public void AddComplexPropertyChild(NestedNode node, string name, Expression expression, ObjectGraphNode targetNode, bool isNull)
+ {
+ // add child with no value (will be lazy-evaluated later)
+ node.AddChild(new PropertyNode(new ObjectGraphProperty
+ { Name = name, Value = "", Expression = expression, IsAtomic = false, TargetNode = targetNode, IsNull = isNull }));
}
///
@@ -271,41 +270,5 @@ namespace Debugger.AddIn.Visualizers.Graph
throw new DebuggerVisualizerException("Arrays are not supported yet");
}
}
-
- ///
- /// Checks whether given expression's type is atomic.
- ///
- /// Expression.
- /// True if expression's type is atomic, False otherwise.
- private bool isOfAtomicType(Expression expr)
- {
- DebugType typeOfValue = expr.Evaluate(debuggerService.DebuggedProcess).Type;
- return !(typeOfValue.IsClass || typeOfValue.IsValueType);
- //return (!typeOfValue.IsClass) || typeOfValue.IsString;
- }
-
- #region Expression helpers
-
- private Value getPermanentReference(Expression expr)
- {
- return expr.Evaluate(debuggerService.DebuggedProcess).GetPermanentReference();
- }
-
- private bool isNull(Expression expr)
- {
- return expr.Evaluate(debuggerService.DebuggedProcess).IsNull;
- }
-
- private DebugType getType(Expression expr)
- {
- return expr.Evaluate(debuggerService.DebuggedProcess).Type;
- }
-
- private ulong getObjectAddress(Expression expr)
- {
- return expr.Evaluate(debuggerService.DebuggedProcess).GetObjectAddress();
- }
-
- #endregion
}
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphNode.cs
new file mode 100644
index 0000000000..372cec5c7c
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphNode.cs
@@ -0,0 +1,59 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Debugger.Expressions;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Node in the .
+ ///
+ public class ObjectGraphNode
+ {
+ ///
+ /// Permanent reference to the value in the the debugee this node represents.
+ ///
+ internal Debugger.Value PermanentReference { get; set; } // needed for graph building and matching, since hashCodes are not unique
+ ///
+ /// Hash code in the debuggee of the DebuggerValue this node represents.
+ ///
+ internal int HashCode { get; set; }
+ ///
+ /// Expression used to obtain this node.
+ ///
+ public Expressions.Expression Expression { get { return this.PermanentReference.Expression; } }
+
+ ///
+ /// Property tree of this node.
+ ///
+ public NestedNode Content
+ {
+ get; set;
+ }
+
+ // TODO just for ObjectGraphBuilder, remove
+ ///
+ /// Only complex properties filtered out of
+ ///
+ public IEnumerable ComplexProperties
+ {
+ get
+ {
+ if (this.Content == null)
+ throw new InvalidOperationException("Cannot enumerate properties, Content is null");
+
+ foreach (var child in this.Content.Childs)
+ {
+ if (child is PropertyNode && !(((PropertyNode)child).Property.IsAtomic))
+ yield return ((PropertyNode)child).Property;
+ }
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs
index 9224ce40b1..af68e6ff10 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs
@@ -18,6 +18,6 @@ namespace Debugger.AddIn.Visualizers.Graph
///
/// Node that this property points to. Can be null. Always null if is true.
///
- public ObjectNode TargetNode { get; set; }
+ public ObjectGraphNode TargetNode { get; set; }
}
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectNode.cs
deleted file mode 100644
index dfb92a4f19..0000000000
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectNode.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-//
-//
-//
-// $Revision$
-//
-using System;
-using System.Collections.Generic;
-using System.Text;
-using Debugger.Expressions;
-
-namespace Debugger.AddIn.Visualizers.Graph
-{
- ///
- /// Node in the .
- ///
- public class ObjectNode
- {
- ///
- /// Permanent reference to the value in the the debugee this node represents.
- ///
- internal Debugger.Value PermanentReference { get; set; } // needed for graph building and matching, since hashCodes are not unique
- ///
- /// Hash code in the debuggee of the DebuggerValue this node represents.
- ///
- internal int HashCode { get; set; }
- ///
- /// Expression used to obtain this node.
- ///
- public Expressions.Expression Expression { get { return this.PermanentReference.Expression; } }
-
- class PropertyComparer : IComparer
- {
- public int Compare(ObjectGraphProperty prop1, ObjectGraphProperty prop2)
- {
- // order by IsAtomic, Name
- int comparedAtomic = prop2.IsAtomic.CompareTo(prop1.IsAtomic);
- if (comparedAtomic != 0)
- {
- return comparedAtomic;
- }
- else
- {
- return prop1.Name.CompareTo(prop2.Name);
- }
- }
- }
-
- private static PropertyComparer propertySortComparer = new PropertyComparer();
-
- private bool sorted = false;
-
- private List properties = new List();
- ///
- /// Properties (either atomic or complex) of the object this node represents.
- ///
- public List Properties
- {
- get
- {
- if (!sorted)
- {
- properties.Sort(propertySortComparer);
- sorted = true;
- }
- return properties;
- }
- }
- ///
- /// Only complex properties filtered out of
- ///
- public IEnumerable ComplexProperties
- {
- get
- {
- foreach (var property in Properties)
- {
- if (!property.IsAtomic)
- yield return property;
- }
- }
- }
-
- ///
- /// Adds primitive property.
- ///
- internal void AddAtomicProperty(string name, string value, Expression expression)
- {
- properties.Add(new ObjectGraphProperty
- { Name = name, Value = value, Expression = expression, IsAtomic = true, TargetNode = null });
- }
-
- ///
- /// Adds complex property.
- ///
- internal void AddComplexProperty(string name, string value, Expression expression, ObjectNode targetNode, bool isNull)
- {
- properties.Add(new ObjectGraphProperty
- { Name = name, Value = value, Expression = expression, IsAtomic = false, TargetNode = targetNode, IsNull = isNull });
- }
- }
-}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectEdge.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/AbstractNode.cs
similarity index 58%
rename from src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectEdge.cs
rename to src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/AbstractNode.cs
index 2363b0f37f..d6e9d5c8fa 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectEdge.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/AbstractNode.cs
@@ -5,15 +5,18 @@
// $Revision$
//
using System;
-using System.Collections.Generic;
-using System.Text;
namespace Debugger.AddIn.Visualizers.Graph
{
- ///
- /// Named edge in the .
- ///
- /*public class ObjectEdge : NamedEdge
- {
- }*/
+ ///
+ /// Description of AbstractNode.
+ ///
+ public class AbstractNode
+ {
+
+
+ public AbstractNode()
+ {
+ }
+ }
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/NestedNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/NestedNode.cs
new file mode 100644
index 0000000000..e8388a84a5
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/NestedNode.cs
@@ -0,0 +1,44 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Description of NestedNode.
+ ///
+ public class NestedNode : AbstractNode
+ {
+ private List childs = new List();
+
+ private NestedNodeType nodeType;
+ public NestedNodeType NodeType
+ {
+ get { return nodeType; }
+ }
+
+ public IEnumerable Childs
+ {
+ get
+ {
+ foreach (var child in childs)
+ yield return child;
+ }
+ }
+
+ public void AddChild(AbstractNode child)
+ {
+ this.childs.Add(child);
+ }
+
+ public NestedNode(NestedNodeType nodeType)
+ {
+ this.nodeType = nodeType;
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/NestedNodeType.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/NestedNodeType.cs
new file mode 100644
index 0000000000..68c327e2c2
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/NestedNodeType.cs
@@ -0,0 +1,22 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Description of NestedNodeType.
+ ///
+ public enum NestedNodeType
+ {
+ ThisNode,
+ BaseClassNode,
+ NonPublicInstanceMembersNode,
+ StaticMembersNode,
+ NonPublicStaticMembersNode
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/PropertyNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/PropertyNode.cs
new file mode 100644
index 0000000000..29170c9cea
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/PropertyNode.cs
@@ -0,0 +1,53 @@
+//
+//
+//
+//
+// $Revision$
+//
+using ICSharpCode.SharpDevelop.Services;
+using System;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Node containing ObjectGraphProperty, with lazy evaluation.
+ ///
+ public class PropertyNode : AbstractNode, IEvaluate
+ {
+ public PropertyNode(ObjectGraphProperty objectGraphProperty)
+ {
+ if (objectGraphProperty == null)
+ throw new ArgumentNullException("objectGraphProperty");
+
+ this.property = objectGraphProperty;
+ }
+
+ private ObjectGraphProperty property;
+ public ObjectGraphProperty Property
+ {
+ get { return this.property; }
+ }
+
+ #region IEvaluate members
+
+ bool evaluateCalled = false;
+ public bool IsEvaluated
+ {
+ get { return this.evaluateCalled; }
+ }
+
+ public void Evaluate()
+ {
+ if (this.Property.Expression == null)
+ {
+ throw new DebuggerVisualizerException("Cannot evaluate property with missing Expression");
+ }
+ this.Property.Value =
+ this.Property.Expression.Evaluate(WindowsDebugger.CurrentProcess).InvokeToString();
+
+ this.evaluateCalled = true;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/AtomicType.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/AtomicType.cs
new file mode 100644
index 0000000000..527c4b568e
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/AtomicType.cs
@@ -0,0 +1,30 @@
+//
+//
+//
+//
+// $Revision$
+//
+using Debugger.MetaData;
+using System;
+using Debugger.Expressions;
+using ICSharpCode.SharpDevelop.Services;
+
+namespace Debugger.AddIn.Visualizers.Utils
+{
+ ///
+ /// Atomic type is a type that "cannot be expanded".
+ ///
+ public static class AtomicType
+ {
+ ///
+ /// Checks whether given expression's type is atomic.
+ ///
+ /// Expression.
+ /// True if expression's type is atomic, False otherwise.
+ public static bool IsOfAtomicType(this Expression expr)
+ {
+ DebugType typeOfValue = expr.Evaluate(WindowsDebugger.CurrentProcess).Type;
+ return !(typeOfValue.IsClass || typeOfValue.IsValueType /* = struct in C# */);
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs
index 9d426c2aa9..ebffc7abae 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs
@@ -4,8 +4,11 @@
//
// $Revision$
//
+using Debugger.Expressions;
using System;
+using Debugger.MetaData;
using Debugger.Wrappers.CorDebug;
+using ICSharpCode.SharpDevelop.Services;
namespace Debugger.AddIn.Visualizers.Utils
{
@@ -19,5 +22,61 @@ namespace Debugger.AddIn.Visualizers.Utils
ICorDebugReferenceValue refVal = val.CorValue.CastTo();
return refVal.Value;
}
+
+ ///
+ /// Evaluates expression and gets underlying address of object in the debuggee.
+ ///
+ public static ulong GetObjectAddress(this Expression expr)
+ {
+ return expr.Evaluate(WindowsDebugger.CurrentProcess).GetObjectAddress();
+ }
+
+ ///
+ /// System.Runtime.CompilerServices.GetHashCode method, for obtaining non-overriden hash codes from debuggee.
+ ///
+ private static MethodInfo hashCodeMethod;
+
+ ///
+ /// Invokes RuntimeHelpers.GetHashCode on given value, that is a default hashCode ignoring user overrides.
+ ///
+ /// Valid value.
+ /// Hash code of the object in the debugee.
+ public static int InvokeDefaultGetHashCode(this Value value)
+ {
+ if (DebuggerHelpers.hashCodeMethod == null)
+ {
+ DebugType typeRuntimeHelpers = DebugType.Create(WindowsDebugger.CurrentProcess, null, "System.Runtime.CompilerServices.RuntimeHelpers");
+ DebuggerHelpers.hashCodeMethod = typeRuntimeHelpers.GetMember("GetHashCode", BindingFlags.Public | BindingFlags.Static | BindingFlags.Method | BindingFlags.IncludeSuperType) as MethodInfo;
+ if (DebuggerHelpers.hashCodeMethod == null)
+ {
+ throw new DebuggerException("Cannot obtain method System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode");
+ }
+ }
+
+ // David: I had hard time finding out how to invoke static method.
+ // value.InvokeMethod is nice for instance methods.
+ // what about MethodInfo.Invoke() ?
+ // also, there could be an overload that takes 1 parameter instead of array
+ string defaultHashCode = Eval.InvokeMethod(DebuggerHelpers.hashCodeMethod, null, new Value[]{value}).AsString;
+
+ //MethodInfo method = value.Type.GetMember("GetHashCode", BindingFlags.Method | BindingFlags.IncludeSuperType) as MethodInfo;
+ //string hashCode = value.InvokeMethod(method, null).AsString;
+ return int.Parse(defaultHashCode);
+ }
+
+ public static Value GetPermanentReference(this Expression expr)
+ {
+ return expr.Evaluate(WindowsDebugger.CurrentProcess).GetPermanentReference();
+ }
+
+ public static bool IsNull(this Expression expr)
+ {
+ return expr.Evaluate(WindowsDebugger.CurrentProcess).IsNull;
+ }
+
+ public static DebugType GetType(this Expression expr)
+ {
+ return expr.Evaluate(WindowsDebugger.CurrentProcess).Type;
+ }
}
}