mirror of https://github.com/icsharpcode/ILSpy.git
21 changed files with 942 additions and 480 deletions
@ -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 @@ |
|||||||
|
// 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 @@ |
|||||||
|
// 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