mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
9.0 KiB
257 lines
9.0 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Collections.Immutable; |
|
using System.Linq; |
|
using System.Reflection.Metadata; |
|
using ICSharpCode.Decompiler.CSharp.Syntax; |
|
using ICSharpCode.Decompiler.Metadata; |
|
using ICSharpCode.Decompiler.Util; |
|
|
|
using FullTypeName = ICSharpCode.Decompiler.TypeSystem.FullTypeName; |
|
|
|
namespace ICSharpCode.Decompiler.CSharp |
|
{ |
|
[Flags] |
|
public enum ConvertTypeOptions |
|
{ |
|
None = 0, |
|
IncludeNamespace = 1, |
|
IncludeTypeParameterDefinitions = 2, |
|
DoNotUsePrimitiveTypeNames = 4, |
|
IncludeOuterTypeName = 8, |
|
} |
|
|
|
public class AstTypeBuilder : ISignatureTypeProvider<AstType, GenericContext> |
|
{ |
|
ConvertTypeOptions options; |
|
|
|
public AstTypeBuilder(ConvertTypeOptions options) |
|
{ |
|
this.options = options; |
|
} |
|
|
|
public AstType GetArrayType(AstType elementType, ArrayShape shape) |
|
{ |
|
return elementType.MakeArrayType(shape.Rank); |
|
} |
|
|
|
public AstType GetByReferenceType(AstType elementType) |
|
{ |
|
return elementType.MakeRefType(); |
|
} |
|
|
|
public AstType GetFunctionPointerType(MethodSignature<AstType> signature) |
|
{ |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("IntPtr"); |
|
return AstType.Create("System.IntPtr"); |
|
} |
|
|
|
public AstType GetGenericInstantiation(AstType genericType, ImmutableArray<AstType> typeArguments) |
|
{ |
|
switch (genericType) { |
|
case SimpleType st: |
|
st.TypeArguments.AddRange(typeArguments); |
|
return st; |
|
case MemberType mt: |
|
mt.TypeArguments.AddRange(typeArguments); |
|
return mt; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
|
|
public AstType GetGenericMethodParameter(GenericContext genericContext, int index) |
|
{ |
|
return new SimpleType(genericContext.GetGenericMethodTypeParameterName(index)); |
|
} |
|
|
|
public AstType GetGenericTypeParameter(GenericContext genericContext, int index) |
|
{ |
|
return new SimpleType(genericContext.GetGenericMethodTypeParameterName(index)); |
|
} |
|
|
|
public AstType GetModifiedType(AstType modifier, AstType unmodifiedType, bool isRequired) |
|
{ |
|
return unmodifiedType; |
|
} |
|
|
|
public AstType GetPinnedType(AstType elementType) |
|
{ |
|
return elementType; |
|
} |
|
|
|
public AstType GetPointerType(AstType elementType) |
|
{ |
|
return elementType.MakePointerType(); |
|
} |
|
|
|
public AstType GetPrimitiveType(PrimitiveTypeCode typeCode) |
|
{ |
|
switch (typeCode) { |
|
case PrimitiveTypeCode.Boolean: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("Boolean"); |
|
return AstType.Create("System.Boolean"); |
|
} |
|
return new PrimitiveType("bool"); |
|
case PrimitiveTypeCode.Byte: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("Byte"); |
|
return AstType.Create("System.Byte"); |
|
} |
|
return new PrimitiveType("byte"); |
|
case PrimitiveTypeCode.SByte: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("SByte"); |
|
return AstType.Create("System.SByte"); |
|
} |
|
return new PrimitiveType("sbyte"); |
|
case PrimitiveTypeCode.Char: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("Char"); |
|
return AstType.Create("System.Char"); |
|
} |
|
return new PrimitiveType("char"); |
|
case PrimitiveTypeCode.Int16: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("Int16"); |
|
return AstType.Create("System.Int16"); |
|
} |
|
return new PrimitiveType("short"); |
|
case PrimitiveTypeCode.UInt16: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("UInt16"); |
|
return AstType.Create("System.UInt16"); |
|
} |
|
return new PrimitiveType("ushort"); |
|
case PrimitiveTypeCode.Int32: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("Int32"); |
|
return AstType.Create("System.In32"); |
|
} |
|
return new PrimitiveType("int"); |
|
case PrimitiveTypeCode.UInt32: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("UInt32"); |
|
return AstType.Create("System.UInt32"); |
|
} |
|
return new PrimitiveType("uint"); |
|
case PrimitiveTypeCode.Int64: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("Int64"); |
|
return AstType.Create("System.Int64"); |
|
} |
|
return new PrimitiveType("long"); |
|
case PrimitiveTypeCode.UInt64: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("UInt64"); |
|
return AstType.Create("System.UInt64"); |
|
} |
|
return new PrimitiveType("ulong"); |
|
case PrimitiveTypeCode.Single: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("Single"); |
|
return AstType.Create("System.Single"); |
|
} |
|
return new PrimitiveType("float"); |
|
case PrimitiveTypeCode.Double: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("Double"); |
|
return AstType.Create("System.Double"); |
|
} |
|
return new PrimitiveType("double"); |
|
case PrimitiveTypeCode.IntPtr: |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("IntPtr"); |
|
return AstType.Create("System.IntPtr"); |
|
case PrimitiveTypeCode.UIntPtr: |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("UIntPtr"); |
|
return AstType.Create("System.UIntPtr"); |
|
case PrimitiveTypeCode.Object: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("Object"); |
|
return AstType.Create("System.Object"); |
|
} |
|
return new PrimitiveType("object"); |
|
case PrimitiveTypeCode.String: |
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("String"); |
|
return AstType.Create("System.String"); |
|
} |
|
return new PrimitiveType("string"); |
|
case PrimitiveTypeCode.TypedReference: |
|
if ((options & ConvertTypeOptions.IncludeNamespace) == 0) |
|
return AstType.Create("TypedReference"); |
|
return AstType.Create("System.TypedReference"); |
|
case PrimitiveTypeCode.Void: |
|
return new PrimitiveType("void"); |
|
default: |
|
throw new NotSupportedException(); |
|
} |
|
} |
|
|
|
public AstType GetSZArrayType(AstType elementType) |
|
{ |
|
return elementType.MakeArrayType(); |
|
} |
|
|
|
public AstType GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) |
|
{ |
|
var td = reader.GetTypeDefinition(handle); |
|
var genericParams = td.GetGenericParameters().Select(gp => (AstType)new SimpleType(reader.GetString(reader.GetGenericParameter(gp).Name))).ToList(); |
|
return MakeAstType(handle.GetFullTypeName(reader), genericParams); |
|
} |
|
|
|
public AstType GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) |
|
{ |
|
return MakeAstType(handle.GetFullTypeName(reader), EmptyList<AstType>.Instance); |
|
} |
|
|
|
public AstType GetTypeFromSpecification(MetadataReader reader, GenericContext genericContext, TypeSpecificationHandle handle, byte rawTypeKind) |
|
{ |
|
var ts = reader.GetTypeSpecification(handle); |
|
return ts.DecodeSignature(this, genericContext); |
|
} |
|
|
|
AstType MakeAstType(FullTypeName fullTypeName, IList<AstType> genericParams) |
|
{ |
|
if (fullTypeName.IsNested) { |
|
int count = fullTypeName.GetNestedTypeAdditionalTypeParameterCount(fullTypeName.NestingLevel - 1); |
|
if ((options & (ConvertTypeOptions.IncludeOuterTypeName | ConvertTypeOptions.IncludeNamespace)) != 0) { |
|
var outerType = MakeAstType(fullTypeName.GetDeclaringType(), genericParams); |
|
var mt = new MemberType(outerType, fullTypeName.Name); |
|
return mt; |
|
} else { |
|
var st = new SimpleType(fullTypeName.Name); |
|
for (int i = 0; i < fullTypeName.TypeParameterCount - count; i++) |
|
genericParams.RemoveAt(0); |
|
return st; |
|
} |
|
} |
|
AstType baseType; |
|
var topLevel = fullTypeName.TopLevelTypeName; |
|
if ((options & ConvertTypeOptions.IncludeNamespace) != 0) { |
|
baseType = AstType.Create(topLevel.Namespace + "." + topLevel.Name); |
|
} else { |
|
baseType = AstType.Create(topLevel.Name); |
|
} |
|
return baseType; |
|
} |
|
} |
|
}
|
|
|