void AddRawViewNode(AbstractNode contentRoot, ObjectGraphNode thisNode) { var rawViewNode = new RawViewNode(); contentRoot.AddChild(rawViewNode); LoadNodeObjectContent(rawViewNode, thisNode.Expression, thisNode.PermanentReference.Type); }
/// <summary> /// Creates new node for the value. /// </summary> /// <param name="permanentReference">Value, has to be valid.</param> /// <returns>New empty object node representing the value.</returns> private ObjectGraphNode createNewNode(Value permanentReference, GraphExpression expression) { if (permanentReference == null) { throw new ArgumentNullException("permanentReference"); } ObjectGraphNode newNode = new ObjectGraphNode(); if (permanentReference.Type != null) { newNode.TypeName = permanentReference.Type.FormatNameCSharp(); } newNode.HashCode = permanentReference.InvokeDefaultGetHashCode(); resultGraph.AddNode(newNode); // remember this node's hashcode for quick lookup objectNodesForHashCode.Add(newNode.HashCode, newNode); // permanent reference to the object this node represents is useful for graph building, // and matching nodes in animations newNode.PermanentReference = permanentReference; newNode.Expression = expression; return(newNode); }
/// <summary> /// Fills node Content property tree. /// </summary> private void loadContent(ObjectGraphNode thisNode) { var contentRoot = new ThisNode(); thisNode.Content = contentRoot; // Object graph visualizer: collection support temp disabled (porting to new NRefactory). /*DebugType collectionType; * DebugType itemType; * if (thisNode.PermanentReference.Type.ResolveIListImplementation(out collectionType, out itemType)) * { * //AddRawViewNode(contentRoot, thisNode); * // it is an IList * LoadNodeCollectionContent(contentRoot, thisNode.Expression, collectionType); * } else if (thisNode.PermanentReference.Type.ResolveIEnumerableImplementation(out collectionType, out itemType)) { * //AddRawViewNode(contentRoot, thisNode); * // it is an IEnumerable * DebugType debugListType; * var debugListExpression = new GraphExpression( * DebuggerHelpers.CreateDebugListExpression(thisNode.Expression.Expr, itemType, out debugListType), * () => DebuggerHelpers.CreateListFromIEnumerable(thisNode.Expression.GetValue()) * ); * LoadNodeCollectionContent(contentRoot, debugListExpression, debugListType); * } else*/{ // it is an object LoadNodeObjectContent(contentRoot, thisNode.Expression, thisNode.PermanentReference.Type); } }
/// <summary> /// Fills node Content property tree. /// </summary> /// <param name="thisNode"></param> private void loadContent(ObjectGraphNode thisNode) { var contentRoot = new ThisNode(); thisNode.Content = contentRoot; DebugType collectionType; DebugType itemType; if (thisNode.PermanentReference.Type.ResolveIListImplementation(out collectionType, out itemType)) { //AddRawViewNode(contentRoot, thisNode); // it is an IList LoadNodeCollectionContent(contentRoot, thisNode.Expression, collectionType); } else if (thisNode.PermanentReference.Type.ResolveIEnumerableImplementation(out collectionType, out itemType)) { //AddRawViewNode(contentRoot, thisNode); // it is an IEnumerable DebugType debugListType; var debugListExpression = DebuggerHelpers.CreateDebugListExpression(thisNode.Expression, itemType, out debugListType); LoadNodeCollectionContent(contentRoot, debugListExpression, debugListType); } else { // it is an object LoadNodeObjectContent(contentRoot, thisNode.Expression, thisNode.PermanentReference.Type); } }
void FindReachableNodesRecursive(ObjectGraphNode root, HashSet<ObjectGraphNode> seenNodes) { seenNodes.Add(root); foreach(var prop in root.Properties) { if (prop.TargetNode != null && !seenNodes.Contains(prop.TargetNode)) FindReachableNodesRecursive(prop.TargetNode, seenNodes); } }
private void determineReachableNodes(ObjectGraphNode root, HashSet<ObjectGraphNode> seenNodes) { seenNodes.Add(root); foreach(var prop in root.Properties) { if (prop.TargetNode != null && !seenNodes.Contains(prop.TargetNode)) determineReachableNodes(prop.TargetNode, seenNodes); } }
void FindReachableNodesRecursive(ObjectGraphNode root, HashSet <ObjectGraphNode> seenNodes) { seenNodes.Add(root); foreach (var prop in root.Properties) { if (prop.TargetNode != null && !seenNodes.Contains(prop.TargetNode)) { FindReachableNodesRecursive(prop.TargetNode, seenNodes); } } }
private void determineReachableNodes(ObjectGraphNode root, HashSet <ObjectGraphNode> seenNodes) { seenNodes.Add(root); foreach (var prop in root.Properties) { if (prop.TargetNode != null && !seenNodes.Contains(prop.TargetNode)) { determineReachableNodes(prop.TargetNode, seenNodes); } } }
/// <summary> /// Returns node in the graph that represents given value, or returns new node if not found. /// </summary> /// <param name="value">Value for which to obtain the node/</param> /// <param name="createdNew">True if new node was created, false if existing node was returned.</param> public ObjectGraphNode ObtainNodeForValue(Value value, GraphExpression expression, out bool createdNew) { createdNew = false; ObjectGraphNode nodeForValue = getExistingNodeForValue(value); if (nodeForValue == null) { // if no node for memberValue exists, create it nodeForValue = createNewNode(value, expression); loadContent(nodeForValue); createdNew = true; } return(nodeForValue); }
/// <summary> /// Creates new node for the value. /// </summary> /// <param name="permanentReference">Value, has to be valid.</param> /// <returns>New empty object node representing the value.</returns> private ObjectGraphNode createNewNode(Value permanentReference, Expression expression) { ObjectGraphNode newNode = new ObjectGraphNode(); newNode.HashCode = permanentReference.InvokeDefaultGetHashCode(); resultGraph.AddNode(newNode); // remember this node's hashcode for quick lookup objectNodesForHashCode.Add(newNode.HashCode, newNode); // permanent reference to the object this node represents is useful for graph building, // and matching nodes in animations newNode.PermanentReference = permanentReference; newNode.Expression = expression; return(newNode); }
/// <summary> /// Fills node Content property tree. /// </summary> /// <param name="thisNode"></param> private void loadContent(ObjectGraphNode thisNode) { thisNode.Content = new ThisNode(); ThisNode contentRoot = thisNode.Content; DebugType iListType; DebugType listItemType; if (thisNode.PermanentReference.Type.ResolveIListImplementation(out iListType, out listItemType)) { // it is a collection loadNodeCollectionContent(contentRoot, thisNode.Expression, iListType); } else { // it is an object loadNodeObjectContent(contentRoot, thisNode.Expression, thisNode.PermanentReference.Type); } }
/// <summary> /// Finds node that represents the same instance as given value. /// </summary> /// <param name="value">Valid value representing an instance.</param> private ObjectGraphNode getExistingNodeForValue(Value value) { int objectHashCode = value.InvokeDefaultGetHashCode(); // are there any nodes with the same hash code? var nodesWithSameHashCode = objectNodesForHashCode[objectHashCode]; if (nodesWithSameHashCode == null) { return(null); } else { // 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(); ObjectGraphNode nodeWithSameAddress = nodesWithSameHashCode.FirstOrDefault(node => node.PermanentReference.GetObjectAddress() == objectAddress); return(nodeWithSameAddress); } }
/// <summary> /// For each complex property of this node, create s neighbor graph node if needed and connects the neighbor to ObjectProperty.TargetNode. /// </summary> /// <param name="thisNode"></param> /// <param name="expandedNodes"></param> private void loadNeighborsRecursive(ObjectGraphNode thisNode, ExpandedExpressions expandedNodes) { //foreach(ObjectGraphProperty complexProperty in thisNode.ComplexProperties) foreach (ObjectGraphProperty complexProperty in thisNode.Properties) { 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 && we dont know yet if it's null */ expandedNodes.IsExpanded(complexProperty.Expression)) { // if expanded, evaluate this property // complexProperty.Evaluate(); // consider Value memberValue = complexProperty.Expression.Evaluate(this.debuggerService.DebuggedProcess); if (memberValue.IsNull) { continue; } else { // if property value is not null, create neighbor memberValue = memberValue.GetPermanentReference(); bool createdNew; // get existing node (loop) or create new targetNode = ObtainNodeForValue(memberValue, complexProperty.Expression, out createdNew); if (createdNew) { // if member node is new, recursively build its subtree loadNeighborsRecursive(targetNode, expandedNodes); } } } else { targetNode = null; } // connect property to target ObjectGraphNode complexProperty.TargetNode = targetNode; } }
/// <summary> /// For each complex property of this node, create s neighbor graph node if needed and connects the neighbor to ObjectProperty.TargetNode. /// </summary> /// <param name="thisNode"></param> /// <param name="expandedNodes"></param> private void loadNeighborsRecursive(ObjectGraphNode thisNode, ExpandedExpressions expandedNodes) { // evaluate properties first in case property getters are changing some fields - the fields will then have correct values foreach (ObjectGraphProperty complexProperty in thisNode.PropertiesFirstThenFields) { ObjectGraphNode targetNode = null; // We are only evaluating expanded nodes here. // We have to do this to know the "shape" of the graph. // We do not evaluate atomic and non-expanded properties, those will be lazy evaluated when drawn. if (expandedNodes.IsExpanded(complexProperty.Expression)) { // if expanded, evaluate this property Value memberValue = complexProperty.Expression.Evaluate(this.debuggerService.DebuggedProcess); if (memberValue.IsNull) { continue; } else { // if property value is not null, create neighbor memberValue = memberValue.GetPermanentReference(); bool createdNew; // get existing node (loop) or create new targetNode = ObtainNodeForValue(memberValue, complexProperty.Expression, out createdNew); if (createdNew) { // if member node is new, recursively build its subtree loadNeighborsRecursive(targetNode, expandedNodes); } } } else { targetNode = null; } // connect property to target ObjectGraphNode complexProperty.TargetNode = targetNode; } }
/// <summary> /// Fills node Content property tree. /// </summary> private void loadContent(ObjectGraphNode thisNode) { var contentRoot = new ThisNode(); thisNode.Content = contentRoot; // Object graph visualizer: collection support temp disabled (porting to new NRefactory). /*DebugType collectionType; DebugType itemType; if (thisNode.PermanentReference.Type.ResolveIListImplementation(out collectionType, out itemType)) { //AddRawViewNode(contentRoot, thisNode); // it is an IList LoadNodeCollectionContent(contentRoot, thisNode.Expression, collectionType); } else if (thisNode.PermanentReference.Type.ResolveIEnumerableImplementation(out collectionType, out itemType)) { //AddRawViewNode(contentRoot, thisNode); // it is an IEnumerable DebugType debugListType; var debugListExpression = new GraphExpression( DebuggerHelpers.CreateDebugListExpression(thisNode.Expression.Expr, itemType, out debugListType), () => DebuggerHelpers.CreateListFromIEnumerable(thisNode.Expression.GetValue()) ); LoadNodeCollectionContent(contentRoot, debugListExpression, debugListType); } else*/ { // it is an object LoadNodeObjectContent(contentRoot, thisNode.Expression, thisNode.PermanentReference.Type); } }
public ObjectGraphProperty createComplexProperty(string name, Expression expression, ObjectGraphNode targetNode, bool isNull) { // value is empty (will be lazy-evaluated later) return new ObjectGraphProperty { Name = name, Value = "", Expression = expression, IsAtomic = false, TargetNode = targetNode, IsNull = isNull }; }
/// <summary> /// For each complex property of this node, creates a neighbor graph node if needed and connects /// it using to ObjectProperty.TargetNode. /// </summary> private void loadNeighborsRecursive(ObjectGraphNode thisNode, ExpandedExpressions expandedNodes) { // evaluate properties first in case property getters are changing some fields - the fields will then have correct values foreach(ObjectGraphProperty complexProperty in thisNode.PropertiesFirstThenFields) { ObjectGraphNode targetNode = null; // We are only evaluating expanded nodes here. // We have to do this to know the "shape" of the graph. // We do not evaluate atomic and non-expanded properties, those will be lazy evaluated when drawn. if (expandedNodes.IsExpanded(complexProperty.Expression.Expr)) { // if expanded, evaluate this property Value memberValue = complexProperty.Expression.GetValue(); if (memberValue.IsNull) { continue; } else { // if property value is not null, create neighbor memberValue = memberValue.GetPermanentReference(WindowsDebugger.EvalThread); bool createdNew; // get existing node (loop) or create new targetNode = ObtainNodeForValue(memberValue, complexProperty.Expression, out createdNew); if (createdNew) { // if member node is new, recursively build its subtree loadNeighborsRecursive(targetNode, expandedNodes); } } } // connect property to target ObjectGraphNode complexProperty.TargetNode = targetNode; } }
/// <summary> /// Creates new node for the value. /// </summary> /// <param name="permanentReference">Value, has to be valid.</param> /// <returns>New empty object node representing the value.</returns> private ObjectGraphNode createNewNode(Value permanentReference, GraphExpression expression) { if (permanentReference == null) throw new ArgumentNullException("permanentReference"); ObjectGraphNode newNode = new ObjectGraphNode(); if (permanentReference.Type != null) { newNode.TypeName = permanentReference.Type.FormatNameCSharp(); } newNode.HashCode = permanentReference.InvokeDefaultGetHashCode(); resultGraph.AddNode(newNode); // remember this node's hashcode for quick lookup objectNodesForHashCode.Add(newNode.HashCode, newNode); // permanent reference to the object this node represents is useful for graph building, // and matching nodes in animations newNode.PermanentReference = permanentReference; newNode.Expression = expression; return newNode; }
/// <summary> /// Adds node to the graph. /// </summary> /// <param name="node">node to be added</param> internal void AddNode(ObjectGraphNode node) { _nodes.Add(node); }
/// <summary> /// Adds node to the graph. /// </summary> /// <param name="node">node to be added</param> internal void AddNode(ObjectGraphNode node) { nodes.Add(node); }
public ObjectGraphProperty createComplexProperty(string name, Expression expression, ObjectGraphNode targetNode, bool isNull) { // value is empty (will be lazy-evaluated later) return(new ObjectGraphProperty { Name = name, Value = "", Expression = expression, IsAtomic = false, TargetNode = targetNode, IsNull = isNull }); }