12 changed files with 219 additions and 24 deletions
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using NUnit.Framework; |
||||
|
||||
namespace ICSharpCode.NRefactory.Util |
||||
{ |
||||
[TestFixture] |
||||
public class TreeTraversalTests |
||||
{ |
||||
sealed class Node |
||||
{ |
||||
public int Data; |
||||
public List<Node> Children = new List<Node>(); |
||||
} |
||||
|
||||
Node tree = new Node { |
||||
Data = 1, |
||||
Children = { |
||||
new Node { Data = 2 }, |
||||
new Node { Data = 3, |
||||
Children = { |
||||
new Node { Data = 4 }, |
||||
new Node { Data = 5 } |
||||
} }, |
||||
new Node { Data = 6, Children = null } |
||||
} |
||||
}; |
||||
|
||||
[Test] |
||||
public void PreOrder() |
||||
{ |
||||
Assert.AreEqual(new int[] { 1, 2, 3, 4, 5, 6 }, |
||||
TreeTraversal.PreOrder(tree, n => n.Children).Select(n => n.Data).ToArray()); |
||||
} |
||||
|
||||
[Test] |
||||
public void PostOrder() |
||||
{ |
||||
Assert.AreEqual(new int[] { 2, 4, 5, 3, 6, 1 }, |
||||
TreeTraversal.PostOrder(tree, n => n.Children).Select(n => n.Data).ToArray()); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using ICSharpCode.NRefactory.Util; |
||||
|
||||
namespace ICSharpCode.NRefactory.TypeSystem |
||||
{ |
||||
/// <summary>
|
||||
/// Contains extension methods for the type system.
|
||||
/// </summary>
|
||||
public static class ExtensionMethods |
||||
{ |
||||
/// <summary>
|
||||
/// Gets all base types.
|
||||
/// </summary>
|
||||
/// <remarks>This is the reflexive and transitive closure of <see cref="IType.GetBaseTypes"/>.
|
||||
/// Note that this method does not return all supertypes - doing so is impossible due to contravariance.
|
||||
/// This method may return an infinite list for certain (invalid) class declarations like <c>class C{T} : C{C{T}}</c>
|
||||
/// TODO: we could ensure a finite list by filtering out cyclic inheritance
|
||||
/// </remarks>
|
||||
public static IEnumerable<IType> GetAllBaseTypes(this IType type, ITypeResolveContext context) |
||||
{ |
||||
// Given types as nodes and GetBaseTypes() as edges, the type hierarchy forms a graph.
|
||||
// This method should return all nodes reachable from the given start node.
|
||||
|
||||
// We perform this operation by converting the graph into a tree by making sure we return each node at most once.
|
||||
// Then we convert the tree into a flat list using the Flatten operation.
|
||||
|
||||
HashSet<IType> visited = new HashSet<IType>(); |
||||
visited.Add(type); |
||||
return TreeTraversal.PreOrder(type, t => t.GetBaseTypes(context).Where(visited.Add)); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,97 @@
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace ICSharpCode.NRefactory.Util |
||||
{ |
||||
/// <summary>
|
||||
/// Static helper methods for traversing trees.
|
||||
/// </summary>
|
||||
public static class TreeTraversal |
||||
{ |
||||
/// <summary>
|
||||
/// Converts a tree data structure into a flat list by traversing it in pre-order.
|
||||
/// </summary>
|
||||
/// <param name="input">The root element of the tree.</param>
|
||||
/// <param name="recursive">The function that gets the children of an element.</param>
|
||||
/// <returns>Iterator that enumerates the tree structure in pre-order.</returns>
|
||||
public static IEnumerable<T> PreOrder<T>(T root, Func<T, IEnumerable<T>> recursion) |
||||
{ |
||||
return PreOrder(new T[] { root }, recursion); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Converts a tree data structure into a flat list by traversing it in pre-order.
|
||||
/// </summary>
|
||||
/// <param name="input">The root elements of the forest.</param>
|
||||
/// <param name="recursive">The function that gets the children of an element.</param>
|
||||
/// <returns>Iterator that enumerates the tree structure in pre-order.</returns>
|
||||
public static IEnumerable<T> PreOrder<T>(IEnumerable<T> input, Func<T, IEnumerable<T>> recursion) |
||||
{ |
||||
Stack<IEnumerator<T>> stack = new Stack<IEnumerator<T>>(); |
||||
try { |
||||
stack.Push(input.GetEnumerator()); |
||||
while (stack.Count > 0) { |
||||
while (stack.Peek().MoveNext()) { |
||||
T element = stack.Peek().Current; |
||||
yield return element; |
||||
IEnumerable<T> children = recursion(element); |
||||
if (children != null) { |
||||
stack.Push(children.GetEnumerator()); |
||||
} |
||||
} |
||||
stack.Pop().Dispose(); |
||||
} |
||||
} finally { |
||||
while (stack.Count > 0) { |
||||
stack.Pop().Dispose(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Converts a tree data structure into a flat list by traversing it in post-order.
|
||||
/// </summary>
|
||||
/// <param name="input">The root element of the tree.</param>
|
||||
/// <param name="recursive">The function that gets the children of an element.</param>
|
||||
/// <returns>Iterator that enumerates the tree structure in post-order.</returns>
|
||||
public static IEnumerable<T> PostOrder<T>(T root, Func<T, IEnumerable<T>> recursion) |
||||
{ |
||||
return PostOrder(new T[] { root }, recursion); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Converts a tree data structure into a flat list by traversing it in post-order.
|
||||
/// </summary>
|
||||
/// <param name="input">The root elements of the forest.</param>
|
||||
/// <param name="recursive">The function that gets the children of an element.</param>
|
||||
/// <returns>Iterator that enumerates the tree structure in post-order.</returns>
|
||||
public static IEnumerable<T> PostOrder<T>(IEnumerable<T> input, Func<T, IEnumerable<T>> recursion) |
||||
{ |
||||
Stack<IEnumerator<T>> stack = new Stack<IEnumerator<T>>(); |
||||
try { |
||||
stack.Push(input.GetEnumerator()); |
||||
while (stack.Count > 0) { |
||||
while (stack.Peek().MoveNext()) { |
||||
T element = stack.Peek().Current; |
||||
IEnumerable<T> children = recursion(element); |
||||
if (children != null) { |
||||
stack.Push(children.GetEnumerator()); |
||||
} else { |
||||
yield return element; |
||||
} |
||||
} |
||||
stack.Pop().Dispose(); |
||||
if (stack.Count > 0) |
||||
yield return stack.Peek().Current; |
||||
} |
||||
} finally { |
||||
while (stack.Count > 0) { |
||||
stack.Pop().Dispose(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue