Browse Source

Add 'FullTypeName' struct, and use it to represent type names.

Contains some breaking API changes:
 - Renamed 'FullNameAndTypeParameterCount' to 'TopLevelTypeName'.
 - IAssembly.GetTypeDefinition(string, string, int) -> IAssembly.GetTypeDefinition(TopLevelTypeName)
 - IAssembly.GetTypeDefinition(IUnresolvedTypeDefinition) -> IAssembly.GetTypeDefinition(FullTypeName)
 - GetClassTypeReference now supports nested types
newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
5670248de8
  1. 4
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  2. 2
      ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs
  3. 18
      ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs
  4. 6
      ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs
  5. 23
      ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs
  6. 15
      ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs
  7. 13
      ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs
  8. 14
      ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs
  9. 4
      ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/TestBase.cs
  10. 2
      ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs
  11. 4
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs
  12. 6
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs
  13. 2
      ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs
  14. 5
      ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs
  15. 10
      ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs
  16. 6
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeParameterTests.cs
  17. 6
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemHelper.cs
  18. 9
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  19. 2
      ICSharpCode.NRefactory/Documentation/GetPotentiallyNestedClassTypeReference.cs
  20. 4
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  21. 10
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  22. 57
      ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs
  23. 312
      ICSharpCode.NRefactory/TypeSystem/FullTypeName.cs
  24. 2
      ICSharpCode.NRefactory/TypeSystem/IAssembly.cs
  25. 3
      ICSharpCode.NRefactory/TypeSystem/ICompilation.cs
  26. 6
      ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs
  27. 4
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs
  28. 26
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  29. 24
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeDefinition.cs
  30. 69
      ICSharpCode.NRefactory/TypeSystem/Implementation/FullNameAndTypeParameterCount.cs
  31. 99
      ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs
  32. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/KnownTypeCache.cs
  33. 50
      ICSharpCode.NRefactory/TypeSystem/Implementation/UnknownType.cs
  34. 12
      ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs
  35. 144
      ICSharpCode.NRefactory/TypeSystem/TopLevelTypeName.cs

4
ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

@ -1336,7 +1336,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1336,7 +1336,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
}
if (this.currentMember != null && !(node is AstType)) {
var def = ctx.CurrentTypeDefinition ?? Compilation.MainAssembly.GetTypeDefinition(currentType);
var def = ctx.CurrentTypeDefinition;
if (def == null && currentType != null)
def = Compilation.MainAssembly.GetTypeDefinition(currentType.FullTypeName);
if (def != null) {
bool isProtectedAllowed = true;
foreach (var member in def.GetMembers ()) {

2
ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs

@ -60,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -60,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public virtual AstType CreateShortType(string ns, string name, int typeParameterCount = 0)
{
var builder = CreateTypeSytemAstBuilder();
return builder.ConvertType(ns, name, typeParameterCount);
return builder.ConvertType(new TopLevelTypeName(ns, name, typeParameterCount));
}
public virtual IEnumerable<AstNode> GetSelectedNodes()

18
ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs

@ -142,17 +142,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -142,17 +142,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return astType;
}
public AstType ConvertType(string ns, string name, int typeParameterCount = 0)
public AstType ConvertType(FullTypeName fullTypeName)
{
if (resolver != null) {
foreach (var asm in resolver.Compilation.Assemblies) {
var def = asm.GetTypeDefinition(ns, name, typeParameterCount);
var def = asm.GetTypeDefinition(fullTypeName);
if (def != null) {
return ConvertType(def);
}
}
}
return new MemberType(new SimpleType(ns), name);
TopLevelTypeName top = fullTypeName.TopLevelTypeName;
AstType type;
if (string.IsNullOrEmpty(top.Namespace)) {
type = new SimpleType(top.Name);
} else {
type = new SimpleType(top.Namespace).MemberType(top.Name);
}
for (int i = 0; i < fullTypeName.NestingLevel; i++) {
type = type.MemberType(fullTypeName.GetNestedTypeName(i));
}
return type;
}
AstType ConvertTypeHelper(IType type)
@ -601,7 +611,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -601,7 +611,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
if (GenerateBody) {
return new BlockStatement {
new ThrowStatement(new ObjectCreateExpression(ConvertType("System", "NotImplementedException")))
new ThrowStatement(new ObjectCreateExpression(ConvertType(new TopLevelTypeName("System", "NotImplementedException", 0))))
};
} else {
return BlockStatement.Null;

6
ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs

@ -51,6 +51,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -51,6 +51,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return resolver.ResolveAlias(identifier);
}
public override IType ResolveType(CSharpResolver resolver)
{
// alias cannot refer to types
return SpecialType.UnknownType;
}
public override string ToString()
{
return identifier + "::";

23
ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs

@ -181,9 +181,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -181,9 +181,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return fullAssemblyName.Substring(0, pos);
}
Dictionary<FullNameAndTypeParameterCount, ITypeDefinition> typeDict;
Dictionary<TopLevelTypeName, ITypeDefinition> typeDict;
Dictionary<FullNameAndTypeParameterCount, ITypeDefinition> GetTypes()
Dictionary<TopLevelTypeName, ITypeDefinition> GetTypes()
{
var dict = LazyInit.VolatileRead(ref this.typeDict);
if (dict != null) {
@ -192,9 +192,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -192,9 +192,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
// Always use the ordinal comparer for the main dictionary so that partial classes
// get merged correctly.
// The compilation's comparer will be used for the per-namespace dictionaries.
var comparer = FullNameAndTypeParameterCountComparer.Ordinal;
var comparer = TopLevelTypeNameComparer.Ordinal;
dict = projectContent.TopLevelTypeDefinitions
.GroupBy(t => new FullNameAndTypeParameterCount(t.Namespace, t.Name, t.TypeParameters.Count), comparer)
.GroupBy(t => new TopLevelTypeName(t.Namespace, t.Name, t.TypeParameters.Count), comparer)
.ToDictionary(g => g.Key, g => CreateResolvedTypeDefinition(g.ToArray()), comparer);
return LazyInit.GetOrSet(ref this.typeDict, dict);
}
@ -205,11 +205,10 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -205,11 +205,10 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return new DefaultResolvedTypeDefinition(context, parts);
}
public ITypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount)
public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
{
var key = new FullNameAndTypeParameterCount(ns ?? string.Empty, name, typeParameterCount);
ITypeDefinition def;
if (GetTypes().TryGetValue(key, out def))
if (GetTypes().TryGetValue(topLevelTypeName, out def))
return def;
else
return null;
@ -233,7 +232,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -233,7 +232,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
readonly string fullName;
readonly string name;
internal readonly List<NS> childNamespaces = new List<NS>();
internal readonly Dictionary<FullNameAndTypeParameterCount, ITypeDefinition> types;
internal readonly Dictionary<TopLevelTypeName, ITypeDefinition> types;
public NS(CSharpAssembly assembly)
{
@ -243,7 +242,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -243,7 +242,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
// Our main dictionary for the CSharpAssembly is using an ordinal comparer.
// If the compilation's comparer isn't ordinal, we need to create a new dictionary with the compilation's comparer.
if (assembly.compilation.NameComparer != StringComparer.Ordinal) {
this.types = new Dictionary<FullNameAndTypeParameterCount, ITypeDefinition>(new FullNameAndTypeParameterCountComparer(assembly.compilation.NameComparer));
this.types = new Dictionary<TopLevelTypeName, ITypeDefinition>(new TopLevelTypeNameComparer(assembly.compilation.NameComparer));
}
}
@ -254,7 +253,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -254,7 +253,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
this.fullName = fullName;
this.name = name;
if (parentNamespace.types != null)
this.types = new Dictionary<FullNameAndTypeParameterCount, ITypeDefinition>(parentNamespace.types.Comparer);
this.types = new Dictionary<TopLevelTypeName, ITypeDefinition>(parentNamespace.types.Comparer);
}
string INamespace.ExternAlias {
@ -310,15 +309,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -310,15 +309,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount)
{
var key = new TopLevelTypeName(fullName, name, typeParameterCount);
if (types != null) {
var key = new FullNameAndTypeParameterCount(fullName, name, typeParameterCount);
ITypeDefinition typeDef;
if (types.TryGetValue(key, out typeDef))
return typeDef;
else
return null;
} else {
return assembly.GetTypeDefinition(fullName, name, typeParameterCount);
return assembly.GetTypeDefinition(key);
}
}
}

