Browse Source

Fix TypeSystemLoaderTests

pull/1198/head
Siegfried Pammer 7 years ago
parent
commit
61eead50c7
  1. 1
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  2. 1
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  4. 8
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  5. 9
      ICSharpCode.Decompiler/IL/ILReader.cs
  6. 2
      ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs
  7. 6
      ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
  8. 18
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  9. 161
      ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
  10. 269
      ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs
  11. 2
      ICSharpCode.Decompiler/Util/CollectionExtensions.cs

1
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs

@ -98,6 +98,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void DynamicType() public void DynamicType()
{ {
ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest));
Assert.AreEqual(SpecialType.Dynamic, testClass.Fields.Single(f => f.Name == "DynamicField").ReturnType);
Assert.AreEqual(SpecialType.Dynamic, testClass.Properties.Single().ReturnType); Assert.AreEqual(SpecialType.Dynamic, testClass.Properties.Single().ReturnType);
Assert.AreEqual(0, testClass.Properties.Single().Attributes.Count); Assert.AreEqual(0, testClass.Properties.Single().Attributes.Count);
} }

1
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs

@ -61,6 +61,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public unsafe class DynamicTest public unsafe class DynamicTest
{ {
public dynamic DynamicField;
public dynamic SimpleProperty { get; set; } public dynamic SimpleProperty { get; set; }
public List<dynamic> DynamicGenerics1(Action<object, dynamic[], object> param) { return null; } public List<dynamic> DynamicGenerics1(Action<object, dynamic[], object> param) { return null; }

2
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -523,7 +523,7 @@ namespace ICSharpCode.Decompiler.CSharp
}; };
bool needsCast = false; bool needsCast = false;
ResolveResult result = null; ResolveResult result = null;
var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type))); var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectReadOnlyArray(p => new TypeResolveResult(p.Type)));
if (!requireTarget) { if (!requireTarget) {
result = resolver.ResolveSimpleName(method.Name, method.TypeArguments, isInvocationTarget: false); result = resolver.ResolveSimpleName(method.Name, method.TypeArguments, isInvocationTarget: false);
if (result is MethodGroupResolveResult mgrr) { if (result is MethodGroupResolveResult mgrr) {

8
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -3,11 +3,8 @@
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" /> <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />
<PropertyGroup> <PropertyGroup>
<!--
<TargetFramework Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0</TargetFramework> <TargetFramework Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0</TargetFramework>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">netstandard2.0;net46;net45</TargetFrameworks> <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">netstandard2.0;net46;net45</TargetFrameworks>
-->
<TargetFramework>net46</TargetFramework>
<Description>IL decompiler engine</Description> <Description>IL decompiler engine</Description>
<Company>ic#code</Company> <Company>ic#code</Company>
@ -19,6 +16,7 @@
<GenerateAssemblyInformationalVersionAttribute>False</GenerateAssemblyInformationalVersionAttribute> <GenerateAssemblyInformationalVersionAttribute>False</GenerateAssemblyInformationalVersionAttribute>
<EnableDefaultItems>false</EnableDefaultItems> <EnableDefaultItems>false</EnableDefaultItems>
<LangVersion>7.2</LangVersion>
<SignAssembly>True</SignAssembly> <SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>ICSharpCode.Decompiler.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>ICSharpCode.Decompiler.snk</AssemblyOriginatorKeyFile>
@ -51,10 +49,6 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<LangVersion>7.2</LangVersion>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.2.0" /> <PackageReference Include="Humanizer.Core" Version="2.2.0" />
<PackageReference Include="Mono.Cecil" Version="0.10.0-beta7" /> <PackageReference Include="Mono.Cecil" Version="0.10.0-beta7" />

9
ICSharpCode.Decompiler/IL/ILReader.cs

@ -78,7 +78,8 @@ namespace ICSharpCode.Decompiler.IL
throw new ArgumentNullException(nameof(body)); throw new ArgumentNullException(nameof(body));
this.metadata = module.GetMetadataReader(); this.metadata = module.GetMetadataReader();
this.method = typeSystem.ResolveAsMethod(methodDefinitionHandle); this.method = typeSystem.ResolveAsMethod(methodDefinitionHandle);
this.methodSignature = metadata.GetMethodDefinition(methodDefinitionHandle).DecodeSignature(new TypeSystem.Implementation.TypeReferenceSignatureDecoder(), default); var methodDefinition = metadata.GetMethodDefinition(methodDefinitionHandle);
this.methodSignature = methodDefinition.DecodeSignature(TypeSystem.Implementation.TypeReferenceSignatureDecoder.Instance, default);
this.body = body; this.body = body;
this.reader = body.GetILReader(); this.reader = body.GetILReader();
//this.debugInfo = metadata.GetMethodDebugInformation(method.Handle.ToDebugInformationHandle()); //this.debugInfo = metadata.GetMethodDebugInformation(method.Handle.ToDebugInformationHandle());
@ -86,7 +87,7 @@ namespace ICSharpCode.Decompiler.IL
this.unionFind = new UnionFind<ILVariable>(); this.unionFind = new UnionFind<ILVariable>();
this.stackMismatchPairs = new List<(ILVariable, ILVariable)>(); this.stackMismatchPairs = new List<(ILVariable, ILVariable)>();
this.resolveContext = new SimpleTypeResolveContext(this.method); this.resolveContext = new SimpleTypeResolveContext(this.method);
this.methodReturnStackType = methodSignature.ReturnType.Resolve(resolveContext).GetStackType(); this.methodReturnStackType = TypeSystem.Implementation.DynamicAwareTypeReference.Create(methodSignature.ReturnType, methodDefinition.GetCustomAttributes(), metadata).Resolve(resolveContext).GetStackType();
InitParameterVariables(); InitParameterVariables();
InitLocalVariables(); InitLocalVariables();
if (body.LocalVariablesInitialized) { if (body.LocalVariablesInitialized) {
@ -129,7 +130,7 @@ namespace ICSharpCode.Decompiler.IL
if (body.LocalSignature.IsNil) return; if (body.LocalSignature.IsNil) return;
var standaloneSignature = metadata.GetStandaloneSignature(body.LocalSignature); var standaloneSignature = metadata.GetStandaloneSignature(body.LocalSignature);
Debug.Assert(standaloneSignature.GetKind() == StandaloneSignatureKind.LocalVariables); Debug.Assert(standaloneSignature.GetKind() == StandaloneSignatureKind.LocalVariables);
var variableTypes = standaloneSignature.DecodeLocalSignature(new TypeSystem.Implementation.TypeReferenceSignatureDecoder(), default); var variableTypes = standaloneSignature.DecodeLocalSignature(TypeSystem.Implementation.TypeReferenceSignatureDecoder.Instance, default);
localVariables = new ILVariable[variableTypes.Length]; localVariables = new ILVariable[variableTypes.Length];
foreach (var (index, type) in variableTypes.WithIndex()) { foreach (var (index, type) in variableTypes.WithIndex()) {
localVariables[index] = CreateILVariable(index, type); localVariables[index] = CreateILVariable(index, type);
@ -1279,7 +1280,7 @@ namespace ICSharpCode.Decompiler.IL
{ {
var standaloneSignature = metadata.GetStandaloneSignature((StandaloneSignatureHandle)ReadAndDecodeMetadataToken()); var standaloneSignature = metadata.GetStandaloneSignature((StandaloneSignatureHandle)ReadAndDecodeMetadataToken());
Debug.Assert(standaloneSignature.GetKind() == StandaloneSignatureKind.Method); Debug.Assert(standaloneSignature.GetKind() == StandaloneSignatureKind.Method);
var signature = standaloneSignature.DecodeMethodSignature(new TypeSystem.Implementation.TypeReferenceSignatureDecoder(), default); var signature = standaloneSignature.DecodeMethodSignature(TypeSystem.Implementation.TypeReferenceSignatureDecoder.Instance, default);
var functionPointer = Pop(StackType.I); var functionPointer = Pop(StackType.I);
Debug.Assert(!signature.Header.IsInstance); Debug.Assert(!signature.Header.IsInstance);
var parameterTypes = new IType[signature.ParameterTypes.Length]; var parameterTypes = new IType[signature.ParameterTypes.Length];

2
ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs

@ -244,7 +244,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (call.Method.Parameters.Count == 0) return false; if (call.Method.Parameters.Count == 0) return false;
var targetType = call.Method.Parameters.Select(p => new ResolveResult(p.Type)).First(); var targetType = call.Method.Parameters.Select(p => new ResolveResult(p.Type)).First();
var paramTypes = call.Method.Parameters.Skip(1).Select(p => new ResolveResult(p.Type)).ToArray(); var paramTypes = call.Method.Parameters.Skip(1).Select(p => new ResolveResult(p.Type)).ToArray();
var paramNames = call.Method.Parameters.SelectArray(p => p.Name); var paramNames = call.Method.Parameters.SelectReadOnlyArray(p => p.Name);
var typeArgs = call.Method.TypeArguments.ToArray(); var typeArgs = call.Method.TypeArguments.ToArray();
var resolveContext = new CSharp.TypeSystem.CSharpTypeResolveContext(context.TypeSystem.Compilation.MainAssembly, context.UsingScope); var resolveContext = new CSharp.TypeSystem.CSharpTypeResolveContext(context.TypeSystem.Compilation.MainAssembly, context.UsingScope);
var resolver = new CSharp.Resolver.CSharpResolver(resolveContext); var resolver = new CSharp.Resolver.CSharpResolver(resolveContext);

6
ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs

@ -290,11 +290,11 @@ namespace ICSharpCode.Decompiler.Metadata
case PrimitiveTypeCode.SByte: case PrimitiveTypeCode.SByte:
return KnownTypeCode.SByte; return KnownTypeCode.SByte;
case PrimitiveTypeCode.Char: case PrimitiveTypeCode.Char:
return KnownTypeCode.Byte; return KnownTypeCode.Char;
case PrimitiveTypeCode.Int16: case PrimitiveTypeCode.Int16:
return KnownTypeCode.Byte; return KnownTypeCode.Int16;
case PrimitiveTypeCode.UInt16: case PrimitiveTypeCode.UInt16:
return KnownTypeCode.Byte; return KnownTypeCode.UInt16;
case PrimitiveTypeCode.Int32: case PrimitiveTypeCode.Int32:
return KnownTypeCode.Int32; return KnownTypeCode.Int32;
case PrimitiveTypeCode.UInt32: case PrimitiveTypeCode.UInt32:

18
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -173,7 +173,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
case SRM.HandleKind.FieldDefinition: case SRM.HandleKind.FieldDefinition:
var fieldDef = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)fieldReference); var fieldDef = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)fieldReference);
declaringType = ResolveAsType(fieldDef.GetDeclaringType()); declaringType = ResolveAsType(fieldDef.GetDeclaringType());
returnType = fieldDef.DecodeSignature(new TypeReferenceSignatureDecoder(), default); returnType = DynamicAwareTypeReference.Create(fieldDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default), fieldDef.GetCustomAttributes(), metadata);
var declaringTypeDefinition = declaringType.GetDefinition(); var declaringTypeDefinition = declaringType.GetDefinition();
if (declaringTypeDefinition == null) if (declaringTypeDefinition == null)
field = CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType); field = CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType);
@ -211,7 +211,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
string name = metadata.GetString(memberRef.Name); string name = metadata.GetString(memberRef.Name);
ITypeDefinition typeDef = declaringType.GetDefinition(); ITypeDefinition typeDef = declaringType.GetDefinition();
ITypeReference returnType = memberRef.DecodeFieldSignature(new TypeReferenceSignatureDecoder(), default); ITypeReference returnType = memberRef.DecodeFieldSignature(TypeReferenceSignatureDecoder.Instance, default);
if (typeDef == null) if (typeDef == null)
return CreateFakeField(declaringType, name, returnType); return CreateFakeField(declaringType, name, returnType);
@ -263,11 +263,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)methodReference); var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)methodReference);
declaringType = ResolveAsType(methodDef.GetDeclaringType()); declaringType = ResolveAsType(methodDef.GetDeclaringType());
var declaringTypeDefinition = declaringType.GetDefinition(); var declaringTypeDefinition = declaringType.GetDefinition();
if (declaringTypeDefinition == null) if (declaringTypeDefinition == null) {
method = CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), methodDef.DecodeSignature(new TypeReferenceSignatureDecoder(), default)); method = CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), methodDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default));
else { } else {
method = (IMethod)declaringTypeDefinition.GetMembers(m => m.MetadataToken == methodReference, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault() method = (IMethod)declaringTypeDefinition.GetMembers(m => m.MetadataToken == methodReference, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault()
?? CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), methodDef.DecodeSignature(new TypeReferenceSignatureDecoder(), default)); ?? CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), methodDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default));
} }
break; break;
case SRM.HandleKind.MemberReference: case SRM.HandleKind.MemberReference:
@ -282,7 +282,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
case SRM.HandleKind.StandaloneSignature: case SRM.HandleKind.StandaloneSignature:
var standaloneSignature = metadata.GetStandaloneSignature((SRM.StandaloneSignatureHandle)methodReference); var standaloneSignature = metadata.GetStandaloneSignature((SRM.StandaloneSignatureHandle)methodReference);
Debug.Assert(standaloneSignature.GetKind() == SRM.StandaloneSignatureKind.Method); Debug.Assert(standaloneSignature.GetKind() == SRM.StandaloneSignatureKind.Method);
var signature = standaloneSignature.DecodeMethodSignature(new TypeReferenceSignatureDecoder(), default); var signature = standaloneSignature.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default);
method = new VarArgInstanceMethod( method = new VarArgInstanceMethod(
method, method,
signature.ParameterTypes.Skip(signature.RequiredParameterCount).Select(p => p.Resolve(context)) signature.ParameterTypes.Skip(signature.RequiredParameterCount).Select(p => p.Resolve(context))
@ -292,7 +292,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
IReadOnlyList<IType> classTypeArguments = null; IReadOnlyList<IType> classTypeArguments = null;
IReadOnlyList<IType> methodTypeArguments = null; IReadOnlyList<IType> methodTypeArguments = null;
var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference); var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference);
var typeArguments = methodSpec.DecodeSignature(new TypeReferenceSignatureDecoder(), default); var typeArguments = methodSpec.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
if (typeArguments.Length > 0) { if (typeArguments.Length > 0) {
methodTypeArguments = typeArguments.SelectArray(arg => arg.Resolve(context)); methodTypeArguments = typeArguments.SelectArray(arg => arg.Resolve(context));
} }
@ -332,7 +332,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
return m; return m;
} }
IType[] parameterTypes; IType[] parameterTypes;
var signature = methodDefinition.DecodeSignature(new TypeReferenceSignatureDecoder(), default); var signature = methodDefinition.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) { if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
parameterTypes = signature.ParameterTypes parameterTypes = signature.ParameterTypes
.Take(signature.RequiredParameterCount) .Take(signature.RequiredParameterCount)

161
ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs

@ -22,26 +22,10 @@ using System.Linq;
using SRM = System.Reflection.Metadata; using SRM = System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{ {
class SignatureTypeReference : ITypeReference
{
readonly SRM.TypeSpecification typeSpecification;
readonly SRM.MetadataReader reader;
public SignatureTypeReference(SRM.TypeSpecificationHandle handle, SRM.MetadataReader reader)
{
this.typeSpecification = reader.GetTypeSpecification(handle);
this.reader = reader;
}
public IType Resolve(ITypeResolveContext context)
{
return typeSpecification.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit)).Resolve(context);
}
}
public sealed class PinnedType : TypeWithElementType public sealed class PinnedType : TypeWithElementType
{ {
public PinnedType(IType elementType) public PinnedType(IType elementType)
@ -103,8 +87,114 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
} }
sealed class DynamicAwareTypeReference : TypeVisitor, ITypeReference
{
readonly ITypeReference reference;
readonly bool isDynamic;
readonly bool[] dynamicInfo;
int typeIndex;
static readonly ITypeResolveContext minimalCorlibContext = new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation());
public static DynamicAwareTypeReference Create(ITypeReference reference, SRM.CustomAttributeHandleCollection? customAttributes, SRM.MetadataReader metadata)
{
bool isDynamic = HasDynamicAttribute(customAttributes, metadata, out var dynamicInfo);
return new DynamicAwareTypeReference(reference, isDynamic, dynamicInfo);
}
static bool HasDynamicAttribute(SRM.CustomAttributeHandleCollection? attributes, SRM.MetadataReader metadata, out bool[] mapping)
{
mapping = null;
if (attributes == null)
return false;
foreach (var handle in attributes) {
var a = metadata.GetCustomAttribute(handle);
var type = a.GetAttributeType(metadata);
if (type.GetFullTypeName(metadata).ToString() == "System.Runtime.CompilerServices.DynamicAttribute") {
var ctor = a.DecodeValue(new TypeSystemAttributeTypeProvider(minimalCorlibContext));
if (ctor.FixedArguments.Length == 1) {
var arg = ctor.FixedArguments[0];
if (arg.Type.ReflectionName == "System.Boolean[]" && arg.Value is ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> values) {
mapping = values.SelectArray(v => (bool)v.Value);
return true;
}
}
return true;
}
}
return false;
}
DynamicAwareTypeReference(ITypeReference reference, bool isDynamic, bool[] dynamicInfo)
{
this.reference = reference;
this.isDynamic = isDynamic;
this.dynamicInfo = dynamicInfo;
}
public IType Resolve(ITypeResolveContext context)
{
if (isDynamic)
return reference.Resolve(context).AcceptVisitor(this);
else
return reference.Resolve(context);
}
public override IType VisitPointerType(PointerType type)
{
typeIndex++;
return base.VisitPointerType(type);
}
public override IType VisitArrayType(ArrayType type)
{
typeIndex++;
return base.VisitArrayType(type);
}
public override IType VisitByReferenceType(ByReferenceType type)
{
typeIndex++;
return base.VisitByReferenceType(type);
}
public override IType VisitParameterizedType(ParameterizedType type)
{
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++) {
typeIndex++;
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 (!isDynamic)
return type;
if (type.KnownTypeCode == KnownTypeCode.Object) {
if (dynamicInfo == null || typeIndex >= dynamicInfo.Length)
return SpecialType.Dynamic;
if (dynamicInfo[typeIndex])
return SpecialType.Dynamic;
return type;
}
return type;
}
}
class TypeReferenceSignatureDecoder : SRM.ISignatureTypeProvider<ITypeReference, Unit> class TypeReferenceSignatureDecoder : SRM.ISignatureTypeProvider<ITypeReference, Unit>
{ {
public static readonly TypeReferenceSignatureDecoder Instance = new TypeReferenceSignatureDecoder();
private TypeReferenceSignatureDecoder() { }
public ITypeReference GetArrayType(ITypeReference elementType, SRM.ArrayShape shape) public ITypeReference GetArrayType(ITypeReference elementType, SRM.ArrayShape shape)
{ {
return new ArrayTypeReference(elementType, shape.Rank); return new ArrayTypeReference(elementType, shape.Rank);
@ -176,7 +266,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public ITypeReference GetTypeFromSpecification(SRM.MetadataReader reader, Unit genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind) public ITypeReference GetTypeFromSpecification(SRM.MetadataReader reader, Unit genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)
{ {
return new SignatureTypeReference(handle, reader); return reader.GetTypeSpecification(handle)
.DecodeSignature(this, default);
} }
} }
@ -235,38 +326,4 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return type.IsKnownType(KnownTypeCode.Type); return type.IsKnownType(KnownTypeCode.Type);
} }
} }
public class MetadataUnresolvedAttributeBlob : IUnresolvedAttribute, ISupportsInterning
{
SRM.MetadataReader reader;
ITypeReference attributeType;
SRM.CustomAttribute attribute;
public MetadataUnresolvedAttributeBlob(SRM.MetadataReader reader, ITypeReference attributeType, SRM.CustomAttribute attribute)
{
this.reader = reader;
this.attributeType = attributeType;
this.attribute = attribute;
}
public DomRegion Region => DomRegion.Empty;
public IAttribute CreateResolvedAttribute(ITypeResolveContext context)
{
var blob = reader.GetBlobBytes(attribute.Value);
var signature = attribute.DecodeValue(new TypeSystemAttributeTypeProvider(context));
return new UnresolvedAttributeBlob(attributeType, signature.FixedArguments.Select(t => t.Type.ToTypeReference()).ToArray(), blob)
.CreateResolvedAttribute(context);
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
throw new NotImplementedException();
}
int ISupportsInterning.GetHashCodeForInterning()
{
throw new NotImplementedException();
}
}
} }

