7 changed files with 270 additions and 11 deletions
@ -0,0 +1,230 @@
@@ -0,0 +1,230 @@
|
||||
// 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.Collections.ObjectModel; |
||||
using System.Diagnostics; |
||||
using System.Linq; |
||||
using System.Text; |
||||
|
||||
namespace ICSharpCode.NRefactory.TypeSystem.Implementation |
||||
{ |
||||
/// <summary>
|
||||
/// ConstructedType represents an instance of a generic type.
|
||||
/// Example: List<string>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When getting the Members, this type modifies the lists in such a way that the
|
||||
/// <see cref="GenericReturnType"/>s are replaced with the return types in the
|
||||
/// type arguments collection.
|
||||
/// </remarks>
|
||||
public class ConstructedType : Immutable, IType |
||||
{ |
||||
readonly ITypeDefinition genericType; |
||||
readonly IType[] typeArguments; |
||||
|
||||
public ConstructedType(ITypeDefinition genericType, IEnumerable<IType> typeArguments) |
||||
{ |
||||
if (genericType == null) |
||||
throw new ArgumentNullException("genericType"); |
||||
if (typeArguments == null) |
||||
throw new ArgumentNullException("typeArguments"); |
||||
this.genericType = genericType; |
||||
this.typeArguments = typeArguments.ToArray(); // copy input array to ensure it isn't modified
|
||||
if (this.typeArguments.Length == 0) |
||||
throw new ArgumentException("Cannot use ConstructedType with 0 type arguments."); |
||||
if (genericType.TypeParameterCount != this.typeArguments.Length) |
||||
throw new ArgumentException("Number of type arguments must match the type definition's number of type parameters"); |
||||
for (int i = 0; i < this.typeArguments.Length; i++) { |
||||
if (this.typeArguments[i] == null) |
||||
throw new ArgumentNullException("typeArguments[" + i + "]"); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Fast internal version of the constructor. (no safety checks)
|
||||
/// Keeps the array that was passed and assumes it won't be modified.
|
||||
/// </summary>
|
||||
internal ConstructedType(ITypeDefinition genericType, IType[] typeArguments) |
||||
{ |
||||
Debug.Assert(genericType.TypeParameterCount == typeArguments.Length); |
||||
this.genericType = genericType; |
||||
this.typeArguments = typeArguments; |
||||
} |
||||
|
||||
public bool? IsReferenceType { |
||||
get { return genericType.IsReferenceType; } |
||||
} |
||||
|
||||
public IType DeclaringType { |
||||
get { return genericType.DeclaringType; } |
||||
} |
||||
|
||||
public int TypeParameterCount { |
||||
get { return genericType.TypeParameterCount; } |
||||
} |
||||
|
||||
public string FullName { |
||||
get { return genericType.FullName; } |
||||
} |
||||
|
||||
public string Name { |
||||
get { return genericType.Name; } |
||||
} |
||||
|
||||
public string Namespace { |
||||
get { return genericType.Namespace;} |
||||
} |
||||
|
||||
public string DotNetName { |
||||
get { |
||||
StringBuilder b = new StringBuilder(genericType.DotNetName); |
||||
b.Append('['); |
||||
for (int i = 0; i < typeArguments.Length; i++) { |
||||
if (i > 0) |
||||
b.Append(','); |
||||
b.Append('['); |
||||
b.Append(typeArguments[i].DotNetName); |
||||
b.Append(']'); |
||||
} |
||||
b.Append(']'); |
||||
return b.ToString(); |
||||
} |
||||
} |
||||
|
||||
public IType GetElementType() |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
|
||||
public ReadOnlyCollection<IType> TypeArguments { |
||||
get { |
||||
return Array.AsReadOnly(typeArguments); |
||||
} |
||||
} |
||||
|
||||
public ITypeDefinition GetDefinition() |
||||
{ |
||||
return genericType; |
||||
} |
||||
|
||||
public IType Resolve(ITypeResolveContext context) |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
public IType GetBaseType(ITypeResolveContext context) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public IList<IType> GetNestedTypes(ITypeResolveContext context) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public IList<IMethod> GetMethods(ITypeResolveContext context) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public IList<IProperty> GetProperties(ITypeResolveContext context) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public IList<IField> GetFields(ITypeResolveContext context) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public IList<IEvent> GetEvents(ITypeResolveContext context) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public override bool Equals(object obj) |
||||
{ |
||||
return Equals(obj as IType); |
||||
} |
||||
|
||||
public bool Equals(IType other) |
||||
{ |
||||
ConstructedType c = other as ConstructedType; |
||||
if (c == null || typeArguments.Length != c.typeArguments.Length) |
||||
return false; |
||||
if (genericType.Equals(c.genericType)) { |
||||
for (int i = 0; i < typeArguments.Length; i++) { |
||||
if (!typeArguments[i].Equals(c.typeArguments[i])) |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
public override int GetHashCode() |
||||
{ |
||||
int hashCode = genericType.GetHashCode(); |
||||
unchecked { |
||||
foreach (var ta in typeArguments) { |
||||
hashCode *= 1000000007; |
||||
hashCode += 1000000009 * ta.GetHashCode(); |
||||
} |
||||
} |
||||
return hashCode; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// ConstructedTypeReference is a reference to generic class that specifies the type parameters.
|
||||
/// Example: List<string>
|
||||
/// </summary>
|
||||
public class ConstructedTypeReference : AbstractTypeReference |
||||
{ |
||||
readonly ITypeReference genericType; |
||||
readonly ITypeReference[] typeArguments; |
||||
|
||||
public ConstructedTypeReference(ITypeReference genericType, IEnumerable<ITypeReference> typeArguments) |
||||
{ |
||||
if (genericType == null) |
||||
throw new ArgumentNullException("genericType"); |
||||
if (typeArguments == null) |
||||
throw new ArgumentNullException("typeArguments"); |
||||
this.genericType = genericType; |
||||
this.typeArguments = typeArguments.ToArray(); |
||||
for (int i = 0; i < this.typeArguments.Length; i++) { |
||||
if (this.typeArguments[i] == null) |
||||
throw new ArgumentNullException("typeArguments[" + i + "]"); |
||||
} |
||||
} |
||||
|
||||
public ITypeReference GenericType { |
||||
get { return genericType; } |
||||
} |
||||
|
||||
public ReadOnlyCollection<ITypeReference> TypeArguments { |
||||
get { |
||||
return Array.AsReadOnly(typeArguments); |
||||
} |
||||
} |
||||
|
||||
public override IType Resolve(ITypeResolveContext context) |
||||
{ |
||||
ITypeDefinition baseTypeDef = genericType.Resolve(context).GetDefinition(); |
||||
if (baseTypeDef == null) |
||||
return SharedTypes.UnknownType; |
||||
int tpc = baseTypeDef.TypeParameterCount; |
||||
if (tpc == 0) |
||||
return baseTypeDef; |
||||
IType[] resolvedTypes = new IType[tpc]; |
||||
for (int i = 0; i < resolvedTypes.Length; i++) { |
||||
if (i < typeArguments.Length) |
||||
resolvedTypes[i] = typeArguments[i].Resolve(context); |
||||
else |
||||
resolvedTypes[i] = SharedTypes.UnknownType; |
||||
} |
||||
return new ConstructedType(baseTypeDef, resolvedTypes); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
TypeSystem API: |
||||
* ITypeReference extends IFreezable? |
||||
either: |
||||
- make sure all ITypeReference implementations correctly freeze their contained types |
||||
or: |
||||
- remove IFreezable from type references |
||||
|
||||
* For clarity: move all ITypeReference members except for Resolve() to IType? |
||||
|
||||
* Decide on the fate of ISupportsInterning |
||||
|
||||
* Try to build SharedTypes for void, int, etc. |
||||
Take care of equality with the real System.Void, System.Int32 etc. |
Loading…
Reference in new issue