15
ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs

@ -22,6 +22,7 @@ using System.Collections.ObjectModel; @@ -22,6 +22,7 @@ using System.Collections.ObjectModel;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.TypeSystem
@ -58,7 +59,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -58,7 +59,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
}
public IList<ITypeReference> TypeArguments {
get { return new ReadOnlyCollection<ITypeReference>(typeArguments); }
get { return typeArguments; }
}
public NameLookupMode LookupMode {
get { return lookupMode; }
}
/// <summary>
@ -67,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -67,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
/// </summary>
public MemberTypeOrNamespaceReference AddSuffix(string suffix)
{
return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments);
return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments, lookupMode);
}
public override ResolveResult Resolve(CSharpResolver resolver)
@ -86,6 +91,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -86,6 +91,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
}
}
public override IType ResolveType(CSharpResolver resolver)
{
TypeResolveResult trr = Resolve(resolver) as TypeResolveResult;
return trr != null ? trr.Type : new UnknownType(null, identifier, typeArguments.Count);
}
public override string ToString()
{
if (typeArguments.Count == 0)

13
ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs

@ -23,6 +23,7 @@ using System.Collections.ObjectModel; @@ -23,6 +23,7 @@ using System.Collections.ObjectModel;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.TypeSystem
@ -51,7 +52,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -51,7 +52,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
}
public IList<ITypeReference> TypeArguments {
get { return new ReadOnlyCollection<ITypeReference>(typeArguments); }
get { return typeArguments; }
}
public NameLookupMode LookupMode {
get { return lookupMode; }
}
/// <summary>
@ -69,6 +74,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -69,6 +74,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return resolver.LookupSimpleNameOrTypeName(identifier, typeArgs, lookupMode);
}
public override IType ResolveType(CSharpResolver resolver)
{
TypeResolveResult trr = Resolve(resolver) as TypeResolveResult;
return trr != null ? trr.Type : new UnknownType(null, identifier, typeArguments.Count);
}
public override string ToString()
{
if (typeArguments.Count == 0)

14
ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs

@ -34,6 +34,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -34,6 +34,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
/// </summary>
public abstract ResolveResult Resolve(CSharpResolver resolver);
/// <summary>
/// Returns the type that is referenced; or an <see cref="UnknownType"/> if the type isn't found.
/// </summary>
public abstract IType ResolveType(CSharpResolver resolver);
/// <summary>
/// Returns the namespace that is referenced; or null if no such namespace is found.
/// </summary>
@ -43,15 +48,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -43,15 +48,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return nrr != null ? nrr.Namespace : null;
}
/// <summary>
/// Returns the type that is referenced; or <see cref="SpecialType.UnknownType"/> if the type isn't found.
/// </summary>
public IType ResolveType(CSharpResolver resolver)
{
TypeResolveResult trr = Resolve(resolver) as TypeResolveResult;
return trr != null ? trr.Type : SpecialType.UnknownType;
}
IType ITypeReference.Resolve(ITypeResolveContext context)
{
// Strictly speaking, we might have to resolve the type in a nested compilation, similar

4
ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/TestBase.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// TestBase.cs
//
// Author:
@ -38,7 +38,7 @@ using System.Diagnostics; @@ -38,7 +38,7 @@ using System.Diagnostics;
namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
{
[TestFixture]
public class TestBase
public abstract class TestBase
{
class TestListener : TraceListener
{

2
ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs

@ -217,7 +217,7 @@ namespace OtherNS { @@ -217,7 +217,7 @@ namespace OtherNS {
public void AmbiguousType()
{
Assert.AreEqual("System.Array", TypeToString(compilation.FindType(typeof(Array))));
Assert.AreEqual("OtherNS.Array", TypeToString(compilation.MainAssembly.GetTypeDefinition("OtherNS", "Array", 0)));
Assert.AreEqual("OtherNS.Array", TypeToString(compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName("OtherNS", "Array"))));
}
}
}

4
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs

@ -508,8 +508,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -508,8 +508,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
) } ) }));
ICompilation compilation = TypeSystemHelper.CreateCompilation(a, b);
ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a);
ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b);
ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a.FullTypeName);
ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b.FullTypeName);
IType type1 = new ParameterizedType(resolvedB, new [] { compilation.FindType(KnownTypeCode.Double) });
IType type2 = new ParameterizedType(resolvedA, new [] { new ParameterizedType(resolvedB, new[] { compilation.FindType(KnownTypeCode.String) }) });

6
ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs

@ -61,7 +61,7 @@ class Derived : Middle { @@ -61,7 +61,7 @@ class Derived : Middle {
public override void Method() {}
}";
var unresolvedFile = Parse(program);
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(unresolvedFile.TopLevelTypeDefinitions[2]);
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(unresolvedFile.TopLevelTypeDefinitions[2].FullTypeName);
var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count());
@ -88,7 +88,7 @@ class Derived : Base<int> { @@ -88,7 +88,7 @@ class Derived : Base<int> {
public override void Method(string a) {}
}";
var unresolvedFile = Parse(program);
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(unresolvedFile.TopLevelTypeDefinitions[1]);
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(unresolvedFile.TopLevelTypeDefinitions[1].FullTypeName);
var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count());
@ -116,7 +116,7 @@ class Derived : Base { @@ -116,7 +116,7 @@ class Derived : Base {
public override void Method<S>(S a) {}
}";
var unresolvedFile = Parse(program);
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(unresolvedFile.TopLevelTypeDefinitions[1]);
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(unresolvedFile.TopLevelTypeDefinitions[1].FullTypeName);
var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
Assert.AreEqual(1, rr.MethodsGroupedByDeclaringType.Count());

2
ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs

@ -59,7 +59,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -59,7 +59,7 @@ namespace ICSharpCode.NRefactory.Documentation
ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount = 0)
{
return compilation.MainAssembly.GetTypeDefinition(nameSpace, name, typeParameterCount);
return compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName(nameSpace, name, typeParameterCount));
}
[Test]

5
ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs

@ -83,7 +83,7 @@ namespace System.Collections.Generic { @@ -83,7 +83,7 @@ namespace System.Collections.Generic {
ITypeDefinition Resolve(IUnresolvedTypeDefinition typeDef)
{
return compilation.MainAssembly.GetTypeDefinition(typeDef);
return typeDef.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition();
}
[Test]
@ -135,8 +135,7 @@ namespace System.Collections.Generic { @@ -135,8 +135,7 @@ namespace System.Collections.Generic {
// class C : C {}
var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C");
c.BaseTypes.Add(c);
compilation = TypeSystemHelper.CreateCompilation(c);
ITypeDefinition resolvedC = Resolve(c);
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
Assert.AreEqual(new [] { resolvedC }, resolvedC.GetAllBaseTypes().ToArray());
}

10
ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs

@ -31,8 +31,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -31,8 +31,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
public void EmptyClassHasToString()
{
DefaultUnresolvedTypeDefinition c = new DefaultUnresolvedTypeDefinition(string.Empty, "C");
var compilation = TypeSystemHelper.CreateCompilation(c);
Assert.AreEqual("System.Object.ToString", compilation.MainAssembly.GetTypeDefinition(c).GetMethods(m => m.Name == "ToString").Single().FullName);
var resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
Assert.AreEqual("System.Object.ToString", resolvedC.GetMethods(m => m.Name == "ToString").Single().FullName);
}
[Test]
@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
c.BaseTypes.Add(b2);
var compilation = TypeSystemHelper.CreateCompilation(b1, b2, c);
ITypeDefinition resolvedC = compilation.MainAssembly.GetTypeDefinition(c);
ITypeDefinition resolvedC = compilation.MainAssembly.GetTypeDefinition(c.FullTypeName);
Assert.AreEqual(new[] { "P1", "P2" }, resolvedC.GetProperties().Select(p => p.Name).ToArray());
// Test that there's only one copy of ToString():
Assert.AreEqual(1, resolvedC.GetMethods(m => m.Name == "ToString").Count());
@ -91,8 +91,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -91,8 +91,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
a.NestedTypes.Add(b);
var compilation = TypeSystemHelper.CreateCompilation(a, b);
ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a);
ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b);
ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a.FullTypeName);
ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b.FullTypeName);
// A<> gets self-parameterized, B<> stays unbound
Assert.AreEqual("A`1+B`1[[`0],[]]", resolvedA.GetNestedTypes().Single().ReflectionName);

6
ICSharpCode.NRefactory.Tests/TypeSystem/TypeParameterTests.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -36,7 +36,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) }
});
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilation(c).MainAssembly.GetTypeDefinition(c);
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
// At runtime, we might have T=System.ValueType and U=int, so C# can't inherit the 'class' constraint
// from one type parameter to another.
Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType);
@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) }
});
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilation(c).MainAssembly.GetTypeDefinition(c);
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
// At runtime, we might have T=System.ValueType and U=int, so C# can't inherit the 'class' constraint
// from one type parameter to another.
Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType);
@ -73,7 +73,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -73,7 +73,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) }
});
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilation(c).MainAssembly.GetTypeDefinition(c);
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType);
Assert.AreEqual(true, resolvedC.TypeParameters[1].IsReferenceType);
Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", resolvedC.TypeParameters[0].EffectiveBaseClass.ReflectionName);

6
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemHelper.cs

@ -44,5 +44,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -44,5 +44,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
pc = pc.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore });
return pc.CreateCompilation();
}
public static ITypeDefinition CreateCompilationAndResolve(IUnresolvedTypeDefinition unresolvedTypeDefinition)
{
var compilation = CreateCompilation(unresolvedTypeDefinition);
return unresolvedTypeDefinition.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition();
}
}
}

9
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs

@ -137,8 +137,13 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -137,8 +137,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
ParameterizedType crt = (ParameterizedType)rt.ReferencedType;
Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName);
Assert.AreEqual("System.String", crt.TypeArguments[0].FullName);
// ? for NUnit.TestAttribute (because that assembly isn't in ctx)
Assert.AreEqual("System.Collections.Generic.IList`1[[?]]", crt.TypeArguments[1].ReflectionName);
// we know the name for TestAttribute, but not necessarily the namespace, as NUnit is not in the compilation
Assert.AreEqual("System.Collections.Generic.IList", crt.TypeArguments[1].FullName);
var testAttributeType = ((ParameterizedType)crt.TypeArguments[1]).TypeArguments.Single();
Assert.AreEqual("TestAttribute", testAttributeType.Name);
Assert.AreEqual(TypeKind.Unknown, testAttributeType.Kind);
// (more accurately, we know the namespace and reflection name if the type was loaded by cecil,
// but not if we parsed it from C#)
}
[Test]

2
ICSharpCode.NRefactory/Documentation/GetPotentiallyNestedClassTypeReference.cs

@ -51,7 +51,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -51,7 +51,7 @@ namespace ICSharpCode.NRefactory.Documentation
foreach (var asm in assemblies) {
if (asm == null)
continue;
ITypeDefinition typeDef = asm.GetTypeDefinition(ns, name, topLevelTPC);
ITypeDefinition typeDef = asm.GetTypeDefinition(new TopLevelTypeName(ns, name, topLevelTPC));
for (int j = i + 1; j < parts.Length && typeDef != null; j++) {
int tpc = (j == parts.Length - 1 ? typeParameterCount : 0);
typeDef = typeDef.NestedTypes.FirstOrDefault(n => n.Name == parts[j] && n.TypeParameterCount == tpc);

4
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -138,6 +138,7 @@ @@ -138,6 +138,7 @@
<Compile Include="TypeSystem\DomRegion.cs" />
<Compile Include="TypeSystem\EntityType.cs" />
<Compile Include="TypeSystem\ExtensionMethods.cs" />
<Compile Include="TypeSystem\FullTypeName.cs" />
<Compile Include="TypeSystem\IAmbience.cs" />
<Compile Include="TypeSystem\IAssembly.cs" />
<Compile Include="TypeSystem\IAttribute.cs" />
@ -223,6 +224,7 @@ @@ -223,6 +224,7 @@
<Compile Include="TypeSystem\ProjectReference.cs" />
<Compile Include="TypeSystem\ReflectionNameParseException.cs" />
<Compile Include="TypeSystem\SimpleTypeResolveContext.cs" />
<Compile Include="TypeSystem\TopLevelTypeName.cs" />
<Compile Include="TypeSystem\TypeKind.cs" />
<Compile Include="TypeSystem\TypeVisitor.cs" />
<Compile Include="TypeSystem\IVariable.cs" />
@ -284,4 +286,4 @@ @@ -284,4 +286,4 @@
</None>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
</Project>

10
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -190,7 +190,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -190,7 +190,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
name = interningProvider.Intern(name);
var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount);
typeRef = interningProvider.Intern(typeRef);
var key = new FullNameAndTypeParameterCount(ns, name, typeParameterCount);
var key = new TopLevelTypeName(ns, name, typeParameterCount);
currentAssembly.AddTypeForwarder(key, typeRef);
}
}
@ -1793,6 +1793,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1793,6 +1793,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
get { return cecilTypeDef.FullName; }
}
public FullTypeName FullTypeName {
get {
return new TopLevelTypeName(namespaceName, this.Name, typeParameters.Count);
}
}
public TypeKind Kind {
get { return kind; }
}
@ -1884,7 +1890,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1884,7 +1890,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
throw new ArgumentNullException("context");
if (context.CurrentAssembly == null)
throw new ArgumentException("An ITypeDefinition cannot be resolved in a context without a current assembly.");
return context.CurrentAssembly.GetTypeDefinition(this)
return context.CurrentAssembly.GetTypeDefinition(this.FullTypeName)
?? (IType)new UnknownType(this.Namespace, this.Name, this.TypeParameters.Count);
}

57
ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs

@ -392,28 +392,59 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -392,28 +392,59 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endregion
#region IAssembly.GetTypeDefinition()
/// <summary>
/// Retrieves the specified type in this compilation.
/// Returns an <see cref="UnknownType"/> if the type cannot be found in this compilation.
/// </summary>
/// <remarks>
/// There can be multiple types with the same full name in a compilation, as a
/// full type name is only unique per assembly.
/// If there are multiple possible matches, this method will return just one of them.
/// When possible, use <see cref="IAssembly.GetTypeDefinition"/> instead to
/// retrieve a type from a specific assembly.
/// </remarks>
public static IType FindType(this ICompilation compilation, FullTypeName fullTypeName)
{
if (compilation == null)
throw new ArgumentNullException("compilation");
foreach (IAssembly asm in compilation.Assemblies) {
ITypeDefinition def = asm.GetTypeDefinition(fullTypeName);
if (def != null)
return def;
}
return new UnknownType(fullTypeName);
}
/// <summary>
/// Gets the type definition for the specified unresolved type.
/// Returns null if the unresolved type does not belong to this assembly.
/// </summary>
public static ITypeDefinition GetTypeDefinition(this IAssembly assembly, IUnresolvedTypeDefinition unresolved)
public static ITypeDefinition GetTypeDefinition(this IAssembly assembly, FullTypeName fullTypeName)
{
if (assembly == null)
throw new ArgumentNullException("assembly");
if (unresolved == null)
TopLevelTypeName topLevelTypeName = fullTypeName.TopLevelTypeName;
ITypeDefinition typeDef = assembly.GetTypeDefinition(topLevelTypeName);
if (typeDef == null)
return null;
if (unresolved.DeclaringTypeDefinition != null) {
ITypeDefinition parentType = GetTypeDefinition(assembly, unresolved.DeclaringTypeDefinition);
if (parentType == null)
return null;
foreach (var nestedType in parentType.NestedTypes) {
if (nestedType.Name == unresolved.Name && nestedType.TypeParameterCount == unresolved.TypeParameters.Count)
return nestedType;
}
return null;
} else {
return assembly.GetTypeDefinition(unresolved.Namespace, unresolved.Name, unresolved.TypeParameters.Count);
int typeParameterCount = topLevelTypeName.TypeParameterCount;
for (int i = 0; i < fullTypeName.NestingLevel; i++) {
string name = fullTypeName.GetNestedTypeName(i);
typeParameterCount += fullTypeName.GetNestedTypeAdditionalTypeParameterCount(i);
typeDef = FindNestedType(typeDef, name, typeParameterCount);
if (typeDef == null)
break;
}
return typeDef;
}
static ITypeDefinition FindNestedType(ITypeDefinition typeDef, string name, int typeParameterCount)
{
foreach (var nestedType in typeDef.NestedTypes) {
if (nestedType.Name == name && nestedType.TypeParameterCount == typeParameterCount)
return nestedType;
}
return null;
}
#endregion

312
ICSharpCode.NRefactory/TypeSystem/FullTypeName.cs

@ -0,0 +1,312 @@ @@ -0,0 +1,312 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Holds the full name of a type definition.
/// A full type name uniquely identifies a type definition within a single assembly.
/// </summary>
/// <remarks>
/// A full type name can only represent type definitions, not arbitrary types.
/// It does not include any type arguments, and can not refer to array or pointer types.
///
///
/// </remarks>
[Serializable]
public struct FullTypeName : IEquatable<FullTypeName>
{
[Serializable]
struct NestedTypeName
{
public readonly string Name;
public readonly int AdditionalTypeParameterCount;
public NestedTypeName(string name, int additionalTypeParameterCount)
{
if (name == null)
throw new ArgumentNullException("name");
this.Name = name;
this.AdditionalTypeParameterCount = additionalTypeParameterCount;
}
}
readonly TopLevelTypeName topLevelType;
readonly NestedTypeName[] nestedTypes;
FullTypeName(TopLevelTypeName topLevelTypeName, NestedTypeName[] nestedTypes)
{
this.topLevelType = topLevelTypeName;
this.nestedTypes = nestedTypes;
}
/// <summary>
/// Constructs a FullTypeName representing the given top-level type.
/// </summary>
/// <remarks>
/// FullTypeName has an implicit conversion operator from TopLevelTypeName,
/// so you can simply write:
/// <c>FullTypeName f = new TopLevelTypeName(...);</c>
/// </remarks>
public FullTypeName(TopLevelTypeName topLevelTypeName)
{
this.topLevelType = topLevelTypeName;
this.nestedTypes = null;
}
/// <summary>
/// Constructs a FullTypeName by parsing the given reflection name.
/// Note that FullTypeName can only represent type definition names. If the reflection name
/// might refer to a parameterized type or array etc., use
/// <see cref="ReflectionHelper.ParseReflectionName(string)"/> instead.
/// </summary>
/// <remarks>
/// Expected syntax: <c>NamespaceName '.' TopLevelTypeName ['`'#] { '+' NestedTypeName ['`'#] }</c>
/// where # are type parameter counts
/// </remarks>
public FullTypeName(string reflectionName)
{
int pos = reflectionName.IndexOf('+');
if (pos < 0) {
// top-level type
this.topLevelType = new TopLevelTypeName(reflectionName);
this.nestedTypes = null;
} else {
// nested type
string[] parts = reflectionName.Split('+');
this.topLevelType = new TopLevelTypeName(parts[0]);
this.nestedTypes = new NestedTypeName[parts.Length - 1];
for (int i = 0; i < nestedTypes.Length; i++) {
int tpc;
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(parts[i + 1], out tpc);
nestedTypes[i] = new NestedTypeName(name, tpc);
}
}
}
/// <summary>
/// Gets the top-level type name.
/// </summary>
public TopLevelTypeName TopLevelTypeName {
get { return topLevelType; }
}
/// <summary>
/// Gets whether this is a nested type.
/// </summary>
public bool IsNested {
get {
return nestedTypes != null;
}
}
/// <summary>
/// Gets the nesting level.
/// </summary>
public int NestingLevel {
get {
return nestedTypes != null ? nestedTypes.Length : 0;
}
}
/// <summary>
/// Gets the name of the type.
/// For nested types, this is the name of the innermost type.
/// </summary>
public string Name {
get {
if (nestedTypes != null)
return nestedTypes[nestedTypes.Length - 1].Name;
else
return topLevelType.Name;
}
}
public string ReflectionName {
get {
if (nestedTypes == null)
return topLevelType.ReflectionName;
StringBuilder b = new StringBuilder(topLevelType.ReflectionName);
foreach (NestedTypeName nt in nestedTypes) {
b.Append('+');
b.Append(nt.Name);
if (nt.AdditionalTypeParameterCount > 0) {
b.Append('`');
b.Append(nt.AdditionalTypeParameterCount);
}
}
return b.ToString();
}
}
/// <summary>
/// Gets the total type parameter count.
/// </summary>
public int TypeParameterCount {
get {
int tpc = topLevelType.TypeParameterCount;
if (nestedTypes != null) {
foreach (var nt in nestedTypes) {
tpc += nt.AdditionalTypeParameterCount;
}
}
return tpc;
}
}
/// <summary>
/// Gets the name of the nested type at the given level.
/// </summary>
public string GetNestedTypeName(int nestingLevel)
{
if (nestedTypes == null)
throw new InvalidOperationException();
return nestedTypes[nestingLevel].Name;
}
/// <summary>
/// Gets the number of additional type parameters of the nested type at the given level.
/// </summary>
public int GetNestedTypeAdditionalTypeParameterCount(int nestingLevel)
{
if (nestedTypes == null)
throw new InvalidOperationException();
return nestedTypes[nestingLevel].AdditionalTypeParameterCount;
}
/// <summary>
/// Gets the declaring type name.
/// </summary>
/// <exception cref="InvalidOperationException">This is a top-level type name.</exception>
public FullTypeName GetDeclaringType()
{
if (nestedTypes == null)
throw new InvalidOperationException();
if (nestedTypes.Length == 1)
return topLevelType;
NestedTypeName[] outerNestedTypeNames = new NestedTypeName[nestedTypes.Length - 1];
Array.Copy(nestedTypes, 0, outerNestedTypeNames, 0, outerNestedTypeNames.Length);
return new FullTypeName(topLevelType, nestedTypes);
}
/// <summary>
/// Gets a nested type name.
/// </summary>
public FullTypeName NestedType(string name, int additionalTypeParameterCount)
{
if (name == null)
throw new ArgumentNullException("name");
var newNestedType = new NestedTypeName(name, additionalTypeParameterCount);
if (nestedTypes == null)
return new FullTypeName(topLevelType, new[] { newNestedType });
NestedTypeName[] newNestedTypeNames = new NestedTypeName[nestedTypes.Length + 1];
nestedTypes.CopyTo(newNestedTypeNames, 0);
newNestedTypeNames[newNestedTypeNames.Length - 1] = newNestedType;
return new FullTypeName(topLevelType, newNestedTypeNames);
}
public static implicit operator FullTypeName(TopLevelTypeName topLevelTypeName)
{
return new FullTypeName(topLevelTypeName);
}
public override string ToString()
{
return this.ReflectionName;
}
#region Equals and GetHashCode implementation
public override bool Equals(object obj)
{
return obj is FullTypeName && Equals((FullTypeName)obj);
}
public bool Equals(FullTypeName other)
{
return FullTypeNameComparer.Ordinal.Equals(this, other);
}
public override int GetHashCode()
{
return FullTypeNameComparer.Ordinal.GetHashCode(this);
}
public static bool operator ==(FullTypeName left, FullTypeName right)
{
return left.Equals(right);
}
public static bool operator !=(FullTypeName left, FullTypeName right)
{
return !left.Equals(right);
}
#endregion
}
[Serializable]
public sealed class FullTypeNameComparer : IEqualityComparer<FullTypeName>
{
public static readonly FullTypeNameComparer Ordinal = new FullTypeNameComparer(StringComparer.Ordinal);
public static readonly FullTypeNameComparer OrdinalIgnoreCase = new FullTypeNameComparer(StringComparer.OrdinalIgnoreCase);
public readonly StringComparer NameComparer;
public FullTypeNameComparer(StringComparer nameComparer)
{
this.NameComparer = nameComparer;
}
public bool Equals(FullTypeName x, FullTypeName y)
{
if (x.NestingLevel != y.NestingLevel)
return false;
TopLevelTypeName topX = x.TopLevelTypeName;
TopLevelTypeName topY = y.TopLevelTypeName;
if (topX.TypeParameterCount == topY.TypeParameterCount
&& NameComparer.Equals(topX.Name, topY.Name)
&& NameComparer.Equals(topX.Namespace, topY.Namespace))
{
for (int i = 0; i < x.NestingLevel; i++) {
if (x.GetNestedTypeAdditionalTypeParameterCount(i) != y.GetNestedTypeAdditionalTypeParameterCount(i))
return false;
if (!NameComparer.Equals(x.GetNestedTypeName(i), y.GetNestedTypeName(i)))
return false;
}
return true;
}
return false;
}
public int GetHashCode(FullTypeName obj)
{
TopLevelTypeName top = obj.TopLevelTypeName;
int hash = NameComparer.GetHashCode(top.Name) ^ NameComparer.GetHashCode(top.Namespace) ^ top.TypeParameterCount;
unchecked {
for (int i = 0; i < obj.NestingLevel; i++) {
hash *= 31;
hash += NameComparer.GetHashCode(obj.Name) ^ obj.TypeParameterCount;
}
}
return hash;
}
}
}