269
ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs

@ -112,6 +112,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
MetadataReader currentModule; MetadataReader currentModule;
DefaultUnresolvedAssembly currentAssembly; DefaultUnresolvedAssembly currentAssembly;
static readonly ITypeResolveContext minimalCorlibContext = new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation());
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MetadataLoader"/> class. /// Initializes a new instance of the <see cref="MetadataLoader"/> class.
@ -149,7 +150,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
// Read assembly and module attributes // Read assembly and module attributes
IList<IUnresolvedAttribute> assemblyAttributes = new List<IUnresolvedAttribute>(); IList<IUnresolvedAttribute> assemblyAttributes = new List<IUnresolvedAttribute>();
IList<IUnresolvedAttribute> moduleAttributes = new List<IUnresolvedAttribute>(); IList<IUnresolvedAttribute> moduleAttributes = new List<IUnresolvedAttribute>();
AssemblyDefinition assemblyDefinition = default(AssemblyDefinition);
if (currentModule.IsAssembly) { if (currentModule.IsAssembly) {
AddAttributes(currentModule.GetAssemblyDefinition(), assemblyAttributes); AddAttributes(currentModule.GetAssemblyDefinition(), assemblyAttributes);
} }
@ -166,15 +166,19 @@ namespace ICSharpCode.Decompiler.TypeSystem
foreach (ExportedTypeHandle t in currentModule.ExportedTypes) { foreach (ExportedTypeHandle t in currentModule.ExportedTypes) {
var type = currentModule.GetExportedType(t); var type = currentModule.GetExportedType(t);
if (type.IsForwarder) { if (type.IsForwarder) {
throw new NotImplementedException();/* IAssemblyReference assemblyRef;
switch (type.Implementation.Kind) { switch (type.Implementation.Kind) {
case HandleKind.AssemblyFile: case HandleKind.AssemblyFile:
throw new NotImplementedException(); // type is defined in another module. assemblyRef = DefaultAssemblyReference.CurrentAssembly;
case HandleKind.ExportedType:
break; break;
case HandleKind.ExportedType:
throw new NotImplementedException();
case HandleKind.AssemblyReference: case HandleKind.AssemblyReference:
var asmRef = currentModule.GetAssemblyReference((AssemblyReferenceHandle)type.Implementation);
assemblyRef = new DefaultAssemblyReference(asmRef.GetFullAssemblyName(currentModule));
break; break;
default:
throw new NotSupportedException();
} }
int typeParameterCount; int typeParameterCount;
string ns = currentModule.GetString(type.Namespace); string ns = currentModule.GetString(type.Namespace);
@ -182,10 +186,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
ns = interningProvider.Intern(ns); ns = interningProvider.Intern(ns);
name = interningProvider.Intern(name); name = interningProvider.Intern(name);
var typeRef = new GetClassTypeReference(, ns, name, typeParameterCount); var typeRef = new GetClassTypeReference(assemblyRef, ns, name, typeParameterCount);
typeRef = interningProvider.Intern(typeRef); typeRef = interningProvider.Intern(typeRef);
var key = new TopLevelTypeName(ns, name, typeParameterCount); var key = new TopLevelTypeName(ns, name, typeParameterCount);
currentAssembly.AddTypeForwarder(key, typeRef);*/ currentAssembly.AddTypeForwarder(key, typeRef);
} }
} }
@ -196,6 +200,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
foreach (TypeDefinitionHandle h in module.TypeDefinitions) { foreach (TypeDefinitionHandle h in module.TypeDefinitions) {
this.CancellationToken.ThrowIfCancellationRequested(); this.CancellationToken.ThrowIfCancellationRequested();
var td = module.GetTypeDefinition(h); var td = module.GetTypeDefinition(h);
if (!td.GetDeclaringType().IsNil) continue;
if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) { if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
string name = module.GetString(td.Name); string name = module.GetString(td.Name);
if (name.Length == 0) if (name.Length == 0)
@ -206,7 +211,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
currentAssembly.AddTypeDefinition(t); currentAssembly.AddTypeDefinition(t);
RegisterCecilObject(t, h); RegisterCecilObject(t, h);
} else { } else {
var t = CreateTopLevelTypeDefinition(td); var t = CreateTopLevelTypeDefinition(h, td);
cecilTypeDefs.Add(h); cecilTypeDefs.Add(h);
typeDefs.Add(t); typeDefs.Add(t);
currentAssembly.AddTypeDefinition(t); currentAssembly.AddTypeDefinition(t);
@ -255,7 +260,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
if (typeDefinition.IsNil) if (typeDefinition.IsNil)
throw new ArgumentNullException(nameof(typeDefinition)); throw new ArgumentNullException(nameof(typeDefinition));
var td = CreateTopLevelTypeDefinition(currentModule.GetTypeDefinition(typeDefinition)); var td = CreateTopLevelTypeDefinition(typeDefinition, currentModule.GetTypeDefinition(typeDefinition));
InitTypeDefinition(typeDefinition, td); InitTypeDefinition(typeDefinition, td);
return td; return td;
} }
@ -266,7 +271,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
if (fileName == null) if (fileName == null)
throw new ArgumentNullException(nameof(fileName)); throw new ArgumentNullException(nameof(fileName));
using (var module = new PEReader(new FileStream(fileName, FileMode.Open))) using (var module = new PEReader(new FileStream(fileName, FileMode.Open, FileAccess.Read)))
return LoadModule(module.GetMetadataReader()); return LoadModule(module.GetMetadataReader());
} }
#endregion #endregion
@ -279,7 +284,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// a type system type reference.</param> /// a type system type reference.</param>
/// <param name="typeAttributes">Attributes associated with the Cecil type reference. /// <param name="typeAttributes">Attributes associated with the Cecil type reference.
/// This is used to support the 'dynamic' type.</param> /// This is used to support the 'dynamic' type.</param>
public ITypeReference ReadTypeReference(EntityHandle type, CustomAttributeHandleCollection typeAttributes = default(CustomAttributeHandleCollection)) public ITypeReference ReadTypeReference(EntityHandle type, CustomAttributeHandleCollection? typeAttributes = null)
{ {
ITypeReference CreateTypeReference(TypeReferenceHandle handle) ITypeReference CreateTypeReference(TypeReferenceHandle handle)
{ {
@ -289,28 +294,24 @@ namespace ICSharpCode.Decompiler.TypeSystem
return new GetClassTypeReference(handle.GetFullTypeName(currentModule), DefaultAssemblyReference.CurrentAssembly); return new GetClassTypeReference(handle.GetFullTypeName(currentModule), DefaultAssemblyReference.CurrentAssembly);
var asm = currentModule.GetAssemblyReference(asmref); var asm = currentModule.GetAssemblyReference(asmref);
return new GetClassTypeReference(handle.GetFullTypeName(currentModule), new DefaultAssemblyReference(currentModule.GetString(asm.Name))); return new GetClassTypeReference(handle.GetFullTypeName(currentModule), new DefaultAssemblyReference(currentModule.GetString(asm.Name)));
} }
switch (type.Kind) { switch (type.Kind) {
case HandleKind.TypeSpecification: case HandleKind.TypeSpecification:
return new SignatureTypeReference((TypeSpecificationHandle)type, currentModule); return DynamicAwareTypeReference.Create(currentModule.GetTypeSpecification((TypeSpecificationHandle)type)
.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default), typeAttributes, currentModule);
case HandleKind.TypeReference: case HandleKind.TypeReference:
return CreateTypeReference((TypeReferenceHandle)type); return CreateTypeReference((TypeReferenceHandle)type);
case HandleKind.TypeDefinition: case HandleKind.TypeDefinition:
return new TypeDefTokenTypeReference(type); return new TypeDefTokenTypeReference(type);
case HandleKind.FieldDefinition:
var fd = currentModule.GetFieldDefinition((FieldDefinitionHandle)type);
return DynamicAwareTypeReference.Create(fd.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default), fd.GetCustomAttributes(), currentModule);
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
} }
} }
class DynamicTypeVisitor : TypeVisitor
{
public override IType VisitPointerType(PointerType type)
{
return base.VisitPointerType(type);
}
}
sealed class TypeDefTokenTypeReference : ITypeReference sealed class TypeDefTokenTypeReference : ITypeReference
{ {
readonly EntityHandle token; readonly EntityHandle token;
@ -402,7 +403,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
if ((retParam.Attributes & ParameterAttributes.HasFieldMarshal) == ParameterAttributes.HasFieldMarshal) if ((retParam.Attributes & ParameterAttributes.HasFieldMarshal) == ParameterAttributes.HasFieldMarshal)
return true; return true;
} }
return methodDefinition.GetCustomAttributes().Count > 0; return methodDefinition.GetCustomAttributes().Count > 0 || methodDefinition.GetParameters().Any(p => currentModule.GetParameter(p).GetCustomAttributes().Any());
} }
void AddAttributes(MethodDefinition methodDefinition, IList<IUnresolvedAttribute> attributes, IList<IUnresolvedAttribute> returnTypeAttributes) void AddAttributes(MethodDefinition methodDefinition, IList<IUnresolvedAttribute> attributes, IList<IUnresolvedAttribute> returnTypeAttributes)
@ -699,14 +700,30 @@ namespace ICSharpCode.Decompiler.TypeSystem
case "System.ParamArrayAttribute": case "System.ParamArrayAttribute":
continue; continue;
} }
targetCollection.Add(ReadAttribute(attribute)); targetCollection.Add(ReadAttribute(handle));
} }
} }
public IUnresolvedAttribute ReadAttribute(CustomAttribute attribute) public IUnresolvedAttribute ReadAttribute(CustomAttributeHandle handle)
{ {
var attribute = currentModule.GetCustomAttribute(handle);
ITypeReference attributeType = ReadTypeReference(attribute.GetAttributeType(currentModule)); ITypeReference attributeType = ReadTypeReference(attribute.GetAttributeType(currentModule));
return interningProvider.Intern(new MetadataUnresolvedAttributeBlob(currentModule, attributeType, attribute)); MethodSignature<ITypeReference> signature;
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
var md = currentModule.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
signature = md.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
break;
case HandleKind.MemberReference:
var mr = currentModule.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
Debug.Assert(mr.GetKind() == MemberReferenceKind.Method);
signature = mr.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default);
break;
default:
throw new NotSupportedException();
}
return interningProvider.Intern(new UnresolvedAttributeBlob(attributeType, signature.ParameterTypes, currentModule.GetBlobBytes(attribute.Value)));
} }
#endregion #endregion
@ -739,11 +756,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
#endregion #endregion
#region Read Type Definition #region Read Type Definition
DefaultUnresolvedTypeDefinition CreateTopLevelTypeDefinition(TypeDefinition typeDefinition) DefaultUnresolvedTypeDefinition CreateTopLevelTypeDefinition(TypeDefinitionHandle handle, TypeDefinition typeDefinition)
{ {
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(currentModule.GetString(typeDefinition.Name)); string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(currentModule.GetString(typeDefinition.Name));
var td = new DefaultUnresolvedTypeDefinition(currentModule.GetString(typeDefinition.Namespace), name); var td = new DefaultUnresolvedTypeDefinition(currentModule.GetString(typeDefinition.Namespace), name);
//td.MetadataToken = ... td.MetadataToken = handle;
InitTypeParameters(currentModule, typeDefinition, td.TypeParameters); InitTypeParameters(currentModule, typeDefinition, td.TypeParameters);
return td; return td;
} }
@ -802,8 +819,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (typeDefinition.IsEnum(currentModule)) { if (typeDefinition.IsEnum(currentModule)) {
foreach (FieldDefinitionHandle h in typeDefinition.GetFields()) { foreach (FieldDefinitionHandle h in typeDefinition.GetFields()) {
var enumField = currentModule.GetFieldDefinition(h); var enumField = currentModule.GetFieldDefinition(h);
if ((enumField.Attributes & FieldAttributes.Static) == 0) { if (!enumField.HasFlag(FieldAttributes.Static)) {
baseTypes.Add(enumField.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit))); baseTypes.Add(enumField.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default));
break; break;
} }
} }
@ -890,7 +907,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
static bool IsDelegate(MetadataReader currentModule, TypeDefinition type) static bool IsDelegate(MetadataReader currentModule, TypeDefinition type)
{ {
if (type.BaseType != null) { if (!type.BaseType.IsNil) {
var baseTypeName = type.BaseType.GetFullTypeName(currentModule).ToString(); var baseTypeName = type.BaseType.GetFullTypeName(currentModule).ToString();
if (baseTypeName == "System.MulticastDelegate") if (baseTypeName == "System.MulticastDelegate")
return true; return true;
@ -917,7 +934,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
foreach (MethodDefinitionHandle h in typeDefinition.GetMethods()) { foreach (MethodDefinitionHandle h in typeDefinition.GetMethods()) {
var method = currentModule.GetMethodDefinition(h); var method = currentModule.GetMethodDefinition(h);
/*if (IsVisible(method.Attributes) && !IsAccessor(h.GetMethodSemanticsAttributes(currentModule))) { if (IsVisible(method.Attributes) && !IsAccessor(h.GetMethodSemanticsAttributes(currentModule))) {
SymbolKind type = SymbolKind.Method; SymbolKind type = SymbolKind.Method;
if ((method.Attributes & MethodAttributes.SpecialName) != 0) { if ((method.Attributes & MethodAttributes.SpecialName) != 0) {
if (method.IsConstructor(currentModule)) if (method.IsConstructor(currentModule))
@ -926,11 +943,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
type = SymbolKind.Operator; type = SymbolKind.Operator;
} }
members.Add(ReadMethod(h, td, type)); members.Add(ReadMethod(h, td, type));
}*/ }
} }
foreach (FieldDefinitionHandle h in typeDefinition.GetFields()) { foreach (FieldDefinitionHandle h in typeDefinition.GetFields()) {
var field = currentModule.GetFieldDefinition(h); var field = currentModule.GetFieldDefinition(h);
if (IsVisible(field.Attributes) && (field.Attributes & FieldAttributes.SpecialName) != 0) { if (IsVisible(field.Attributes) && (field.Attributes & FieldAttributes.SpecialName) == 0) {
members.Add(ReadField(h, td)); members.Add(ReadField(h, td));
} }
} }
@ -982,7 +999,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
static bool IsAccessor(MethodSemanticsAttributes semantics) static bool IsAccessor(MethodSemanticsAttributes semantics)
{ {
return semantics != MethodSemanticsAttributes.Other; return semantics > (MethodSemanticsAttributes)0 && semantics != MethodSemanticsAttributes.Other;
} }
#endregion #endregion
@ -1201,18 +1218,21 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
var declaringType = currentModule.GetTypeDefinition(method.GetDeclaringType());
var reader = currentModule.GetBlobReader(method.Signature);
var signature = method.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit));
m.ReturnType = signature.ReturnType;
if (HasAnyAttributes(method)) if (HasAnyAttributes(method))
AddAttributes(method, m.Attributes, m.ReturnTypeAttributes); AddAttributes(method, m.Attributes, m.ReturnTypeAttributes);
TranslateModifiers(handle, m); TranslateModifiers(handle, m);
var declaringType = currentModule.GetTypeDefinition(method.GetDeclaringType());
var reader = currentModule.GetBlobReader(method.Signature);
var signature = method.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
var parameters = method.GetParameters();
int parameterOffset = parameters.Count > signature.ParameterTypes.Length ? 1 : 0;
CustomAttributeHandleCollection? returnAttributes = parameterOffset > 0 ? (CustomAttributeHandleCollection?)currentModule.GetParameter(parameters.First()).GetCustomAttributes() : null;
m.ReturnType = DynamicAwareTypeReference.Create(signature.ReturnType, returnAttributes, currentModule);
int j = 0; int j = 0;
foreach (var par in method.GetParameters()) { foreach (var par in method.GetParameters().Skip(parameterOffset)) {
m.Parameters.Add(ReadParameter(par, signature.ParameterTypes[j])); m.Parameters.Add(ReadParameter(par, signature.ParameterTypes[j]));
j++; j++;
} }
@ -1225,20 +1245,44 @@ namespace ICSharpCode.Decompiler.TypeSystem
if ((method.Attributes & MethodAttributes.Static) == MethodAttributes.Static && HasExtensionAttribute(currentModule, method.GetCustomAttributes())) { if ((method.Attributes & MethodAttributes.Static) == MethodAttributes.Static && HasExtensionAttribute(currentModule, method.GetCustomAttributes())) {
m.IsExtensionMethod = true; m.IsExtensionMethod = true;
} }
/* TODO overrides
int lastDot = m.Name.LastIndexOf('.'); int lastDot = m.Name.LastIndexOf('.');
if (lastDot >= 0 && method.HasOverrides) { var overrides = handle.GetMethodImplementations(currentModule);
if (lastDot >= 0 && overrides.Any()) {
// To be consistent with the parser-initialized type system, shorten the method name: // To be consistent with the parser-initialized type system, shorten the method name:
if (ShortenInterfaceImplNames) if (ShortenInterfaceImplNames)
m.Name = method.Name.Substring(lastDot + 1); m.Name = m.Name.Substring(lastDot + 1);
m.IsExplicitInterfaceImplementation = true; m.IsExplicitInterfaceImplementation = true;
foreach (var or in method.Overrides) { foreach (var h in overrides) {
var or = currentModule.GetMethodImplementation(h);
EntityHandle orDeclaringType;
string orName;
int genericParameterCount;
MethodSignature<ITypeReference> orSignature;
switch (or.MethodDeclaration.Kind) {
case HandleKind.MethodDefinition:
var md = currentModule.GetMethodDefinition((MethodDefinitionHandle)or.MethodDeclaration);
orDeclaringType = md.GetDeclaringType();
orName = currentModule.GetString(md.Name);
orSignature = md.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
genericParameterCount = orSignature.GenericParameterCount;
break;
case HandleKind.MemberReference:
var mr = currentModule.GetMemberReference((MemberReferenceHandle)or.MethodDeclaration);
Debug.Assert(mr.GetKind() == MemberReferenceKind.Method);
orDeclaringType = mr.Parent;
orName = currentModule.GetString(mr.Name);
orSignature = mr.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default);
genericParameterCount = orSignature.GenericParameterCount;
break;
default:
throw new NotSupportedException();
}
m.ExplicitInterfaceImplementations.Add(new DefaultMemberReference( m.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(
accessorOwner != null ? SymbolKind.Accessor : SymbolKind.Method, accessorOwner != null ? SymbolKind.Accessor : SymbolKind.Method,
ReadTypeReference(or.DeclaringType), ReadTypeReference(orDeclaringType),
or.Name, or.GenericParameters.Count, m.Parameters.Select(p => p.Type).ToList())); orName, genericParameterCount, m.Parameters.Select(p => p.Type).ToList()));
} }
}*/ }
FinishReadMember(m, handle); FinishReadMember(m, handle);
return m; return m;
@ -1316,7 +1360,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (handle.IsNil) if (handle.IsNil)
throw new ArgumentNullException(nameof(handle)); throw new ArgumentNullException(nameof(handle));
var parameter = currentModule.GetParameter(handle); var parameter = currentModule.GetParameter(handle);
var p = new DefaultUnresolvedParameter(type, interningProvider.Intern(currentModule.GetString(parameter.Name))); var p = new DefaultUnresolvedParameter(DynamicAwareTypeReference.Create(type, parameter.GetCustomAttributes(), currentModule), interningProvider.Intern(currentModule.GetString(parameter.Name)));
if (type is ByReferenceTypeReference) { if (type is ByReferenceTypeReference) {
if ((parameter.Attributes & ParameterAttributes.In) == 0 && (parameter.Attributes & ParameterAttributes.Out) != 0) if ((parameter.Attributes & ParameterAttributes.In) == 0 && (parameter.Attributes & ParameterAttributes.Out) != 0)
@ -1332,6 +1376,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
var constant = currentModule.GetConstant(constantHandle); var constant = currentModule.GetConstant(constantHandle);
var blobReader = currentModule.GetBlobReader(constant.Value); var blobReader = currentModule.GetBlobReader(constant.Value);
p.DefaultValue = CreateSimpleConstantValue(type, blobReader.ReadConstant(constant.TypeCode)); p.DefaultValue = CreateSimpleConstantValue(type, blobReader.ReadConstant(constant.TypeCode));
} else {
p.DefaultValue = CreateSimpleConstantValue(type, null);
} }
} }
@ -1358,13 +1404,31 @@ namespace ICSharpCode.Decompiler.TypeSystem
|| att == FieldAttributes.Family || att == FieldAttributes.Family
|| att == FieldAttributes.FamORAssem; || att == FieldAttributes.FamORAssem;
} }
/*
decimal? TryDecodeDecimalConstantAttribute(CustomAttribute attribute) decimal? TryDecodeDecimalConstantAttribute(CustomAttributeHandle handle)
{ {
if (attribute.ConstructorArguments.Count != 5) var attribute = currentModule.GetCustomAttribute(handle);
ITypeReference attributeType = ReadTypeReference(attribute.GetAttributeType(currentModule));
MethodSignature<ITypeReference> signature;
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
var md = currentModule.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
signature = md.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
break;
case HandleKind.MemberReference:
var mr = currentModule.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
Debug.Assert(mr.GetKind() == MemberReferenceKind.Method);
signature = mr.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default);
break;
default:
throw new NotSupportedException();
}
if (signature.RequiredParameterCount != 5)
return null; return null;
BlobReader reader = new BlobReader(attribute.GetBlob(), null); var reader = new Implementation.BlobReader(currentModule.GetBlobBytes(attribute.Value), null);
if (reader.ReadUInt16() != 0x0001) { if (reader.ReadUInt16() != 0x0001) {
Debug.WriteLine("Unknown blob prolog"); Debug.WriteLine("Unknown blob prolog");
return null; return null;
@ -1372,9 +1436,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
// DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low) // DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low)
// Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required. // Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required.
var ctorArgs = new object[attribute.ConstructorArguments.Count]; var ctorArgs = new object[signature.RequiredParameterCount];
for (int i = 0; i < ctorArgs.Length; i++) { for (int i = 0; i < ctorArgs.Length; i++) {
switch (attribute.ConstructorArguments[i].Type.FullName) { switch (signature.ParameterTypes[i].Resolve(minimalCorlibContext).FullName) {
case "System.Byte": case "System.Byte":
ctorArgs[i] = reader.ReadByte(); ctorArgs[i] = reader.ReadByte();
break; break;
@ -1394,7 +1458,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
return new decimal((int)ctorArgs[4], (int)ctorArgs[3], (int)ctorArgs[2], (byte)ctorArgs[1] != 0, (byte)ctorArgs[0]); return new decimal((int)ctorArgs[4], (int)ctorArgs[3], (int)ctorArgs[2], (byte)ctorArgs[1] != 0, (byte)ctorArgs[0]);
} }
*/
public IUnresolvedField ReadField(FieldDefinitionHandle handle, IUnresolvedTypeDefinition parentType) public IUnresolvedField ReadField(FieldDefinitionHandle handle, IUnresolvedTypeDefinition parentType)
{ {
@ -1408,20 +1471,19 @@ namespace ICSharpCode.Decompiler.TypeSystem
f.Accessibility = GetAccessibility(field.Attributes); f.Accessibility = GetAccessibility(field.Attributes);
f.IsReadOnly = (field.Attributes & FieldAttributes.InitOnly) == FieldAttributes.InitOnly; f.IsReadOnly = (field.Attributes & FieldAttributes.InitOnly) == FieldAttributes.InitOnly;
f.IsStatic = (field.Attributes & FieldAttributes.Static) == FieldAttributes.Static; f.IsStatic = (field.Attributes & FieldAttributes.Static) == FieldAttributes.Static;
f.ReturnType = ResolveDynamicTypes(field.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit)), field.GetCustomAttributes()); f.ReturnType = ReadTypeReference(handle, field.GetCustomAttributes());
var constantHandle = field.GetDefaultValue(); var constantHandle = field.GetDefaultValue();
if (!constantHandle.IsNil) { if (!constantHandle.IsNil) {
var constant = currentModule.GetConstant(constantHandle); var constant = currentModule.GetConstant(constantHandle);
var blobReader = currentModule.GetBlobReader(constant.Value); var blobReader = currentModule.GetBlobReader(constant.Value);
f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, blobReader.ReadConstant(constant.TypeCode)); f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, blobReader.ReadConstant(constant.TypeCode));
} else { } else {
// TODO decimal constants var decConstant = field.GetCustomAttributes().FirstOrDefault(a => currentModule.GetCustomAttribute(a).GetAttributeType(currentModule).GetFullTypeName(currentModule).ReflectionName == "System.Runtime.CompilerServices.DecimalConstantAttribute");
/*var decConstant = field.CustomAttributes.FirstOrDefault(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.DecimalConstantAttribute"); if (!decConstant.IsNil) {
if (decConstant != null) {
var constValue = TryDecodeDecimalConstantAttribute(decConstant); var constValue = TryDecodeDecimalConstantAttribute(decConstant);
if (constValue != null) if (constValue != null)
f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, constValue); f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, constValue);
}*/ }
} }
AddAttributes(field, f); AddAttributes(field, f);
@ -1455,80 +1517,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
#endregion #endregion
#region Resolve dynamic type
ITypeReference ResolveDynamicTypes(ITypeReference type, CustomAttributeHandleCollection attributes)
{
int typeIndex = 0;
return ResolveDynamicTypes(type, attributes, ref typeIndex);
}
ITypeReference ResolveDynamicTypes(ITypeReference type, CustomAttributeHandleCollection attributes, ref int typeIndex)
{
// TODO : interning??
ITypeReference replacement;
switch (type) {
case ByReferenceTypeReference brtr:
typeIndex++;
replacement = ResolveDynamicTypes(brtr.ElementType, attributes, ref typeIndex);
if (replacement == brtr.ElementType)
return brtr;
else
return new ByReferenceTypeReference(replacement);
case PointerTypeReference ptr:
typeIndex++;
replacement = ResolveDynamicTypes(ptr.ElementType, attributes, ref typeIndex);
if (replacement == ptr.ElementType)
return ptr;
else
return new PointerTypeReference(replacement);
case TypeParameterReference tpr:
return tpr;
case ParameterizedTypeReference genericType:
ITypeReference baseType = ResolveDynamicTypes(genericType.GenericType, attributes, ref typeIndex);
ITypeReference[] para = new ITypeReference[genericType.TypeArguments.Count];
for (int i = 0; i < para.Length; ++i) {
typeIndex++;
para[i] = ResolveDynamicTypes(genericType.TypeArguments[i], attributes, ref typeIndex);
}
return new ParameterizedTypeReference(baseType, para);
case NestedTypeReference ntr:
replacement = ResolveDynamicTypes(ntr.DeclaringTypeReference, attributes, ref typeIndex);
if (replacement == ntr.DeclaringTypeReference)
return ntr;
else
return new NestedTypeReference(replacement, ntr.Name, ntr.AdditionalTypeParameterCount);
case GetClassTypeReference gctr:
return gctr;
case KnownTypeReference ktr:
if (ktr.KnownTypeCode == KnownTypeCode.Object && HasDynamicAttribute(attributes, typeIndex))
return SpecialType.Dynamic.ToTypeReference();
else
return ktr;
default:
return type;
}
}
static readonly ITypeResolveContext minimalCorlibContext = new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation());
bool HasDynamicAttribute(CustomAttributeHandleCollection attributes, int typeIndex)
{
foreach (CustomAttributeHandle handle in attributes) {
var a = currentModule.GetCustomAttribute(handle);
var type = a.GetAttributeType(currentModule);
if (type.GetFullTypeName(currentModule).ToString() == "System.Runtime.CompilerServices.DynamicAttribute") {
var ctor = a.DecodeValue(new TypeSystemAttributeTypeProvider(minimalCorlibContext));
if (ctor.FixedArguments.Length == 1) {
if (ctor.FixedArguments[0].Value is bool[] values && typeIndex < values.Length)
return values[typeIndex];
}
return true;
}
}
return false;
}
#endregion
#region Type Parameter Constraints #region Type Parameter Constraints
void AddConstraints(DefaultUnresolvedTypeParameter tp, GenericParameter g) void AddConstraints(DefaultUnresolvedTypeParameter tp, GenericParameter g)
{ {
@ -1593,29 +1581,26 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (!accessors.Getter.IsNil && !accessors.Setter.IsNil) if (!accessors.Getter.IsNil && !accessors.Setter.IsNil)
p.Accessibility = MergePropertyAccessibility(GetAccessibility(currentModule.GetMethodDefinition(accessors.Getter).Attributes), GetAccessibility(currentModule.GetMethodDefinition(accessors.Setter).Attributes)); p.Accessibility = MergePropertyAccessibility(GetAccessibility(currentModule.GetMethodDefinition(accessors.Getter).Attributes), GetAccessibility(currentModule.GetMethodDefinition(accessors.Setter).Attributes));
var signature = property.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit)); var signature = property.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
p.ReturnType = signature.ReturnType; p.ReturnType = DynamicAwareTypeReference.Create(signature.ReturnType, property.GetCustomAttributes(), currentModule);
p.Getter = ReadMethod(accessors.Getter, parentType, SymbolKind.Accessor, p); p.Getter = ReadMethod(accessors.Getter, parentType, SymbolKind.Accessor, p);
p.Setter = ReadMethod(accessors.Setter, parentType, SymbolKind.Accessor, p); p.Setter = ReadMethod(accessors.Setter, parentType, SymbolKind.Accessor, p);
ParameterHandleCollection parameterHandles = default(ParameterHandleCollection); ParameterHandleCollection parameterHandles = default(ParameterHandleCollection);
int parameterCount = 0;
if (!accessors.Getter.IsNil) { if (!accessors.Getter.IsNil) {
var getter = currentModule.GetMethodDefinition(accessors.Getter); var getter = currentModule.GetMethodDefinition(accessors.Getter);
parameterHandles = getter.GetParameters(); parameterHandles = getter.GetParameters();
parameterCount = parameterHandles.Count;
} else { } else {
if (!accessors.Setter.IsNil) { if (!accessors.Setter.IsNil) {
var setter = currentModule.GetMethodDefinition(accessors.Setter); var setter = currentModule.GetMethodDefinition(accessors.Setter);
parameterHandles = setter.GetParameters(); parameterHandles = setter.GetParameters();
parameterCount = parameterHandles.Count - 1;
} }
} }
int i = 0; int i = 0;
foreach (var par in parameterHandles) { int parameterOffset = parameterHandles.Count > signature.ParameterTypes.Length ? 1 : 0;
if (i >= parameterCount) break; foreach (var par in parameterHandles.Skip(parameterOffset)) {
p.Parameters.Add(ReadParameter(par, signature.ParameterTypes[i])); p.Parameters.Add(ReadParameter(par, signature.ParameterTypes[i]));
i++; i++;
} }

2
ICSharpCode.Decompiler/Util/CollectionExtensions.cs

@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.Util
/// Equivalent to <code>collection.Select(func).ToArray()</code>, but more efficient as it makes /// Equivalent to <code>collection.Select(func).ToArray()</code>, but more efficient as it makes
/// use of the input collection's known size. /// use of the input collection's known size.
/// </summary> /// </summary>
public static U[] SelectArray<T, U>(this IReadOnlyCollection<T> collection, Func<T, U> func) public static U[] SelectReadOnlyArray<T, U>(this IReadOnlyCollection<T> collection, Func<T, U> func)
{ {
U[] result = new U[collection.Count]; U[] result = new U[collection.Count];
int index = 0; int index = 0;

Loading…
Cancel
Save