Browse Source

Add GetAllBaseTypes() extension method.

Move BitVector16 and BusyManager to utils.
newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
8879b7c372
  1. 2
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
  2. 36
      ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs
  3. 7
      ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs
  4. 47
      ICSharpCode.NRefactory.Tests/Util/TreeTraversalTests.cs
  5. 9
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  6. 37
      ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs
  7. 1
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs
  8. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs
  9. 1
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs
  10. 2
      ICSharpCode.NRefactory/Util/BitVector16.cs
  11. 2
      ICSharpCode.NRefactory/Util/BusyManager.cs
  12. 97
      ICSharpCode.NRefactory/Util/TreeTraversal.cs

2
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -53,6 +53,7 @@ @@ -53,6 +53,7 @@
<Compile Include="TypeSystem\TestInterningProvider.cs" />
<Compile Include="TypeSystem\TypeSystemTests.cs" />
<Compile Include="TypeSystem\TypeSystemTests.TestCase.cs" />
<Compile Include="Util\TreeTraversalTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
@ -61,6 +62,7 @@ @@ -61,6 +62,7 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Util" />
<Folder Include="TypeSystem" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />

36
ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs

@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
// 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.TypeSystem.Implementation;
using NUnit.Framework;
@ -11,6 +13,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -11,6 +13,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
public class CecilLoaderTests : TypeSystemTests
{
public static readonly IProjectContent Mscorlib = new CecilLoader().LoadAssemblyFile(typeof(object).Assembly.Location);
ITypeResolveContext ctx = Mscorlib;
[TestFixtureSetUp]
public void SetUp()
@ -23,7 +26,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -23,7 +26,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
[Test]
public void InheritanceTest()
{
ITypeResolveContext ctx = Mscorlib;
ITypeDefinition c = Mscorlib.GetClass(typeof(SystemException));
ITypeDefinition c2 = Mscorlib.GetClass(typeof(Exception));
Assert.IsNotNull(c, "c is null");
@ -33,23 +35,21 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -33,23 +35,21 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual("System.Exception", c.BaseTypes[0].Resolve(ctx).FullName);
Assert.AreSame(c2, c.BaseTypes[0]);
/*
List<ITypeDefinition> subClasses = new List<ITypeDefinition>();
foreach (IClass subClass in c.ClassInheritanceTree) {
subClasses.Add(subClass);
}
Assert.AreEqual(5, subClasses.Count, "ClassInheritanceTree length");
Assert.AreEqual("System.SystemException", subClasses[0].FullyQualifiedName);
Assert.AreEqual("System.Exception", subClasses[1].FullyQualifiedName);
if (subClasses[2].FullyQualifiedName == "System.Object") {
Assert.AreEqual("System.Object", subClasses[2].FullyQualifiedName);
Assert.AreEqual("System.Runtime.Serialization.ISerializable", subClasses[3].FullyQualifiedName);
Assert.AreEqual("System.Runtime.InteropServices._Exception", subClasses[4].FullyQualifiedName);
} else {
Assert.AreEqual("System.Runtime.Serialization.ISerializable", subClasses[2].FullyQualifiedName);
Assert.AreEqual("System.Runtime.InteropServices._Exception", subClasses[3].FullyQualifiedName);
Assert.AreEqual("System.Object", subClasses[4].FullyQualifiedName);
}*/
string[] superTypes = c.GetAllBaseTypes(ctx).Select(t => t.ToString()).ToArray();
Assert.AreEqual(new string[] {
"System.SystemException", "System.Exception", "System.Object",
"System.Runtime.Serialization.ISerializable", "System.Runtime.InteropServices._Exception"
}, superTypes);
}
[Test]
public void GenericPropertyTest()
{
ITypeDefinition c = Mscorlib.GetClass(typeof(Comparer<>));
IProperty def = c.Properties.Single(p => p.Name == "Default");
ConstructedType pt = (ConstructedType)def.ReturnType.Resolve(ctx);
Assert.AreEqual("System.Collections.Generic.Comparer", pt.FullName);
Assert.AreSame(c.TypeParameters[0], pt.TypeArguments[0]);
}
}
}

7
ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs

@ -1,4 +1,6 @@ @@ -1,4 +1,6 @@

// 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;
using System.Collections.Generic;
@ -10,6 +12,7 @@ using NUnit.Framework; @@ -10,6 +12,7 @@ using NUnit.Framework;
namespace ICSharpCode.NRefactory.TypeSystem
{
/* Not a real unit test
[TestFixture]
public class TestInterningProvider : IInterningProvider
{
@ -148,5 +151,5 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -148,5 +151,5 @@ namespace ICSharpCode.NRefactory.TypeSystem
Console.WriteLine(element.Type + ": " + element.PostCount + "/" + element.PreCount);
}
}
}
}*/
}

47
ICSharpCode.NRefactory.Tests/Util/TreeTraversalTests.cs

@ -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());
}
}
}

9
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -149,6 +149,7 @@ @@ -149,6 +149,7 @@
<Compile Include="TypeSystem\ConstructedType.cs" />
<Compile Include="TypeSystem\DomRegion.cs" />
<Compile Include="TypeSystem\EntityType.cs" />
<Compile Include="TypeSystem\ExtensionMethods.cs" />
<Compile Include="TypeSystem\IAttribute.cs" />
<Compile Include="TypeSystem\IConstantValue.cs" />
<Compile Include="TypeSystem\IEntity.cs" />
@ -162,8 +163,6 @@ @@ -162,8 +163,6 @@
<Compile Include="TypeSystem\Implementation\AbstractFreezable.cs" />
<Compile Include="TypeSystem\Implementation\AbstractMember.cs" />
<Compile Include="TypeSystem\Implementation\AbstractType.cs" />
<Compile Include="TypeSystem\Implementation\BitVector16.cs" />
<Compile Include="TypeSystem\Implementation\BusyManager.cs" />
<Compile Include="TypeSystem\Implementation\DefaultAttribute.cs" />
<Compile Include="TypeSystem\Implementation\DefaultEvent.cs" />
<Compile Include="TypeSystem\Implementation\DefaultExplicitInterfaceImplementation.cs" />
@ -250,6 +249,12 @@ @@ -250,6 +249,12 @@
<Compile Include="CSharp\Parser\mcs\support.cs" />
<Compile Include="CSharp\Parser\mcs\complete.cs" />
<Compile Include="CSharp\Parser\mcs\literal.cs" />
<Compile Include="Util\BitVector16.cs" />
<Compile Include="Util\BusyManager.cs" />
<Compile Include="Util\TreeTraversal.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Util" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

37
ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs

@ -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));
}
}
}

1
ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Util;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{

2
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs

@ -7,6 +7,8 @@ using System.Diagnostics.Contracts; @@ -7,6 +7,8 @@ using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using ICSharpCode.NRefactory.Util;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
public class DefaultTypeDefinition : AbstractFreezable, ITypeDefinition

1
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Util;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{

2
ICSharpCode.NRefactory/TypeSystem/Implementation/BitVector16.cs → ICSharpCode.NRefactory/Util/BitVector16.cs

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
using System;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
namespace ICSharpCode.NRefactory.Util
{
/// <summary>
/// Holds 16 boolean values.

2
ICSharpCode.NRefactory/TypeSystem/Implementation/BusyManager.cs → ICSharpCode.NRefactory/Util/BusyManager.cs

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
namespace ICSharpCode.NRefactory.Util
{
/// <summary>
/// This class is used to prevent stack overflows by representing a 'busy' flag

97
ICSharpCode.NRefactory/Util/TreeTraversal.cs

@ -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…
Cancel
Save