2
ICSharpCode.NRefactory/TypeSystem/IAssembly.cs

@ -115,7 +115,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -115,7 +115,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// Gets the type definition for a top-level type.
/// </summary>
/// <remarks>This method uses ordinal name comparison, not the compilation's name comparer.</remarks>
ITypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount);
ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName);
/// <summary>
/// Gets all non-nested types in the assembly.

3
ICSharpCode.NRefactory/TypeSystem/ICompilation.cs

@ -37,6 +37,9 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -37,6 +37,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Gets the list of all assemblies in the compilation.
/// </summary>
/// <remarks>
/// This main assembly is the first entry in the list.
/// </remarks>
IList<IAssembly> Assemblies { get; }
/// <summary>

6
ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs

@ -30,6 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -30,6 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
{
TypeKind Kind { get; }
FullTypeName FullTypeName { get; }
IList<ITypeReference> BaseTypes { get; }
IList<IUnresolvedTypeParameter> TypeParameters { get; }
@ -119,6 +120,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -119,6 +120,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary>
IType EnumUnderlyingType { get; }
/// <summary>
/// Gets the full name of this type.
/// </summary>
FullTypeName FullTypeName { get; }
/// <summary>
/// Gets/Sets the declaring type (incl. type arguments, if any).
/// This property never returns null -- for top-level entities, it returns SharedTypes.UnknownType.

4
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs

@ -566,6 +566,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -566,6 +566,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return parts[0].Namespace; }
}
public FullTypeName FullTypeName {
get { return parts[0].FullTypeName; }
}
public DomRegion Region {
get { return parts[0].Region; }
}

26
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs

