mirror of https://github.com/icsharpcode/ILSpy.git
21 changed files with 942 additions and 480 deletions
@ -0,0 +1,202 @@
@@ -0,0 +1,202 @@
|
||||
// Copyright (c) 2018 Daniel Grunwald
|
||||
//
|
||||
// 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.Immutable; |
||||
using System.Diagnostics; |
||||
using System.Linq; |
||||
using ICSharpCode.Decompiler.Util; |
||||
using SRM = System.Reflection.Metadata; |
||||
|
||||
namespace ICSharpCode.Decompiler.TypeSystem |
||||
{ |
||||
/// <summary>
|
||||
/// Options for converting builtin
|
||||
/// </summary>
|
||||
[Flags] |
||||
enum TypeAttributeOptions |
||||
{ |
||||
None = 0, |
||||
Dynamic = 1, |
||||
Tuple = 2, |
||||
Default = Dynamic | Tuple |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Introduces 'dynamic' and tuple types based on attribute values.
|
||||
/// </summary>
|
||||
class ApplyAttributeTypeVisitor : TypeVisitor |
||||
{ |
||||
public static IType ApplyAttributesToType( |
||||
IType inputType, |
||||
ICompilation compilation, |
||||
SRM.CustomAttributeHandleCollection? attributes, |
||||
SRM.MetadataReader metadata, |
||||
TypeAttributeOptions options) |
||||
{ |
||||
if (options == TypeAttributeOptions.None) { |
||||
return inputType; |
||||
} |
||||
bool hasDynamicAttribute = false; |
||||
bool[] dynamicAttributeData = null; |
||||
bool useTupleTypes = (options & TypeAttributeOptions.Tuple) != 0; |
||||
string[] tupleElementNames = null; |
||||
if (attributes != null) { |
||||
foreach (var attrHandle in attributes.Value) { |
||||
var attr = metadata.GetCustomAttribute(attrHandle); |
||||
var attrType = attr.GetAttributeType(metadata); |
||||
if ((options & TypeAttributeOptions.Dynamic) != 0 |
||||
&& attrType.IsTopLevelType(metadata, "System.Runtime.CompilerServices", "DynamicAttribute")) { |
||||
hasDynamicAttribute = true; |
||||
var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider); |
||||
if (ctor.FixedArguments.Length == 1) { |
||||
var arg = ctor.FixedArguments[0]; |
||||
if (arg.Value is ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> values |
||||
&& values.All(v => v.Value is bool)) { |
||||
dynamicAttributeData = values.SelectArray(v => (bool)v.Value); |
||||
} |
||||
} |
||||
} else if (useTupleTypes && attrType.IsTopLevelType(metadata, "System.Runtime.CompilerServices", "TupleElementNamesAttribute")) { |
||||
var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider); |
||||
if (ctor.FixedArguments.Length == 1) { |
||||
var arg = ctor.FixedArguments[0]; |
||||
if (arg.Value is ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> values |
||||
&& values.All(v => v.Value is string || v.Value == null)) { |
||||
tupleElementNames = values.SelectArray(v => (string)v.Value); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
if (hasDynamicAttribute || useTupleTypes) { |
||||
return inputType.AcceptVisitor(new ApplyAttributeTypeVisitor( |
||||
compilation, hasDynamicAttribute, dynamicAttributeData, useTupleTypes, tupleElementNames |
||||
)); |
||||
} else { |
||||
return inputType; |
||||
} |
||||
} |
||||
|
||||
readonly ICompilation compilation; |
||||
readonly bool hasDynamicAttribute; |
||||
readonly bool[] dynamicAttributeData; |
||||
readonly bool useTupleTypes; |
||||
readonly string[] tupleElementNames; |
||||
int dynamicTypeIndex = 0; |
||||
int tupleTypeIndex = 0; |
||||
|
||||
public ApplyAttributeTypeVisitor(ICompilation compilation, bool hasDynamicAttribute, bool[] dynamicAttributeData, bool useTupleTypes, string[] tupleElementNames) |
||||
{ |
||||
this.compilation = compilation ?? throw new ArgumentNullException(nameof(compilation)); |
||||
this.hasDynamicAttribute = hasDynamicAttribute; |
||||
this.dynamicAttributeData = dynamicAttributeData; |
||||
this.useTupleTypes = useTupleTypes; |
||||
this.tupleElementNames = tupleElementNames; |
||||
} |
||||
|
||||
public override IType VisitPointerType(PointerType type) |
||||
{ |
||||
dynamicTypeIndex++; |
||||
return base.VisitPointerType(type); |
||||
} |
||||
|
||||
public override IType VisitArrayType(ArrayType type) |
||||
{ |
||||
dynamicTypeIndex++; |
||||
return base.VisitArrayType(type); |
||||
} |
||||
|
||||
public override IType VisitByReferenceType(ByReferenceType type) |
||||
{ |
||||
dynamicTypeIndex++; |
||||
return base.VisitByReferenceType(type); |
||||
} |
||||
|
||||
public override IType VisitParameterizedType(ParameterizedType type) |
||||
{ |
||||
if (useTupleTypes && TupleType.IsTupleCompatible(type, out int tupleCardinality)) { |
||||
if (tupleCardinality > 1) { |
||||
var valueTupleAssembly = type.GetDefinition()?.ParentAssembly; |
||||
ImmutableArray<string> elementNames = default; |
||||
if (tupleElementNames != null && tupleTypeIndex < tupleElementNames.Length) { |
||||
string[] extractedValues = new string[tupleCardinality]; |
||||
Array.Copy(tupleElementNames, tupleTypeIndex, extractedValues, 0, |
||||
Math.Min(tupleCardinality, tupleElementNames.Length - tupleTypeIndex)); |
||||
elementNames = ImmutableArray.CreateRange(extractedValues); |
||||
} |
||||
tupleTypeIndex += tupleCardinality; |
||||
var elementTypes = ImmutableArray.CreateBuilder<IType>(tupleCardinality); |
||||
do { |
||||
int normalArgCount = Math.Min(type.TypeArguments.Count, TupleType.RestPosition - 1); |
||||
for (int i = 0; i < normalArgCount; i++) { |
||||
dynamicTypeIndex++; |
||||
elementTypes.Add(type.TypeArguments[i].AcceptVisitor(this)); |
||||
} |
||||
if (type.TypeArguments.Count == TupleType.RestPosition) { |
||||
type = type.TypeArguments.Last() as ParameterizedType; |
||||
dynamicTypeIndex++; |
||||
if (type != null && TupleType.IsTupleCompatible(type, out int nestedCardinality)) { |
||||
tupleTypeIndex += nestedCardinality; |
||||
} else { |
||||
Debug.Fail("TRest should be another value tuple"); |
||||
type = null; |
||||
} |
||||
} else { |
||||
type = null; |
||||
} |
||||
} while (type != null); |
||||
Debug.Assert(elementTypes.Count == tupleCardinality); |
||||
return new TupleType( |
||||
compilation, |
||||
elementTypes.ToImmutable(), |
||||
elementNames, |
||||
valueTupleAssembly |
||||
); |
||||
} else { |
||||
// C# doesn't have syntax for tuples of cardinality <= 1
|
||||
tupleTypeIndex += tupleCardinality; |
||||
} |
||||
} |
||||
// Visit generic type and type arguments.
|
||||
// Like base implementation, except that it increments typeIndex.
|
||||
var genericType = type.GenericType.AcceptVisitor(this); |
||||
bool changed = type.GenericType != genericType; |
||||
var arguments = new IType[type.TypeArguments.Count]; |
||||
for (int i = 0; i < type.TypeArguments.Count; i++) { |
||||
dynamicTypeIndex++; |
||||
arguments[i] = type.TypeArguments[i].AcceptVisitor(this); |
||||
changed = changed || arguments[i] != type.TypeArguments[i]; |
||||
} |
||||
if (!changed) |
||||
return type; |
||||
return new ParameterizedType(genericType, arguments); |
||||
} |
||||
|
||||
public override IType VisitTypeDefinition(ITypeDefinition type) |
||||
{ |
||||
if (type.KnownTypeCode == KnownTypeCode.Object && hasDynamicAttribute) { |
||||
if (dynamicAttributeData == null || dynamicTypeIndex >= dynamicAttributeData.Length) |
||||
return SpecialType.Dynamic; |
||||
if (dynamicAttributeData[dynamicTypeIndex]) |
||||
return SpecialType.Dynamic; |
||||
return type; |
||||
} |
||||
return type; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,259 @@
@@ -0,0 +1,259 @@
|
||||
// Copyright (c) 2018 Daniel Grunwald
|
||||
//
|
||||
// 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 SRM = System.Reflection.Metadata; |
||||
using System.Diagnostics; |
||||
using System; |
||||
using ICSharpCode.Decompiler.Util; |
||||
using System.Linq; |
||||
using System.Collections.Immutable; |
||||
|
||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
||||
{ |
||||
sealed class MetadataTypeReference : ITypeReference |
||||
{ |
||||
readonly SRM.EntityHandle type; |
||||
readonly SRM.MetadataReader metadata; |
||||
readonly SRM.CustomAttributeHandleCollection? typeAttributes; |
||||
readonly TypeAttributeOptions attributeOptions; |
||||
|
||||
public MetadataTypeReference(SRM.EntityHandle type, |
||||
SRM.MetadataReader metadata, |
||||
SRM.CustomAttributeHandleCollection? typeAttributes = null, |
||||
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default) |
||||
{ |
||||
this.type = type; |
||||
this.metadata = metadata; |
||||
this.typeAttributes = typeAttributes; |
||||
this.attributeOptions = attributeOptions; |
||||
} |
||||
|
||||
public IType Resolve(ITypeResolveContext context) |
||||
{ |
||||
return Resolve(type, metadata, context, |
||||
typeAttributes, attributeOptions); |
||||
} |
||||
|
||||
public static IType Resolve(SRM.EntityHandle type, |
||||
SRM.MetadataReader metadata, |
||||
ITypeResolveContext context, |
||||
SRM.CustomAttributeHandleCollection? typeAttributes = null, |
||||
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default) |
||||
{ |
||||
if (type.IsNil) |
||||
return SpecialType.UnknownType; |
||||
var tp = new TypeProvider(context.CurrentAssembly); |
||||
IType ty; |
||||
switch (type.Kind) { |
||||
case SRM.HandleKind.TypeDefinition: |
||||
ty = tp.GetTypeFromDefinition(metadata, (SRM.TypeDefinitionHandle)type, 0); |
||||
break; |
||||
case SRM.HandleKind.TypeReference: |
||||
ty = tp.GetTypeFromReference(metadata, (SRM.TypeReferenceHandle)type, 0); |
||||
break; |
||||
case SRM.HandleKind.TypeSpecification: |
||||
var typeSpec = metadata.GetTypeSpecification((SRM.TypeSpecificationHandle)type); |
||||
ty = typeSpec.DecodeSignature(tp, context); |
||||
break; |
||||
default: |
||||
Debug.Fail("Not a type handle"); |
||||
ty = SpecialType.UnknownType; |
||||
break; |
||||
} |
||||
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation, |
||||
typeAttributes, metadata, attributeOptions); |
||||
return ty; |
||||
} |
||||
} |
||||
|
||||
sealed class FieldTypeReference : ITypeReference |
||||
{ |
||||
readonly SRM.FieldDefinitionHandle fieldHandle; |
||||
readonly SRM.MetadataReader metadata; |
||||
readonly TypeAttributeOptions attributeOptions; |
||||
|
||||
public FieldTypeReference(SRM.FieldDefinitionHandle fieldHandle, |
||||
SRM.MetadataReader metadata, |
||||
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default) |
||||
{ |
||||
this.fieldHandle = fieldHandle; |
||||
this.metadata = metadata; |
||||
this.attributeOptions = attributeOptions; |
||||
} |
||||
|
||||
IType ITypeReference.Resolve(ITypeResolveContext context) |
||||
{ |
||||
return Resolve(fieldHandle, metadata, context, attributeOptions); |
||||
} |
||||
|
||||
public static IType Resolve(SRM.FieldDefinitionHandle fieldHandle, |
||||
SRM.MetadataReader metadata, |
||||
ITypeResolveContext context, |
||||
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default) |
||||
{ |
||||
var fieldDef = metadata.GetFieldDefinition(fieldHandle); |
||||
IType ty = fieldDef.DecodeSignature(new TypeProvider(context.CurrentAssembly), context); |
||||
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation, |
||||
fieldDef.GetCustomAttributes(), metadata, attributeOptions); |
||||
return ty; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents an unresolved method signature.
|
||||
/// </summary>
|
||||
sealed class UnresolvedMethodSignature |
||||
{ |
||||
readonly SRM.EntityHandle handle; |
||||
readonly SRM.MetadataReader metadata; |
||||
readonly TypeAttributeOptions attributeOptions; |
||||
|
||||
public UnresolvedMethodSignature(SRM.MethodDefinitionHandle handle, SRM.MetadataReader metadata, |
||||
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default) |
||||
{ |
||||
this.handle = handle; |
||||
this.metadata = metadata; |
||||
this.attributeOptions = attributeOptions; |
||||
} |
||||
|
||||
public UnresolvedMethodSignature(SRM.PropertyDefinitionHandle handle, SRM.MetadataReader metadata, |
||||
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default) |
||||
{ |
||||
this.handle = handle; |
||||
this.metadata = metadata; |
||||
this.attributeOptions = attributeOptions; |
||||
} |
||||
|
||||
public SRM.MethodSignature<IType> Resolve(ITypeResolveContext context) |
||||
{ |
||||
return (SRM.MethodSignature<IType>)context.Compilation.CacheManager.GetOrAddShared( |
||||
this, key => { |
||||
Debug.Assert(key == this); |
||||
switch (handle.Kind) { |
||||
case SRM.HandleKind.MethodDefinition: |
||||
return GetSignature( |
||||
metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)handle), |
||||
metadata, context |
||||
); |
||||
case SRM.HandleKind.PropertyDefinition: |
||||
return GetSignature( |
||||
metadata.GetPropertyDefinition((SRM.PropertyDefinitionHandle)handle), |
||||
metadata, context |
||||
); |
||||
default: |
||||
throw new InvalidOperationException(); |
||||
} |
||||
} |
||||
); |
||||
} |
||||
|
||||
public static SRM.MethodSignature<IType> GetSignature(SRM.MethodDefinition methodDef, |
||||
SRM.MetadataReader metadata, ITypeResolveContext context, |
||||
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default) |
||||
{ |
||||
var typeProvider = new TypeProvider(context.CurrentAssembly); |
||||
var signature = methodDef.DecodeSignature(typeProvider, context); |
||||
return ApplyAttributes(signature, methodDef.GetParameters(), context.Compilation, metadata, attributeOptions); |
||||
} |
||||
|
||||
public static SRM.MethodSignature<IType> GetSignature(SRM.PropertyDefinition propertyDef, |
||||
SRM.MetadataReader metadata, ITypeResolveContext context, |
||||
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default) |
||||
{ |
||||
var typeProvider = new TypeProvider(context.CurrentAssembly); |
||||
var signature = propertyDef.DecodeSignature(typeProvider, context); |
||||
var accessors = propertyDef.GetAccessors(); |
||||
SRM.ParameterHandleCollection? parameterHandles = null; |
||||
if (!accessors.Getter.IsNil) { |
||||
var getter = metadata.GetMethodDefinition(accessors.Getter); |
||||
parameterHandles = getter.GetParameters(); |
||||
} else { |
||||
if (!accessors.Setter.IsNil) { |
||||
var setter = metadata.GetMethodDefinition(accessors.Setter); |
||||
parameterHandles = setter.GetParameters(); |
||||
} |
||||
} |
||||
return ApplyAttributes(signature, parameterHandles, context.Compilation, metadata, attributeOptions); |
||||
} |
||||
|
||||
static SRM.MethodSignature<IType> ApplyAttributes(SRM.MethodSignature<IType> signature, SRM.ParameterHandleCollection? parameterHandles, ICompilation compilation, SRM.MetadataReader metadata, TypeAttributeOptions attributeOptions) |
||||
{ |
||||
SRM.CustomAttributeHandleCollection? returnTypeAttributes = null; |
||||
var parameterAttributes = new SRM.CustomAttributeHandleCollection?[signature.ParameterTypes.Length]; |
||||
if (parameterHandles != null) { |
||||
foreach (var parameterHandle in parameterHandles) { |
||||
var par = metadata.GetParameter(parameterHandle); |
||||
if (par.SequenceNumber == 0) { |
||||
returnTypeAttributes = par.GetCustomAttributes(); |
||||
} else if (par.SequenceNumber <= parameterAttributes.Length) { |
||||
parameterAttributes[par.SequenceNumber - 1] = par.GetCustomAttributes(); |
||||
} |
||||
} |
||||
} |
||||
IType returnType = ApplyAttributeTypeVisitor.ApplyAttributesToType( |
||||
signature.ReturnType, compilation, returnTypeAttributes, metadata, attributeOptions |
||||
); |
||||
var parameterTypes = signature.ParameterTypes.SelectWithIndex( |
||||
(i, p) => ApplyAttributeTypeVisitor.ApplyAttributesToType( |
||||
p, compilation, parameterAttributes[i], metadata, attributeOptions |
||||
) |
||||
).ToImmutableArray(); |
||||
return new SRM.MethodSignature<IType>( |
||||
signature.Header, returnType, |
||||
signature.RequiredParameterCount, signature.GenericParameterCount, |
||||
parameterTypes |
||||
); |
||||
} |
||||
} |
||||
|
||||
sealed class SignatureParameterTypeReference : ITypeReference |
||||
{ |
||||
readonly UnresolvedMethodSignature unresolvedSig; |
||||
readonly int index; |
||||
|
||||
public SignatureParameterTypeReference(UnresolvedMethodSignature unresolvedSig, int index) |
||||
{ |
||||
this.unresolvedSig = unresolvedSig; |
||||
this.index = index; |
||||
} |
||||
|
||||
public IType Resolve(ITypeResolveContext context) |
||||
{ |
||||
var sig = unresolvedSig.Resolve(context); |
||||
if (index < sig.ParameterTypes.Length) |
||||
return sig.ParameterTypes[index]; |
||||
else |
||||
return SpecialType.UnknownType; |
||||
} |
||||
} |
||||
|
||||
sealed class SignatureReturnTypeReference : ITypeReference |
||||
{ |
||||
readonly UnresolvedMethodSignature unresolvedSig; |
||||
|
||||
public SignatureReturnTypeReference(UnresolvedMethodSignature unresolvedSig) |
||||
{ |
||||
this.unresolvedSig = unresolvedSig; |
||||
} |
||||
|
||||
public IType Resolve(ITypeResolveContext context) |
||||
{ |
||||
return unresolvedSig.Resolve(context).ReturnType; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,166 @@
@@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2018 Daniel Grunwald
|
||||
//
|
||||
// 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.Immutable; |
||||
using System.Reflection.Metadata.Ecma335; |
||||
using ICSharpCode.Decompiler.Metadata; |
||||
using ICSharpCode.Decompiler.TypeSystem.Implementation; |
||||
using SRM = System.Reflection.Metadata; |
||||
|
||||
namespace ICSharpCode.Decompiler.TypeSystem |
||||
{ |
||||
/// <summary>
|
||||
/// Allows decoding signatures using decompiler types.
|
||||
/// </summary>
|
||||
class TypeProvider : SRM.ISignatureTypeProvider<IType, ITypeResolveContext>, SRM.ICustomAttributeTypeProvider<IType> |
||||
{ |
||||
readonly IAssembly assembly; |
||||
readonly ICompilation compilation; |
||||
|
||||
public TypeProvider(IAssembly assembly) |
||||
{ |
||||
this.assembly = assembly; |
||||
this.compilation = assembly.Compilation; |
||||
} |
||||
|
||||
public IType GetArrayType(IType elementType, SRM.ArrayShape shape) |
||||
{ |
||||
return new ArrayType(compilation, elementType, shape.Rank); |
||||
} |
||||
|
||||
public IType GetByReferenceType(IType elementType) |
||||
{ |
||||
return new ByReferenceType(elementType); |
||||
} |
||||
|
||||
public IType GetFunctionPointerType(SRM.MethodSignature<IType> signature) |
||||
{ |
||||
return compilation.FindType(KnownTypeCode.IntPtr); |
||||
} |
||||
|
||||
public IType GetGenericInstantiation(IType genericType, ImmutableArray<IType> typeArguments) |
||||
{ |
||||
return new ParameterizedType(genericType, typeArguments); |
||||
} |
||||
|
||||
public IType GetGenericMethodParameter(ITypeResolveContext genericContext, int index) |
||||
{ |
||||
// Note: returning type parameter, never type argument.
|
||||
// Otherwise we risk screwing up the counting for dynamicTypeIndex.
|
||||
IMethod method = genericContext.CurrentMember as IMethod; |
||||
if (method != null && index < method.TypeParameters.Count) { |
||||
return method.TypeParameters[index]; |
||||
} |
||||
return DummyTypeParameter.GetMethodTypeParameter(index); |
||||
} |
||||
|
||||
public IType GetGenericTypeParameter(ITypeResolveContext genericContext, int index) |
||||
{ |
||||
ITypeDefinition typeDef = genericContext.CurrentTypeDefinition; |
||||
if (typeDef != null && index < typeDef.TypeParameters.Count) { |
||||
return typeDef.TypeParameters[index]; |
||||
} |
||||
return DummyTypeParameter.GetClassTypeParameter(index); |
||||
} |
||||
|
||||
public IType GetModifiedType(IType modifier, IType unmodifiedType, bool isRequired) |
||||
{ |
||||
return unmodifiedType; |
||||
} |
||||
|
||||
public IType GetPinnedType(IType elementType) |
||||
{ |
||||
return new PinnedType(elementType); |
||||
} |
||||
|
||||
public IType GetPointerType(IType elementType) |
||||
{ |
||||
return new PointerType(elementType); |
||||
} |
||||
|
||||
public IType GetPrimitiveType(SRM.PrimitiveTypeCode typeCode) |
||||
{ |
||||
return compilation.FindType(typeCode.ToKnownTypeCode()); |
||||
} |
||||
|
||||
public IType GetSystemType() |
||||
{ |
||||
return compilation.FindType(KnownTypeCode.Type); |
||||
} |
||||
|
||||
public IType GetSZArrayType(IType elementType) |
||||
{ |
||||
return new ArrayType(compilation, elementType); |
||||
} |
||||
|
||||
public IType GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind) |
||||
{ |
||||
ITypeDefinition td = assembly.ResolveTypeDefToken(handle); |
||||
if (td != null) |
||||
return td; |
||||
return SpecialType.UnknownType; |
||||
} |
||||
|
||||
public IType GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind) |
||||
{ |
||||
var asmref = handle.GetDeclaringAssembly(reader); |
||||
IAssemblyReference nrAsmRef; |
||||
if (asmref.IsNil) |
||||
nrAsmRef = DefaultAssemblyReference.CurrentAssembly; |
||||
else |
||||
nrAsmRef = new DefaultAssemblyReference(reader.GetString(reader.GetAssemblyReference(asmref).Name)); |
||||
bool? isReferenceType = null; |
||||
switch (reader.ResolveSignatureTypeKind(handle, rawTypeKind)) { |
||||
case SRM.SignatureTypeKind.ValueType: |
||||
isReferenceType = false; |
||||
break; |
||||
case SRM.SignatureTypeKind.Class: |
||||
isReferenceType = true; |
||||
break; |
||||
} |
||||
var gctr = new GetClassTypeReference(handle.GetFullTypeName(reader), nrAsmRef, isReferenceType); |
||||
return gctr.Resolve(new SimpleTypeResolveContext(assembly)); |
||||
} |
||||
|
||||
public IType GetTypeFromSerializedName(string name) |
||||
{ |
||||
// TODO: aren't we missing support for assembly-qualified names?
|
||||
return new GetClassTypeReference(new FullTypeName(name)) |
||||
.Resolve(new SimpleTypeResolveContext(assembly)); |
||||
} |
||||
|
||||
public IType GetTypeFromSpecification(SRM.MetadataReader reader, ITypeResolveContext genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind) |
||||
{ |
||||
return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext); |
||||
} |
||||
|
||||
public SRM.PrimitiveTypeCode GetUnderlyingEnumType(IType type) |
||||
{ |
||||
var def = type.GetEnumUnderlyingType().GetDefinition(); |
||||
if (def == null) |
||||
throw new InvalidOperationException(); |
||||
return def.KnownTypeCode.ToPrimitiveTypeCode(); |
||||
} |
||||
|
||||
public bool IsSystemType(IType type) |
||||
{ |
||||
return type.IsKnownType(KnownTypeCode.Type); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue