Browse Source

Fix #1085: The type system can now parameterize not just type definitions, but also unknown types.

This improves decompilation when references assemblies cannot be found.
pull/1087/head
Daniel Grunwald 8 years ago
parent
commit
c869a4fc16
  1. 9
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs
  2. 12
      ICSharpCode.Decompiler/CSharp/Resolver/TypeInference.cs
  3. 58
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  4. 7
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  5. 6
      ICSharpCode.Decompiler/TypeSystem/IType.cs
  6. 2
      ICSharpCode.Decompiler/TypeSystem/ITypeDefinition.cs
  7. 6
      ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs
  8. 7
      ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractType.cs
  9. 6
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs
  10. 37
      ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs
  11. 9
      ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs
  12. 4
      ICSharpCode.Decompiler/TypeSystem/NullableType.cs
  13. 69
      ICSharpCode.Decompiler/TypeSystem/ParameterizedType.cs

9
ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs

@ -477,9 +477,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -477,9 +477,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
{
ParameterizedType pt = interfaceType as ParameterizedType;
if (pt != null) {
KnownTypeCode tc = pt.GetDefinition().KnownTypeCode;
if (tc == KnownTypeCode.IListOfT || tc == KnownTypeCode.ICollectionOfT || tc == KnownTypeCode.IEnumerableOfT || tc == KnownTypeCode.IReadOnlyListOfT) {
return pt.GetTypeArgument(0);
switch (pt.GetDefinition()?.KnownTypeCode) {
case KnownTypeCode.IListOfT:
case KnownTypeCode.ICollectionOfT:
case KnownTypeCode.IEnumerableOfT:
case KnownTypeCode.IReadOnlyListOfT:
return pt.GetTypeArgument(0);
}
}
return null;

12
ICSharpCode.Decompiler/CSharp/Resolver/TypeInference.cs

@ -596,7 +596,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -596,7 +596,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
ParameterizedType pU = U as ParameterizedType;
ParameterizedType pV = V as ParameterizedType;
if (pU != null && pV != null
&& object.Equals(pU.GetDefinition(), pV.GetDefinition())
&& object.Equals(pU.GenericType, pV.GenericType)
&& pU.TypeParameterCount == pV.TypeParameterCount)
{
Log.Indent();
@ -657,7 +657,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -657,7 +657,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
ParameterizedType uniqueBaseType = null;
foreach (IType baseU in U.GetAllBaseTypes()) {
ParameterizedType pU = baseU as ParameterizedType;
if (pU != null && object.Equals(pU.GetDefinition(), pV.GetDefinition()) && pU.TypeParameterCount == pV.TypeParameterCount) {
if (pU != null && object.Equals(pU.GenericType, pV.GenericType) && pU.TypeParameterCount == pV.TypeParameterCount) {
if (uniqueBaseType == null)
uniqueBaseType = pU;
else
@ -671,7 +671,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -671,7 +671,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
IType Vi = pV.GetTypeArgument(i);
if (Ui.IsReferenceType == true) {
// look for variance
ITypeParameter Xi = pV.GetDefinition().TypeParameters[i];
ITypeParameter Xi = pV.TypeParameters[i];
switch (Xi.Variance) {
case VarianceModifier.Covariant:
MakeLowerBoundInference(Ui, Vi);
@ -697,7 +697,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -697,7 +697,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
{
if (rt == null || rt.TypeParameterCount != 1)
return false;
switch (rt.GetDefinition().KnownTypeCode) {
switch (rt.GetDefinition()?.KnownTypeCode) {
case KnownTypeCode.IEnumerableOfT:
case KnownTypeCode.ICollectionOfT:
case KnownTypeCode.IListOfT:
@ -743,7 +743,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -743,7 +743,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
ParameterizedType uniqueBaseType = null;
foreach (IType baseV in V.GetAllBaseTypes()) {
ParameterizedType pV = baseV as ParameterizedType;
if (pV != null && object.Equals(pU.GetDefinition(), pV.GetDefinition()) && pU.TypeParameterCount == pV.TypeParameterCount) {
if (pV != null && object.Equals(pU.GenericType, pV.GenericType) && pU.TypeParameterCount == pV.TypeParameterCount) {
if (uniqueBaseType == null)
uniqueBaseType = pV;
else
@ -757,7 +757,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -757,7 +757,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
IType Vi = uniqueBaseType.GetTypeArgument(i);
if (Ui.IsReferenceType == true) {
// look for variance
ITypeParameter Xi = pU.GetDefinition().TypeParameters[i];
ITypeParameter Xi = pU.TypeParameters[i];
switch (Xi.Variance) {
case VarianceModifier.Covariant:
MakeUpperBoundInference(Ui, Vi);

58
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -233,10 +233,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -233,10 +233,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
ParameterizedType pt = type as ParameterizedType;
if (pt != null) {
if (pt.Name == "Nullable" && pt.Namespace == "System" && pt.TypeParameterCount == 1) {
if (pt.IsKnownType(KnownTypeCode.NullableOfT)) {
return ConvertType(pt.TypeArguments[0]).MakeNullableType();
}
return ConvertTypeHelper(pt.GetDefinition(), pt.TypeArguments);
return ConvertTypeHelper(pt.GenericType, pt.TypeArguments);
}
ITypeDefinition typeDef = type as ITypeDefinition;
if (typeDef != null) {
@ -254,22 +254,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -254,22 +254,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return new SimpleType(type.Name);
}
AstType ConvertTypeHelper(ITypeDefinition typeDef, IReadOnlyList<IType> typeArguments)
AstType ConvertTypeHelper(IType genericType, IReadOnlyList<IType> typeArguments)
{
Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount);
string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode);
if (keyword != null)
return new PrimitiveType(keyword);
Debug.Assert(typeArguments.Count >= genericType.TypeParameterCount);
Debug.Assert(genericType is ITypeDefinition || genericType.Kind == TypeKind.Unknown);
ITypeDefinition typeDef = genericType as ITypeDefinition;
if (typeDef != null) {
string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode);
if (keyword != null)
return new PrimitiveType(keyword);
}
// The number of type parameters belonging to outer classes
int outerTypeParameterCount;
if (typeDef.DeclaringType != null)
outerTypeParameterCount = typeDef.DeclaringType.TypeParameterCount;
else
outerTypeParameterCount = 0;
int outerTypeParameterCount = genericType.DeclaringType?.TypeParameterCount ?? 0;
if (resolver != null) {
if (resolver != null && typeDef != null) {
// Look if there's an alias to the target type
if (UseAliases) {
for (ResolvedUsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) {
@ -297,32 +297,32 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -297,32 +297,32 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
if (!trr.IsError && TypeMatches(trr.Type, typeDef, typeArguments)) {
// We can use the short type name
SimpleType shortResult = new SimpleType(typeDef.Name);
AddTypeArguments(shortResult, typeDef, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount);
AddTypeArguments(shortResult, typeDef.TypeParameters, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount);
return shortResult;
}
}
}
if (AlwaysUseShortTypeNames) {
var shortResult = new SimpleType(typeDef.Name);
AddTypeArguments(shortResult, typeDef, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount);
if (AlwaysUseShortTypeNames || (typeDef == null && genericType.DeclaringType == null)) {
var shortResult = new SimpleType(genericType.Name);
AddTypeArguments(shortResult, genericType.TypeParameters, typeArguments, outerTypeParameterCount, genericType.TypeParameterCount);
return shortResult;
}
MemberType result = new MemberType();
if (typeDef.DeclaringTypeDefinition != null) {
if (genericType.DeclaringType != null) {
// Handle nested types
result.Target = ConvertTypeHelper(typeDef.DeclaringTypeDefinition, typeArguments);
result.Target = ConvertTypeHelper(genericType.DeclaringType, typeArguments);
} else {
// Handle top-level types
if (string.IsNullOrEmpty(typeDef.Namespace)) {
if (string.IsNullOrEmpty(genericType.Namespace)) {
result.Target = new SimpleType("global");
result.IsDoubleColon = true;
} else {
result.Target = ConvertNamespace(typeDef.Namespace);
result.Target = ConvertNamespace(genericType.Namespace);
}
}
result.MemberName = typeDef.Name;
AddTypeArguments(result, typeDef, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount);
result.MemberName = genericType.Name;
AddTypeArguments(result, genericType.TypeParameters, typeArguments, outerTypeParameterCount, genericType.TypeParameterCount);
return result;
}
@ -348,21 +348,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -348,21 +348,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return true;
}
}
/// <summary>
/// Adds type arguments to the result type.
/// </summary>
/// <param name="result">The result AST node (a SimpleType or MemberType)</param>
/// <param name="typeDef">The type definition that owns the type parameters</param>
/// <param name="typeParameters">The type parameters</param>
/// <param name="typeArguments">The list of type arguments</param>
/// <param name="startIndex">Index of first type argument to add</param>
/// <param name="endIndex">Index after last type argument to add</param>
void AddTypeArguments(AstType result, ITypeDefinition typeDef, IReadOnlyList<IType> typeArguments, int startIndex, int endIndex)
void AddTypeArguments(AstType result, IReadOnlyList<ITypeParameter> typeParameters, IReadOnlyList<IType> typeArguments, int startIndex, int endIndex)
{
Debug.Assert(endIndex <= typeDef.TypeParameterCount);
Debug.Assert(endIndex <= typeParameters.Count);
for (int i = startIndex; i < endIndex; i++) {
if (ConvertUnboundTypeArguments && typeArguments[i].Kind == TypeKind.UnboundTypeArgument) {
result.AddChild(new SimpleType(typeDef.TypeParameters[i].Name), Roles.TypeArgument);
result.AddChild(new SimpleType(typeParameters[i].Name), Roles.TypeArgument);
} else {
result.AddChild(ConvertType(typeArguments[i]), Roles.TypeArgument);
}

7
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -223,9 +223,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -223,9 +223,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
IMethod method;
if (!methodLookupCache.TryGetValue(methodReference, out method)) {
method = FindNonGenericMethod(methodReference.GetElementMethod());
if (method == null) {
method = CreateFakeMethod(methodReference);
}
if (methodReference.CallingConvention == MethodCallingConvention.VarArg) {
method = new VarArgInstanceMethod(
method,
@ -254,7 +251,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -254,7 +251,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
ITypeDefinition typeDef = Resolve(methodReference.DeclaringType).GetDefinition();
if (typeDef == null)
return null;
return CreateFakeMethod(methodReference);
IEnumerable<IMethod> methods;
if (methodReference.Name == ".ctor") {
methods = typeDef.GetConstructors();
@ -286,7 +283,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -286,7 +283,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
continue;
return method;
}
return null;
return CreateFakeMethod(methodReference);
}
static bool CompareTypes(IType a, IType b)

6
ICSharpCode.Decompiler/TypeSystem/IType.cs

@ -81,6 +81,12 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -81,6 +81,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
int TypeParameterCount { get; }
/// <summary>
/// Gets the type parameters.
/// Returns an empty list if this type is not generic.
/// </summary>
IReadOnlyList<ITypeParameter> TypeParameters { get; }
/// <summary>
/// Gets the type arguments passed to this type.
/// If this type is a generic type definition that is not parameterized, this property returns the type parameters,

2
ICSharpCode.Decompiler/TypeSystem/ITypeDefinition.cs

@ -101,8 +101,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -101,8 +101,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Non-partial classes have a single part that represents the whole class.
/// </summary>
IReadOnlyList<IUnresolvedTypeDefinition> Parts { get; }
IReadOnlyList<ITypeParameter> TypeParameters { get; }
IReadOnlyList<ITypeDefinition> NestedTypes { get; }
IReadOnlyList<IMember> Members { get; }

6
ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs

@ -204,8 +204,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -204,8 +204,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return 0; }
}
IReadOnlyList<ITypeParameter> IType.TypeParameters {
get { return EmptyList<ITypeParameter>.Instance; }
}
IReadOnlyList<IType> IType.TypeArguments {
get { return Empty<IType>.Array; }
get { return EmptyList<IType>.Instance; }
}
public abstract IEnumerable<IType> DirectBaseTypes { get; }

7
ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractType.cs

@ -59,9 +59,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -59,9 +59,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return 0; }
}
readonly static IReadOnlyList<IType> emptyTypeArguments = new IType[0];
public virtual IReadOnlyList<ITypeParameter> TypeParameters {
get { return EmptyList<ITypeParameter>.Instance; }
}
public virtual IReadOnlyList<IType> TypeArguments {
get { return emptyTypeArguments; }
get { return EmptyList<IType>.Instance; }
}
public virtual IType DeclaringType {

6
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs

@ -457,11 +457,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -457,11 +457,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return parts[0].TypeParameters.Count; }
}
public IReadOnlyList<IType> TypeArguments {
get {
return TypeParameters;
}
}
public IReadOnlyList<IType> TypeArguments => TypeParameters;
#region DirectBaseTypes
IList<IType> directBaseTypes;

37
ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// 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.Threading;
using ICSharpCode.Decompiler.Util;
@ -26,6 +27,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -26,6 +27,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
static ITypeParameter[] methodTypeParameters = { new DummyTypeParameter(SymbolKind.Method, 0) };
static ITypeParameter[] classTypeParameters = { new DummyTypeParameter(SymbolKind.TypeDefinition, 0) };
static IReadOnlyList<ITypeParameter>[] classTypeParameterLists = { EmptyList<ITypeParameter>.Instance };
public static ITypeParameter GetMethodTypeParameter(int index)
{
@ -60,7 +62,38 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -60,7 +62,38 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
return tps[index];
}
/// <summary>
/// Gets a list filled with dummy type parameters.
/// </summary>
internal static IReadOnlyList<ITypeParameter> GetClassTypeParameterList(int length)
{
IReadOnlyList<ITypeParameter>[] tps = classTypeParameterLists;
while (length >= tps.Length) {
// We don't have a normal type parameter for this index, so we need to extend our array.
// Because the array can be used concurrently from multiple threads, we have to use
// Interlocked.CompareExchange.
IReadOnlyList<ITypeParameter>[] newTps = new IReadOnlyList<ITypeParameter>[length + 1];
tps.CopyTo(newTps, 0);
for (int i = tps.Length; i < newTps.Length; i++) {
var newList = new ITypeParameter[i];
for (int j = 0; j < newList.Length; j++) {
newList[j] = GetClassTypeParameter(j);
}
newTps[i] = newList;
}
var oldTps = Interlocked.CompareExchange(ref classTypeParameterLists, newTps, tps);
if (oldTps == tps) {
// exchange successful
tps = newTps;
} else {
// exchange not successful
tps = oldTps;
}
}
return tps[length];
}
sealed class NormalizeMethodTypeParametersVisitor : TypeVisitor
{
public override IType VisitTypeParameter(ITypeParameter type)
@ -83,7 +116,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -83,7 +116,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
}
static readonly NormalizeMethodTypeParametersVisitor normalizeMethodTypeParameters = new NormalizeMethodTypeParametersVisitor();
static readonly NormalizeClassTypeParametersVisitor normalizeClassTypeParameters = new NormalizeClassTypeParametersVisitor();

9
ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
@ -91,10 +92,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -91,10 +92,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return namespaceKnown ? fullTypeName.ReflectionName : "?"; }
}
public override int TypeParameterCount {
get { return fullTypeName.TypeParameterCount; }
}
public override int TypeParameterCount => fullTypeName.TypeParameterCount;
public override IReadOnlyList<ITypeParameter> TypeParameters => DummyTypeParameter.GetClassTypeParameterList(TypeParameterCount);
public override IReadOnlyList<IType> TypeArguments => TypeParameters;
public override bool? IsReferenceType {
get { return isReferenceType; }
}

4
ICSharpCode.Decompiler/TypeSystem/NullableType.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (type == null)
throw new ArgumentNullException("type");
ParameterizedType pt = type as ParameterizedType;
return pt != null && pt.TypeParameterCount == 1 && pt.GetDefinition().KnownTypeCode == KnownTypeCode.NullableOfT;
return pt != null && pt.TypeParameterCount == 1 && pt.GenericType.IsKnownType(KnownTypeCode.NullableOfT);
}
public static bool IsNonNullableValueType(IType type)
@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (type == null)
throw new ArgumentNullException("type");
ParameterizedType pt = type as ParameterizedType;
if (pt != null && pt.TypeParameterCount == 1 && pt.GetDefinition().KnownTypeCode == KnownTypeCode.NullableOfT)
if (pt != null && pt.TypeParameterCount == 1 && pt.GenericType.IsKnownType(KnownTypeCode.NullableOfT))
return pt.GetTypeArgument(0);
else
return type;

69
ICSharpCode.Decompiler/TypeSystem/ParameterizedType.cs

@ -36,12 +36,12 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -36,12 +36,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// the type arguments.
/// </remarks>
[Serializable]
public sealed class ParameterizedType : IType, ICompilationProvider
public sealed class ParameterizedType : IType
{
readonly ITypeDefinition genericType;
readonly IType genericType;
readonly IType[] typeArguments;
public ParameterizedType(ITypeDefinition genericType, IEnumerable<IType> typeArguments)
public ParameterizedType(IType genericType, IEnumerable<IType> typeArguments)
{
if (genericType == null)
throw new ArgumentNullException("genericType");
@ -53,11 +53,12 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -53,11 +53,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
throw new ArgumentException("Cannot use ParameterizedType 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");
ICompilationProvider gp = genericType as ICompilationProvider;
for (int i = 0; i < this.typeArguments.Length; i++) {
if (this.typeArguments[i] == null)
throw new ArgumentNullException("typeArguments[" + i + "]");
ICompilationProvider p = this.typeArguments[i] as ICompilationProvider;
if (p != null && p.Compilation != genericType.Compilation)
if (p != null && gp != null && p.Compilation != gp.Compilation)
throw new InvalidOperationException("Cannot parameterize a type with type arguments from a different compilation.");
}
}
@ -66,7 +67,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -66,7 +67,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Fast internal version of the constructor. (no safety checks)
/// Keeps the array that was passed and assumes it won't be modified.
/// </summary>
internal ParameterizedType(ITypeDefinition genericType, IType[] typeArguments)
internal ParameterizedType(IType genericType, IType[] typeArguments)
{
Debug.Assert(genericType.TypeParameterCount == typeArguments.Length);
this.genericType = genericType;
@ -77,8 +78,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -77,8 +78,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return genericType.Kind; }
}
public ICompilation Compilation {
get { return genericType.Compilation; }
public IType GenericType {
get { return genericType; }
}
public bool? IsReferenceType {
@ -87,18 +88,18 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -87,18 +88,18 @@ namespace ICSharpCode.Decompiler.TypeSystem
public IType DeclaringType {
get {
ITypeDefinition declaringTypeDef = genericType.DeclaringTypeDefinition;
if (declaringTypeDef != null && declaringTypeDef.TypeParameterCount > 0
&& declaringTypeDef.TypeParameterCount <= genericType.TypeParameterCount)
IType declaringType = genericType.DeclaringType;
if (declaringType != null && declaringType.TypeParameterCount > 0
&& declaringType.TypeParameterCount <= genericType.TypeParameterCount)
{
IType[] newTypeArgs = new IType[declaringTypeDef.TypeParameterCount];
IType[] newTypeArgs = new IType[declaringType.TypeParameterCount];
Array.Copy(this.typeArguments, 0, newTypeArgs, 0, newTypeArgs.Length);
return new ParameterizedType(declaringTypeDef, newTypeArgs);
return new ParameterizedType(declaringType, newTypeArgs);
}
return declaringTypeDef;
return declaringType;
}
}
public int TypeParameterCount {
get { return typeArguments.Length; }
}
@ -135,34 +136,26 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -135,34 +136,26 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
return ReflectionName;
}
public IReadOnlyList<IType> TypeArguments {
get {
return typeArguments;
}
}
public bool IsParameterized {
get {
return true;
}
}
public IReadOnlyList<IType> TypeArguments => typeArguments;
/// <summary>
/// Same as 'parameterizedType.TypeArguments[index]', but is a bit more efficient (doesn't require the read-only wrapper).
/// Same as 'parameterizedType.TypeArguments[index]'.
/// </summary>
public IType GetTypeArgument(int index)
{
return typeArguments[index];
}
public IReadOnlyList<ITypeParameter> TypeParameters => genericType.TypeParameters;
/// <summary>
/// Gets the definition of the generic type.
/// For <c>ParameterizedType</c>, this method never returns null.
/// </summary>
public ITypeDefinition GetDefinition()
{
return genericType;
return genericType as ITypeDefinition;
}
public ITypeReference ToTypeReference()
@ -313,9 +306,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -313,9 +306,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
public IType VisitChildren(TypeVisitor visitor)
{
IType g = genericType.AcceptVisitor(visitor);
ITypeDefinition def = g as ITypeDefinition;
if (def == null)
return g;
// Keep ta == null as long as no elements changed, allocate the array only if necessary.
IType[] ta = (g != genericType) ? new IType[typeArguments.Length] : null;
for (int i = 0; i < typeArguments.Length; i++) {
@ -332,10 +322,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -332,10 +322,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (ta != null)
ta[i] = r;
}
if (def == genericType && ta == null)
if (ta == null)
return this;
else
return new ParameterizedType(def, ta ?? typeArguments);
return new ParameterizedType(g, ta ?? typeArguments);
}
}
@ -367,21 +357,18 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -367,21 +357,18 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return genericType; }
}
public ReadOnlyCollection<ITypeReference> TypeArguments {
public IReadOnlyList<ITypeReference> TypeArguments {
get {
return Array.AsReadOnly(typeArguments);
return typeArguments;
}
}
public IType Resolve(ITypeResolveContext context)
{
IType baseType = genericType.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef == null)
return baseType;
int tpc = baseTypeDef.TypeParameterCount;
int tpc = baseType.TypeParameterCount;
if (tpc == 0)
return baseTypeDef;
return baseType;
IType[] resolvedTypes = new IType[tpc];
for (int i = 0; i < resolvedTypes.Length; i++) {
if (i < typeArguments.Length)
@ -389,7 +376,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -389,7 +376,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
else
resolvedTypes[i] = SpecialType.UnknownType;
}
return new ParameterizedType(baseTypeDef, resolvedTypes);
return new ParameterizedType(baseType, resolvedTypes);
}
public override string ToString()

Loading…
Cancel
Save