@ -39,8 +39,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -39,8 +39,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
string fullAssemblyName;
IList<IUnresolvedAttribute> assemblyAttributes;
IList<IUnresolvedAttribute> moduleAttributes;
Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition> typeDefinitions = new Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition>(FullNameAndTypeParameterCountComparer.Ordinal);
Dictionary<FullNameAndTypeParameterCount, ITypeReference> typeForwarders = new Dictionary<FullNameAndTypeParameterCount, ITypeReference>(FullNameAndTypeParameterCountComparer.Ordinal);
Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> typeDefinitions = new Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition>(TopLevelTypeNameComparer.Ordinal);
Dictionary<TopLevelTypeName, ITypeReference> typeForwarders = new Dictionary<TopLevelTypeName, ITypeReference>(TopLevelTypeNameComparer.Ordinal);
protected override void FreezeInternal()
{
@ -144,7 +144,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -144,7 +144,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (typeDefinition.DeclaringTypeDefinition != null)
throw new ArgumentException("Cannot add nested types.");
FreezableHelper.ThrowIfFrozen(this);
var key = new FullNameAndTypeParameterCount(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameters.Count);
var key = new TopLevelTypeName(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameters.Count);
typeDefinitions.Add(key, typeDefinition);
}
@ -157,7 +157,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -157,7 +157,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// </summary>
/// <param name="typeName">The name of the type.</param>
/// <param name="referencedType">The reference used to look up the type in the target assembly.</param>
public void AddTypeForwarder(FullNameAndTypeParameterCount typeName, ITypeReference referencedType)
public void AddTypeForwarder(TopLevelTypeName typeName, ITypeReference referencedType)
{
if (referencedType == null)
throw new ArgumentNullException("referencedType");
@ -187,7 +187,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -187,7 +187,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IUnresolvedTypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount)
{
var key = new FullNameAndTypeParameterCount(ns ?? string.Empty, name, typeParameterCount);
var key = new TopLevelTypeName(ns ?? string.Empty, name, typeParameterCount);
IUnresolvedTypeDefinition td;
if (typeDefinitions.TryGetValue(key, out td))
return td;
@ -216,9 +216,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -216,9 +216,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
//[NonSerialized]
//List<Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition>> cachedTypeDictionariesPerNameComparer;
//List<Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition>> cachedTypeDictionariesPerNameComparer;
Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition> GetTypeDictionary(StringComparer nameComparer)
Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> GetTypeDictionary(StringComparer nameComparer)
{
Debug.Assert(IsFrozen);
if (nameComparer == StringComparer.Ordinal)
@ -291,7 +291,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -291,7 +291,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
readonly DefaultUnresolvedAssembly unresolvedAssembly;
readonly ICompilation compilation;
readonly ITypeResolveContext context;
readonly Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition> unresolvedTypeDict;
readonly Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> unresolvedTypeDict;
readonly ConcurrentDictionary<IUnresolvedTypeDefinition, ITypeDefinition> typeDict = new ConcurrentDictionary<IUnresolvedTypeDefinition, ITypeDefinition>();
readonly INamespace rootNamespace;
@ -338,15 +338,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -338,15 +338,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return assembly == this;
}
public ITypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount)
public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
{
var key = new FullNameAndTypeParameterCount(ns ?? string.Empty, name, typeParameterCount);
IUnresolvedTypeDefinition td;
ITypeReference typeRef;
if (unresolvedAssembly.typeDefinitions.TryGetValue(key, out td))
if (unresolvedAssembly.typeDefinitions.TryGetValue(topLevelTypeName, out td))
return GetTypeDefinition(td);
else if (unresolvedAssembly.typeForwarders.TryGetValue(key, out typeRef))
else if (unresolvedAssembly.typeForwarders.TryGetValue(topLevelTypeName, out typeRef))
return typeRef.Resolve(compilation.TypeResolveContext).GetDefinition();
else
return null;
@ -453,7 +451,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -453,7 +451,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount)
{
var key = new FullNameAndTypeParameterCount(ns.FullName, name, typeParameterCount);
var key = new TopLevelTypeName(ns.FullName, name, typeParameterCount);
IUnresolvedTypeDefinition unresolvedTypeDef;
if (assembly.unresolvedTypeDict.TryGetValue(key, out unresolvedTypeDef))
return assembly.GetTypeDefinition(unresolvedTypeDef);

24
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeDefinition.cs

@ -141,24 +141,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -141,24 +141,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public override string ReflectionName {
get {
return this.FullTypeName.ReflectionName;
}
}
public FullTypeName FullTypeName {
get {
IUnresolvedTypeDefinition declaringTypeDef = this.DeclaringTypeDefinition;
if (declaringTypeDef != null) {
if (this.TypeParameters.Count > declaringTypeDef.TypeParameters.Count) {
return declaringTypeDef.ReflectionName + "+" + this.Name + "`" + (this.TypeParameters.Count - declaringTypeDef.TypeParameters.Count).ToString(CultureInfo.InvariantCulture);
} else {
return declaringTypeDef.ReflectionName + "+" + this.Name;
}
} else if (string.IsNullOrEmpty(namespaceName)) {
if (this.TypeParameters.Count > 0)
return this.Name + "`" + this.TypeParameters.Count.ToString(CultureInfo.InvariantCulture);
else
return this.Name;
return declaringTypeDef.FullTypeName.NestedType(this.Name, this.TypeParameters.Count - declaringTypeDef.TypeParameters.Count);
} else {
if (this.TypeParameters.Count > 0)
return namespaceName + "." + this.Name + "`" + this.TypeParameters.Count.ToString(CultureInfo.InvariantCulture);
else
return namespaceName + "." + this.Name;
return new TopLevelTypeName(namespaceName, this.Name, this.TypeParameters.Count);
}
}
}
@ -226,7 +220,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -226,7 +220,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
throw new ArgumentNullException("context");
if (context.CurrentAssembly == null)
throw new ArgumentException("An ITypeDefinition cannot be resolved in a context without a current assembly.");
return context.CurrentAssembly.GetTypeDefinition(this)
return context.CurrentAssembly.GetTypeDefinition(this.FullTypeName)
?? (IType)new UnknownType(this.Namespace, this.Name, this.TypeParameters.Count);
}

69
ICSharpCode.NRefactory/TypeSystem/Implementation/FullNameAndTypeParameterCount.cs

@ -21,73 +21,8 @@ using System.Collections.Generic; @@ -21,73 +21,8 @@ using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
[Serializable]
public struct FullNameAndTypeParameterCount : IEquatable<FullNameAndTypeParameterCount>
[Obsolete("This struct was renamed to 'TopLevelTypeName'.", true)]
public struct FullNameAndTypeParameterCount
{
public readonly string Namespace;
public readonly string Name;
public readonly int TypeParameterCount;
public FullNameAndTypeParameterCount(string nameSpace, string name, int typeParameterCount)
{
if (nameSpace == null)
throw new ArgumentNullException("nameSpace");
if (name == null)
throw new ArgumentNullException("name");
this.Namespace = nameSpace;
this.Name = name;
this.TypeParameterCount = typeParameterCount;
}
public override bool Equals(object obj)
{
return (obj is FullNameAndTypeParameterCount) && Equals((FullNameAndTypeParameterCount)obj);
}
public bool Equals(FullNameAndTypeParameterCount other)
{
return this.Namespace == other.Namespace && this.Name == other.Name && this.TypeParameterCount == other.TypeParameterCount;
}
public override int GetHashCode()
{
return Name.GetHashCode() ^ Namespace.GetHashCode() ^ TypeParameterCount;
}
public static bool operator ==(FullNameAndTypeParameterCount lhs, FullNameAndTypeParameterCount rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(FullNameAndTypeParameterCount lhs, FullNameAndTypeParameterCount rhs)
{
return !lhs.Equals(rhs);
}
}
[Serializable]
public sealed class FullNameAndTypeParameterCountComparer : IEqualityComparer<FullNameAndTypeParameterCount>
{
public static readonly FullNameAndTypeParameterCountComparer Ordinal = new FullNameAndTypeParameterCountComparer(StringComparer.Ordinal);
public static readonly FullNameAndTypeParameterCountComparer OrdinalIgnoreCase = new FullNameAndTypeParameterCountComparer(StringComparer.OrdinalIgnoreCase);
public readonly StringComparer NameComparer;
public FullNameAndTypeParameterCountComparer(StringComparer nameComparer)
{
this.NameComparer = nameComparer;
}
public bool Equals(FullNameAndTypeParameterCount x, FullNameAndTypeParameterCount y)
{
return x.TypeParameterCount == y.TypeParameterCount
&& NameComparer.Equals(x.Name, y.Name)
&& NameComparer.Equals(x.Namespace, y.Namespace);
}
public int GetHashCode(FullNameAndTypeParameterCount obj)
{
return NameComparer.GetHashCode(obj.Name) ^ NameComparer.GetHashCode(obj.Namespace) ^ obj.TypeParameterCount;
}
}
}

99
ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs

@ -28,24 +28,31 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -28,24 +28,31 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public sealed class GetClassTypeReference : ITypeReference, ISupportsInterning
{
readonly IAssemblyReference assembly;
readonly string nameSpace, name;
readonly int typeParameterCount;
readonly FullTypeName fullTypeName;
/// <summary>
/// Creates a new GetClassTypeReference that searches a top-level type.
/// Creates a new GetClassTypeReference that searches a type definition.
/// </summary>
/// <param name="nameSpace">The namespace name containing the type, e.g. "System.Collections.Generic".</param>
/// <param name="fullTypeName">The full name of the type.</param>
/// <param name="assembly">A reference to the assembly containing this type.
/// If this parameter is null, the GetClassTypeReference will search in all
/// assemblies belonging to the compilation.
/// </param>
public GetClassTypeReference(FullTypeName fullTypeName, IAssemblyReference assembly = null)
{
this.fullTypeName = fullTypeName;
this.assembly = assembly;
}
/// <summary>
/// Creates a new GetClassTypeReference that searches a top-level type in all assemblies.
/// </summary>
/// <param name="namespaceName">The namespace name containing the type, e.g. "System.Collections.Generic".</param>
/// <param name="name">The name of the type, e.g. "List".</param>
/// <param name="typeParameterCount">The number of type parameters, (e.g. 1 for List&lt;T&gt;).</param>
public GetClassTypeReference(string nameSpace, string name, int typeParameterCount = 0)
public GetClassTypeReference(string namespaceName, string name, int typeParameterCount = 0)
{
if (nameSpace == null)
throw new ArgumentNullException("nameSpace");
if (name == null)
throw new ArgumentNullException("name");
this.nameSpace = nameSpace;
this.name = name;
this.typeParameterCount = typeParameterCount;
this.fullTypeName = new TopLevelTypeName(namespaceName, name, typeParameterCount);
}
/// <summary>
@ -53,25 +60,33 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -53,25 +60,33 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// </summary>
/// <param name="assembly">A reference to the assembly containing this type.
/// If this parameter is null, the GetClassTypeReference will search in all assemblies belonging to the ICompilation.</param>
/// <param name="nameSpace">The namespace name containing the type, e.g. "System.Collections.Generic".</param>
/// <param name="namespaceName">The namespace name containing the type, e.g. "System.Collections.Generic".</param>
/// <param name="name">The name of the type, e.g. "List".</param>
/// <param name="typeParameterCount">The number of type parameters, (e.g. 1 for List&lt;T&gt;).</param>
public GetClassTypeReference(IAssemblyReference assembly, string nameSpace, string name, int typeParameterCount = 0)
public GetClassTypeReference(IAssemblyReference assembly, string namespaceName, string name, int typeParameterCount = 0)
{
if (nameSpace == null)
throw new ArgumentNullException("nameSpace");
if (name == null)
throw new ArgumentNullException("name");
this.assembly = assembly;
this.nameSpace = nameSpace;
this.name = name;
this.typeParameterCount = typeParameterCount;
this.fullTypeName = new TopLevelTypeName(namespaceName, name, typeParameterCount);
}
/// <summary>
/// Gets the assembly reference.
/// This property returns null if the GetClassTypeReference is searching in all assemblies
/// of the compilation.
/// </summary>
public IAssemblyReference Assembly { get { return assembly; } }
public string Namespace { get { return nameSpace; } }
public string Name { get { return name; } }
public int TypeParameterCount { get { return typeParameterCount; } }
/// <summary>
/// Gets the full name of the type this reference is searching for.
/// </summary>
public FullTypeName FullTypeName { get { return fullTypeName; } }
[Obsolete("Use the FullTypeName property instead. GetClassTypeReference now supports nested types, where the Namespace/Name/TPC tripel isn't sufficient for identifying the type.")]
public string Namespace { get { return fullTypeName.TopLevelTypeName.Namespace; } }
[Obsolete("Use the FullTypeName property instead. GetClassTypeReference now supports nested types, where the Namespace/Name/TPC tripel isn't sufficient for identifying the type.")]
public string Name { get { return fullTypeName.Name; } }
[Obsolete("Use the FullTypeName property instead. GetClassTypeReference now supports nested types, where the Namespace/Name/TPC tripel isn't sufficient for identifying the type.")]
public int TypeParameterCount { get { return fullTypeName.TypeParameterCount; } }
public IType Resolve(ITypeResolveContext context)
{
@ -80,52 +95,42 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -80,52 +95,42 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
IType type = null;
if (assembly == null) {
var compilation = context.Compilation;
foreach (var asm in new[] { context.CurrentAssembly }.Concat(compilation.Assemblies)) {
if (asm != null) {
type = asm.GetTypeDefinition(nameSpace, name, typeParameterCount);
if (context.CurrentAssembly != null) {
type = context.CurrentAssembly.GetTypeDefinition(fullTypeName);
}
if (type == null) {
var compilation = context.Compilation;
foreach (var asm in new[] { context.CurrentAssembly }.Concat(compilation.Assemblies)) {
type = asm.GetTypeDefinition(fullTypeName);
if (type != null)
return type;
break;
}
}
} else {
IAssembly asm = assembly.Resolve(context);
if (asm != null) {
type = asm.GetTypeDefinition(nameSpace, name, typeParameterCount);
type = asm.GetTypeDefinition(fullTypeName);
}
}
return type ?? new UnknownType(nameSpace, name, typeParameterCount);
return type ?? new UnknownType(fullTypeName);
}
public override string ToString()
{
string asmSuffix = (assembly != null ? ", " + assembly.ToString() : null);
if (typeParameterCount == 0)
return BuildQualifiedName(nameSpace, name) + asmSuffix;
else
return BuildQualifiedName(nameSpace, name) + "`" + typeParameterCount + asmSuffix;
}
static string BuildQualifiedName (string name1, string name2)
{
if (string.IsNullOrEmpty (name1))
return name2;
if (string.IsNullOrEmpty (name2))
return name1;
return name1 + "." + name2;
return fullTypeName.ToString() + (assembly != null ? ", " + assembly.ToString() : null);
}
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
return 33 * assembly.GetHashCode() + 27 * nameSpace.GetHashCode() + name.GetHashCode() + typeParameterCount;
return 33 * assembly.GetHashCode() + fullTypeName.GetHashCode();
}
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
GetClassTypeReference o = other as GetClassTypeReference;
return o != null && assembly == o.assembly && name == o.name && nameSpace == o.nameSpace && typeParameterCount == o.typeParameterCount;
return o != null && assembly == o.assembly && fullTypeName == o.fullTypeName;
}
}
}

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

@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (typeRef == null)
return SpecialType.UnknownType;
foreach (IAssembly asm in compilation.Assemblies) {
var typeDef = asm.GetTypeDefinition(typeRef.Namespace, typeRef.Name, typeRef.TypeParameterCount);
var typeDef = asm.GetTypeDefinition(new TopLevelTypeName(typeRef.Namespace, typeRef.Name, typeRef.TypeParameterCount));
if (typeDef != null)
return typeDef;
}

50
ICSharpCode.NRefactory/TypeSystem/Implementation/UnknownType.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
@ -26,9 +27,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -26,9 +27,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
[Serializable]
public class UnknownType : AbstractType, ITypeReference
{
readonly string namespaceName;
readonly string name;
readonly int typeParameterCount;
readonly bool namespaceKnown;
readonly FullTypeName fullTypeName;
/// <summary>
/// Creates a new unknown type.
@ -40,9 +40,24 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -40,9 +40,24 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
if (name == null)
throw new ArgumentNullException("name");
this.namespaceName = namespaceName;
this.name = name;
this.typeParameterCount = typeParameterCount;
this.namespaceKnown = namespaceName != null;
this.fullTypeName = new TopLevelTypeName(namespaceName ?? string.Empty, name, typeParameterCount);
}
/// <summary>
/// Creates a new unknown type.
/// </summary>
/// <param name="fullTypeName">Full name of the unknown type.</param>
public UnknownType(FullTypeName fullTypeName)
{
if (fullTypeName.Name == null) {
Debug.Assert(fullTypeName == default(FullTypeName));
this.namespaceKnown = false;
this.fullTypeName = new TopLevelTypeName(string.Empty, "?", 0);
} else {
this.namespaceKnown = true;
this.fullTypeName = fullTypeName;
}
}
public override TypeKind Kind {
@ -62,15 +77,19 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -62,15 +77,19 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public override string Name {
get { return name; }
get { return fullTypeName.Name; }
}
public override string Namespace {
get { return namespaceName ?? string.Empty; }
get { return fullTypeName.TopLevelTypeName.Namespace; }
}
public override string ReflectionName {
get { return "?"; }
get { return namespaceKnown ? fullTypeName.ReflectionName : "?"; }
}
public override int TypeParameterCount {
get { return fullTypeName.TypeParameterCount; }
}
public override bool? IsReferenceType {
@ -79,14 +98,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -79,14 +98,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public override int GetHashCode()
{
int hashCode = 0;
unchecked {
if (namespaceName != null)
hashCode += 1000000007 * namespaceName.GetHashCode();
hashCode += 1000000009 * name.GetHashCode();
hashCode += 1000000021 * typeParameterCount.GetHashCode();
}
return hashCode;
return (namespaceKnown ? 812571 : 12651) ^ fullTypeName.GetHashCode();
}
public override bool Equals(IType other)
@ -94,12 +106,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -94,12 +106,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
UnknownType o = other as UnknownType;
if (o == null)
return false;
return this.namespaceName == o.namespaceName && this.name == o.name && this.typeParameterCount == o.typeParameterCount;
return this.namespaceKnown == o.namespaceKnown && this.fullTypeName == o.fullTypeName;
}
public override string ToString()
{
return "[UnknownType " + this.FullName + "]";
return "[UnknownType " + fullTypeName.ReflectionName + "]";
}
}
}

12
ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs

@ -56,17 +56,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -56,17 +56,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
{
return type.ToTypeReference().Resolve(compilation.TypeResolveContext);
}
/// <summary>
/// Retrieves the specified type in this compilation.
/// Returns <see cref="SpecialType.UnknownType"/> if the type cannot be found in this compilation.
/// </summary>
[Obsolete("Use ReflectionHelper.ParseReflectionName(reflectionTypeName).Resolve(compilation.TypeResolveContext) instead. " +
"Make sure to read the ParseReflectionName() documentation for caveats.")]
public static IType FindType(this ICompilation compilation, string reflectionTypeName)
{
return ParseReflectionName(reflectionTypeName).Resolve(compilation.TypeResolveContext);
}
#endregion
#region Type.ToTypeReference()
@ -218,6 +207,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -218,6 +207,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <see cref="ITypeResolveContext.CurrentAssembly"/> first, and if the type is not found there,
/// it will look in all other assemblies of the compilation.
/// </remarks>
/// <seealso cref="FullTypeName(string)"/>
public static ITypeReference ParseReflectionName(string reflectionTypeName)
{
if (reflectionTypeName == null)

144
ICSharpCode.NRefactory/TypeSystem/TopLevelTypeName.cs

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Holds the name of a top-level type.
/// This struct cannot refer to nested classes.
/// </summary>
[Serializable]
public struct TopLevelTypeName : IEquatable<TopLevelTypeName>
{
readonly string namespaceName;
readonly string name;
readonly int typeParameterCount;
public TopLevelTypeName(string namespaceName, string name, int typeParameterCount = 0)
{
if (namespaceName == null)
throw new ArgumentNullException("namespaceName");
if (name == null)
throw new ArgumentNullException("name");
this.namespaceName = namespaceName;
this.name = name;
this.typeParameterCount = typeParameterCount;
}
public TopLevelTypeName(string reflectionName)
{
int pos = reflectionName.LastIndexOf('.');
if (pos < 0) {
namespaceName = string.Empty;
name = reflectionName;
} else {
namespaceName = reflectionName.Substring(0, pos);
name = reflectionName.Substring(pos + 1);
}
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount);
}
public string Namespace {
get { return namespaceName; }
}
public string Name {
get { return name; }
}
public int TypeParameterCount {
get { return typeParameterCount; }
}
public string ReflectionName {
get {
StringBuilder b = new StringBuilder();
if (!string.IsNullOrEmpty(namespaceName)) {
b.Append(namespaceName);
b.Append('.');
}
b.Append(name);
if (typeParameterCount > 0) {
b.Append('`');
b.Append(typeParameterCount);
}
return b.ToString();
}
}
public override string ToString()
{
return this.ReflectionName;
}
public override bool Equals(object obj)
{
return (obj is TopLevelTypeName) && Equals((TopLevelTypeName)obj);
}
public bool Equals(TopLevelTypeName other)
{
return this.namespaceName == other.namespaceName && this.name == other.name && this.typeParameterCount == other.typeParameterCount;
}
public override int GetHashCode()
{
return (name != null ? name.GetHashCode() : 0) ^ (namespaceName != null ? namespaceName.GetHashCode() : 0) ^ typeParameterCount;
}
public static bool operator ==(TopLevelTypeName lhs, TopLevelTypeName rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(TopLevelTypeName lhs, TopLevelTypeName rhs)
{
return !lhs.Equals(rhs);
}
}
[Serializable]
public sealed class TopLevelTypeNameComparer : IEqualityComparer<TopLevelTypeName>
{
public static readonly TopLevelTypeNameComparer Ordinal = new TopLevelTypeNameComparer(StringComparer.Ordinal);
public static readonly TopLevelTypeNameComparer OrdinalIgnoreCase = new TopLevelTypeNameComparer(StringComparer.OrdinalIgnoreCase);
public readonly StringComparer NameComparer;
public TopLevelTypeNameComparer(StringComparer nameComparer)
{
this.NameComparer = nameComparer;
}
public bool Equals(TopLevelTypeName x, TopLevelTypeName y)
{
return x.TypeParameterCount == y.TypeParameterCount
&& NameComparer.Equals(x.Name, y.Name)
&& NameComparer.Equals(x.Namespace, y.Namespace);
}
public int GetHashCode(TopLevelTypeName obj)
{
return NameComparer.GetHashCode(obj.Name) ^ NameComparer.GetHashCode(obj.Namespace) ^ obj.TypeParameterCount;
}
}
}
Loading…
Cancel
Save