Browse Source

Use MetadataAssembly (the new TS implementation) in DecompilerTypeSystem.

pull/1198/head
Daniel Grunwald 7 years ago
parent
commit
621d90d006
  1. 44
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  2. 2
      ICSharpCode.Decompiler/SRMHacks.cs
  3. 213
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  4. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
  5. 77
      ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs
  6. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
  7. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
  8. 7
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs
  9. 137
      ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs
  10. 3
      ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs
  11. 19
      ICSharpCode.Decompiler/Util/CollectionExtensions.cs

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

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Resolver;
@ -434,15 +435,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -434,15 +435,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} else if (mt != null && mt.MemberName.EndsWith("Attribute", StringComparison.Ordinal)) {
mt.MemberName = mt.MemberName.Substring(0, mt.MemberName.Length - 9);
}
foreach (var arg in attribute.FixedArguments) {
attr.Arguments.Add(ConvertConstantValue(arg.Type, arg.Value));
var parameters = attribute.Constructor?.Parameters ?? EmptyList<IParameter>.Instance;
foreach (var (arg, p) in attribute.FixedArguments.ZipLongest(parameters)) {
attr.Arguments.Add(ConvertConstantValue(p?.Type ?? arg.Type, arg.Type, arg.Value));
}
if (attribute.NamedArguments.Length > 0) {
InitializedObjectResolveResult targetResult = new InitializedObjectResolveResult(attribute.AttributeType);
foreach (var namedArg in attribute.NamedArguments) {
NamedExpression namedArgument = new NamedExpression(namedArg.Name, ConvertConstantValue(namedArg.Type, namedArg.Value));
if (AddResolveResultAnnotations) {
//namedArgument.AddAnnotation(new MemberResolveResult(targetResult, pair.Key));
IMember member = CustomAttribute.MemberForNamedArgument(attribute.AttributeType, namedArg);
if (member != null) {
namedArgument.AddAnnotation(new MemberResolveResult(targetResult, member));
}
}
attr.Arguments.Add(namedArgument);
}
@ -523,6 +528,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -523,6 +528,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// However, the returned expression will always be implicitly convertible to <paramref name="type"/>.
/// </summary>
public Expression ConvertConstantValue(IType type, object constantValue)
{
return ConvertConstantValue(type, type, constantValue);
}
/// <summary>
/// Creates an Expression for the given constant value.
/// </summary>
public Expression ConvertConstantValue(IType expectedType, IType type, object constantValue)
{
if (type == null)
throw new ArgumentNullException("type");
@ -538,20 +551,41 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -538,20 +551,41 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
expr.AddAnnotation(new ConstantResolveResult(type, null));
return expr;
}
} else if (constantValue is IType typeofType) {
var expr = new TypeOfExpression(ConvertType(typeofType));
if (AddResolveResultAnnotations)
expr.AddAnnotation(new TypeOfResolveResult(type, typeofType));
return expr;
} else if (constantValue is ImmutableArray<System.Reflection.Metadata.CustomAttributeTypedArgument<IType>> arr) {
var elementType = (type as ArrayType)?.ElementType ?? SpecialType.UnknownType;
var expr = new ArrayCreateExpression();
expr.Type = ConvertType(type);
if (expr.Type is ComposedType composedType) {
composedType.ArraySpecifiers.MoveTo(expr.AdditionalArraySpecifiers);
if (!composedType.HasNullableSpecifier && composedType.PointerRank == 0)
expr.Type = composedType.BaseType;
}
expr.Initializer = new ArrayInitializerExpression(arr.Select(e => ConvertConstantValue(elementType, e.Type, e.Value)));
return expr;
} else if (type.Kind == TypeKind.Enum) {
return ConvertEnumValue(type, (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false));
} else {
if (IsSpecialConstant(type, constantValue, out var expr))
return expr;
if (type.IsCSharpSmallIntegerType()) {
IType literalType = type;
bool smallInteger = type.IsCSharpSmallIntegerType();
if (smallInteger) {
// C# does not have integer literals of small integer types,
// use `int` literal instead.
constantValue = CSharpPrimitiveCast.Cast(TypeCode.Int32, constantValue, false);
type = type.GetDefinition().Compilation.FindType(KnownTypeCode.Int32);
literalType = type.GetDefinition().Compilation.FindType(KnownTypeCode.Int32);
}
expr = new PrimitiveExpression(constantValue);
if (AddResolveResultAnnotations)
expr.AddAnnotation(new ConstantResolveResult(type, constantValue));
if (smallInteger && !type.Equals(expectedType)) {
expr = new CastExpression(ConvertType(type), expr);
}
return expr;
}
}

2
ICSharpCode.Decompiler/SRMHacks.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler @@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler
}
}
return resultBuilder.MoveToImmutable();
return resultBuilder.ToImmutable();
}
/*

213
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -77,17 +77,9 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -77,17 +77,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
readonly Metadata.PEFile moduleDefinition;
readonly ICompilation compilation;
readonly ITypeResolveContext context;
readonly TypeSystemOptions typeSystemOptions;
readonly MetadataAssembly mainAssembly;
Dictionary<SRM.EntityHandle, IField> fieldLookupCache = new Dictionary<SRM.EntityHandle, IField>();
Dictionary<SRM.EntityHandle, IProperty> propertyLookupCache = new Dictionary<SRM.EntityHandle, IProperty>();
Dictionary<SRM.EntityHandle, IMethod> methodLookupCache = new Dictionary<SRM.EntityHandle, IMethod>();
Dictionary<SRM.EntityHandle, IEvent> eventLookupCache = new Dictionary<SRM.EntityHandle, IEvent>();
Dictionary<IUnresolvedAssembly, Metadata.PEFile> moduleLookup = new Dictionary<IUnresolvedAssembly, Metadata.PEFile>();
public DecompilerTypeSystem(Metadata.PEFile moduleDefinition) : this(moduleDefinition, new DecompilerSettings())
{
}
@ -104,15 +96,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -104,15 +96,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
typeSystemOptions |= TypeSystemOptions.Tuple;
if (settings.ExtensionMethods)
typeSystemOptions |= TypeSystemOptions.ExtensionMethods;
MetadataLoader loader = new MetadataLoader {
IncludeInternalMembers = true,
ShortenInterfaceImplNames = false,
Options = typeSystemOptions,
};
IUnresolvedAssembly mainAssembly = loader.LoadModule(moduleDefinition);
var mainAssembly = moduleDefinition.WithOptions(typeSystemOptions);
// Load referenced assemblies and type-forwarder references.
// This is necessary to make .NET Core/PCL binaries work better.
var referencedAssemblies = new List<IUnresolvedAssembly>();
var referencedAssemblies = new List<IAssemblyReference>();
var assemblyReferenceQueue = new Queue<Metadata.AssemblyReference>(moduleDefinition.AssemblyReferences);
var processedAssemblyReferences = new HashSet<Metadata.AssemblyReference>(KeyComparer.Create((Metadata.AssemblyReference reference) => reference.FullName));
while (assemblyReferenceQueue.Count > 0) {
@ -121,9 +108,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -121,9 +108,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
continue;
var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef);
if (asm != null) {
IUnresolvedAssembly unresolvedAsm = loader.LoadModule(asm);
referencedAssemblies.Add(unresolvedAsm);
moduleLookup.Add(unresolvedAsm, asm);
referencedAssemblies.Add(asm.WithOptions(typeSystemOptions));
var metadata = asm.Metadata;
foreach (var h in metadata.ExportedTypes) {
var forwarder = metadata.GetExportedType(h);
@ -139,7 +124,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -139,7 +124,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
referencedAssemblies.Add(MinimalCorlib.Instance);
compilation = new SimpleCompilation(mainAssembly, referencedAssemblies);
}
context = new SimpleTypeResolveContext(compilation.MainAssembly);
this.mainAssembly = (MetadataAssembly)compilation.MainAssembly;
}
public ICompilation Compilation {
@ -191,31 +176,31 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -191,31 +176,31 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
}
#region Resolve Type
public IType ResolveAsType(SRM.EntityHandle typeReference)
{
return MetadataTypeReference.Resolve(
typeReference,
moduleDefinition.Metadata,
mainAssembly.TypeProvider,
new GenericContext(),
typeSystemOptions
);
return mainAssembly.ResolveType(typeReference, new GenericContext());
}
IType ResolveDeclaringType(SRM.EntityHandle declaringTypeReference)
public IMethod ResolveAsMethod(SRM.EntityHandle methodReference)
{
// resolve without substituting dynamic/tuple types
return MetadataTypeReference.Resolve(
declaringTypeReference,
moduleDefinition.Metadata,
mainAssembly.TypeProvider,
new GenericContext(context),
typeSystemOptions & ~(TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple)
);
return mainAssembly.ResolveMethod(methodReference);
}
#endregion
public IField ResolveAsField(SRM.EntityHandle fieldReference)
{
return mainAssembly.ResolveEntity(fieldReference, new GenericContext()) as IField;
}
public IProperty ResolveAsProperty(SRM.EntityHandle propertyReference)
{
return mainAssembly.ResolveEntity(propertyReference, new GenericContext()) as IProperty;
}
public IEvent ResolveAsEvent(SRM.EntityHandle eventReference)
{
return mainAssembly.ResolveEntity(eventReference, new GenericContext()) as IEvent;
}
public SRM.MethodSignature<IType> DecodeMethodSignature(SRM.StandaloneSignatureHandle handle)
{
var standaloneSignature = moduleDefinition.Metadata.GetStandaloneSignature(handle);
@ -223,7 +208,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -223,7 +208,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
throw new InvalidOperationException("Expected Method signature");
return standaloneSignature.DecodeMethodSignature(
mainAssembly.TypeProvider,
new GenericContext(context)
new GenericContext()
);
}
@ -234,158 +219,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -234,158 +219,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
throw new InvalidOperationException("Expected Local signature");
return standaloneSignature.DecodeLocalSignature(
mainAssembly.TypeProvider,
new GenericContext(context)
new GenericContext()
);
}
#region Resolve Field
public IField ResolveAsField(SRM.EntityHandle fieldReference)
{
/*if (fieldReference.IsNil)
throw new ArgumentNullException(nameof(fieldReference));
if (fieldReference.Kind != SRM.HandleKind.FieldDefinition && fieldReference.Kind != SRM.HandleKind.MemberReference)
throw new ArgumentException("HandleKind must be either FieldDefinition or MemberReference", nameof(fieldReference));
lock (fieldLookupCache) {
if (!fieldLookupCache.TryGetValue(fieldReference, out IField field)) {
var metadata = moduleDefinition.Metadata;
IType declaringType;
switch (fieldReference.Kind) {
case SRM.HandleKind.FieldDefinition:
var fieldDefHandle = (SRM.FieldDefinitionHandle)fieldReference;
field = mainAssembly.GetDefinition(fieldDefHandle);
if (field == null) {
throw new NotImplementedException();
}
break;
case SRM.HandleKind.MemberReference:
var memberRefHandle = (SRM.MemberReferenceHandle)fieldReference;
var memberRef = metadata.GetMemberReference(memberRefHandle);
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Field);
declaringType = ResolveDeclaringType(memberRef.Parent);
field = FindNonGenericField(metadata, memberRefHandle, declaringType);
break;
default:
throw new NotSupportedException();
}
if (declaringType.TypeArguments.Count > 0) {
field = (IField)field.Specialize(new TypeParameterSubstitution(declaringType.TypeArguments, null));
}
fieldLookupCache.Add(fieldReference, field);
}
return field;
}*/
throw new NotImplementedException();
}
/*
IField FindNonGenericField(SRM.MetadataReader metadata, SRM.MemberReferenceHandle memberRefHandle, IType declaringType)
{
var memberRef = metadata.GetMemberReference(memberRefHandle);
string name = metadata.GetString(memberRef.Name);
ITypeDefinition typeDef = declaringType.GetDefinition();
if (typeDef != null) {
foreach (IField field in typeDef.Fields) {
if (field.Name == name)
return field;
}
}
var returnType = memberRef.DecodeFieldSignature(mainAssembly.TypeProvider, new GenericContext(context));
return new FakeField(compilation) {
DeclaringType = declaringType,
Name = name,
ReturnType = returnType
};
}
*/
#endregion
#region Resolve Method
public IMethod ResolveAsMethod(SRM.EntityHandle methodReference)
{
return MainAssembly.ResolveMethod(methodReference);
}
#endregion
#region Resolve Property
public IProperty ResolveAsProperty(SRM.EntityHandle propertyReference)
{
if (propertyReference.IsNil)
throw new ArgumentNullException(nameof(propertyReference));
if (propertyReference.Kind != SRM.HandleKind.PropertyDefinition)
throw new ArgumentException("HandleKind must be PropertyDefinition", nameof(propertyReference));
lock (propertyLookupCache) {
IProperty property;
if (!propertyLookupCache.TryGetValue(propertyReference, out property)) {
var metadata = moduleDefinition.Metadata;
property = FindNonGenericProperty(metadata, (SRM.PropertyDefinitionHandle)propertyReference);
/*if (propertyReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)propertyReference.DeclaringType;
var typeArguments = git.GenericArguments.SelectArray(Resolve);
property = (IProperty)property.Specialize(new TypeParameterSubstitution(typeArguments, null));
}*/
propertyLookupCache.Add(propertyReference, property);
}
return property;
}
}
IProperty FindNonGenericProperty(SRM.MetadataReader metadata, SRM.PropertyDefinitionHandle handle)
{
var propertyDefinition = metadata.GetPropertyDefinition(handle);
var declaringType = metadata.GetMethodDefinition(propertyDefinition.GetAccessors().GetAny()).GetDeclaringType();
ITypeDefinition typeDef = ResolveDeclaringType(declaringType).GetDefinition();
if (typeDef == null)
return null;
foreach (IProperty property in typeDef.Properties) {
if (property.MetadataToken == handle)
return property;
}
return null;
}
#endregion
#region Resolve Event
public IEvent ResolveAsEvent(SRM.EntityHandle eventReference)
{
if (eventReference.IsNil)
throw new ArgumentNullException(nameof(eventReference));
if (eventReference.Kind != SRM.HandleKind.EventDefinition)
throw new ArgumentException("HandleKind must be EventDefinition", nameof(eventReference));
lock (eventLookupCache) {
IEvent ev;
if (!eventLookupCache.TryGetValue(eventReference, out ev)) {
var metadata = moduleDefinition.Metadata;
ev = FindNonGenericEvent(metadata, (SRM.EventDefinitionHandle)eventReference);
/*if (eventReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)eventReference.DeclaringType;
var typeArguments = git.GenericArguments.SelectArray(Resolve);
ev = (IEvent)ev.Specialize(new TypeParameterSubstitution(typeArguments, null));
}*/
eventLookupCache.Add(eventReference, ev);
}
return ev;
}
}
IEvent FindNonGenericEvent(SRM.MetadataReader metadata, SRM.EventDefinitionHandle handle)
{
var eventDefinition = metadata.GetEventDefinition(handle);
var declaringType = metadata.GetMethodDefinition(eventDefinition.GetAccessors().GetAny()).GetDeclaringType();
ITypeDefinition typeDef = ResolveDeclaringType(declaringType).GetDefinition();
if (typeDef == null)
return null;
var returnType = ResolveAsType(eventDefinition.Type);
string name = metadata.GetString(eventDefinition.Name);
foreach (IEvent ev in typeDef.Events) {
if (ev.MetadataToken == handle)
return ev;
}
return null;
}
#endregion
public IDecompilerTypeSystem GetSpecializingTypeSystem(TypeParameterSubstitution substitution)
{
if (substitution.Equals(TypeParameterSubstitution.Identity)) {

2
ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs

@ -250,7 +250,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -250,7 +250,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
private IAttribute ReadBinarySecurityAttribute(ref SRM.BlobReader reader, CustomAttributeTypedArgument<IType> securityAction)
{
string attributeTypeName = reader.ReadSerializedString();
IType attributeType = assembly.Compilation.FindType(new FullTypeName(attributeTypeName));
IType attributeType = assembly.TypeProvider.GetTypeFromSerializedName(attributeTypeName);
reader.ReadCompressedInteger(); // ??
// The specification seems to be incorrect here, so I'm using the logic from Cecil instead.

77
ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs

@ -22,6 +22,7 @@ using System.Collections.Immutable; @@ -22,6 +22,7 @@ using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
@ -78,75 +79,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -78,75 +79,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
}
internal static KeyValuePair<IMember, ResolveResult> MakeNamedArg(ICompilation compilation, IType attrType, string name, ResolveResult rr)
{
var field = attrType.GetFields(f => f.Name == name).FirstOrDefault();
if (field != null) {
return new KeyValuePair<IMember, ResolveResult>(field, rr);
}
var prop = attrType.GetProperties(f => f.Name == name).FirstOrDefault();
if (prop != null) {
return new KeyValuePair<IMember, ResolveResult>(prop, rr);
}
field = new FakeField(compilation) {
DeclaringType = attrType,
Name = name,
ReturnType = rr.Type
};
return new KeyValuePair<IMember, ResolveResult>(field, rr);
}
internal static KeyValuePair<IMember, ResolveResult> MakeNamedArg(ICompilation compilation, IType attrType, SRM.CustomAttributeNamedArgumentKind kind, string name, ResolveResult rr)
{
if (kind == CustomAttributeNamedArgumentKind.Field) {
var field = attrType.GetFields(f => f.Name == name).FirstOrDefault();
if (field != null) {
return new KeyValuePair<IMember, ResolveResult>(field, rr);
}
}
if (kind == CustomAttributeNamedArgumentKind.Property) {
var prop = attrType.GetProperties(f => f.Name == name).FirstOrDefault();
if (prop != null) {
return new KeyValuePair<IMember, ResolveResult>(prop, rr);
}
}
var fakeField = new FakeField(compilation) {
DeclaringType = attrType,
Name = name,
ReturnType = rr.Type
};
return new KeyValuePair<IMember, ResolveResult>(fakeField, rr);
}
internal static IReadOnlyList<KeyValuePair<IMember, ResolveResult>> ConvertNamedArguments(
ICompilation compilation, IType attributeType, ImmutableArray<SRM.CustomAttributeNamedArgument<IType>> namedArgs)
{
var arr = new KeyValuePair<IMember, ResolveResult>[namedArgs.Length];
for (int i = 0; i < arr.Length; i++) {
var namedArg = namedArgs[i];
arr[i] = MakeNamedArg(compilation, attributeType, namedArg.Kind, namedArg.Name,
ConvertArgument(compilation, namedArg.Type, namedArg.Value));
}
return arr;
}
private static ResolveResult ConvertArgument(ICompilation compilation, IType type, object value)
internal static IMember MemberForNamedArgument(IType attributeType, CustomAttributeNamedArgument<IType> namedArgument)
{
if (value is ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> arr) {
var arrSize = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), arr.Length);
return new ArrayCreateResolveResult(type, new[] { arrSize },
ConvertArguments(compilation, type, arr));
} else if (value is IType valueType) {
return new TypeOfResolveResult(type, valueType);
} else {
return new ConstantResolveResult(type, value);
switch (namedArgument.Kind) {
case CustomAttributeNamedArgumentKind.Field:
return attributeType.GetFields(f => f.Name == namedArgument.Name).LastOrDefault();
case CustomAttributeNamedArgumentKind.Property:
return attributeType.GetProperties(p => p.Name == namedArgument.Name).LastOrDefault();
default:
return null;
}
}
private static IReadOnlyList<ResolveResult> ConvertArguments(ICompilation compilation, IType type, ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> arr)
{
return arr.SelectArray(arg => ConvertArgument(compilation, type ?? arg.Type, arg.Value));
}
}
}

4
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs

@ -81,11 +81,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -81,11 +81,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public bool IsStatic => (attributes & FieldAttributes.Static) != 0;
// not sure if we need IsFixed anywhere...
public bool IsFixed => throw new NotImplementedException();
bool IField.IsFixed => false;
// Do we still want IsShadowing in the TS?
// We never set it for assemblies loaded from disk; only for those parsed from C#...
bool IEntity.IsShadowing => throw new NotImplementedException();
bool IEntity.IsShadowing => false;
SymbolKind ISymbol.SymbolKind => SymbolKind.Field;
IMember IMember.MemberDefinition => this;

2
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs

@ -422,7 +422,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -422,7 +422,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
=> (attributes & (MethodAttributes.Abstract | MethodAttributes.Virtual)) != 0
&& (attributes & MethodAttributes.Final) == 0;
bool IEntity.IsShadowing => throw new NotImplementedException();
bool IEntity.IsShadowing => false;
public string FullName => $"{DeclaringType?.FullName}.{Name}";
public string ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}";

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

@ -48,6 +48,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -48,6 +48,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IReadOnlyList<ITypeParameter> TypeParameters { get; }
public KnownTypeCode KnownTypeCode { get; }
public IType EnumUnderlyingType { get; }
public bool HasExtensionMethods { get; }
// lazy-loaded:
IAttribute[] customAttributes;
@ -104,6 +105,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -104,6 +105,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.Kind = TypeKind.Delegate;
} else {
this.Kind = TypeKind.Class;
this.HasExtensionMethods = this.IsStatic
&& td.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.Extension);
}
}
@ -231,8 +234,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -231,8 +234,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IType DeclaringType => DeclaringTypeDefinition;
public bool HasExtensionMethods => throw new NotImplementedException();
public bool? IsReferenceType {
get {
switch (Kind) {
@ -400,7 +401,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -400,7 +401,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public bool IsAbstract => (attributes & TypeAttributes.Abstract) != 0;
public bool IsSealed => (attributes & TypeAttributes.Sealed) != 0;
bool IEntity.IsShadowing => throw new NotImplementedException();
bool IEntity.IsShadowing => false;
public SymbolKind SymbolKind => SymbolKind.TypeDefinition;

137
ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs

@ -24,12 +24,9 @@ using System.Linq; @@ -24,12 +24,9 @@ using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem
{
@ -238,12 +235,15 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -238,12 +235,15 @@ namespace ICSharpCode.Decompiler.TypeSystem
return ResolveType(typeRefDefSpec, context, options, typeAttributes);
}
public IType ResolveType(SRM.EntityHandle typeRefDefSpec, GenericContext context, TypeSystemOptions customOptions, CustomAttributeHandleCollection? typeAttributes = null)
public IType ResolveType(EntityHandle typeRefDefSpec, GenericContext context, TypeSystemOptions customOptions, CustomAttributeHandleCollection? typeAttributes = null)
{
if (typeRefDefSpec.Kind == HandleKind.ExportedType) {
return ResolveForwardedType(metadata.GetExportedType((ExportedTypeHandle)typeRefDefSpec));
}
return MetadataTypeReference.Resolve(typeRefDefSpec, metadata, TypeProvider, context, customOptions, typeAttributes);
}
IType ResolveDeclaringType(SRM.EntityHandle declaringTypeReference, GenericContext context)
IType ResolveDeclaringType(EntityHandle declaringTypeReference, GenericContext context)
{
// resolve without substituting dynamic/tuple types
return ResolveType(declaringTypeReference, context,
@ -251,34 +251,24 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -251,34 +251,24 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
#endregion
#region ResolveMethod
#region Resolve Method
public IMethod ResolveMethod(EntityHandle methodReference, GenericContext context = default)
{
if (methodReference.IsNil)
throw new ArgumentNullException(nameof(methodReference));
switch (methodReference.Kind) {
case SRM.HandleKind.MethodDefinition:
return ResolveMethodDefinition(metadata, (SRM.MethodDefinitionHandle)methodReference, expandVarArgs: true);
case SRM.HandleKind.MemberReference:
return ResolveMethodReference(metadata, (SRM.MemberReferenceHandle)methodReference, context);
case SRM.HandleKind.MethodSpecification:
var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference);
var methodTypeArgs = methodSpec.DecodeSignature(TypeProvider, context);
IMethod method;
if (methodSpec.Method.Kind == SRM.HandleKind.MethodDefinition) {
// generic instance of a methoddef (=generic method in non-generic class in current assembly)
method = ResolveMethodDefinition(metadata, (SRM.MethodDefinitionHandle)methodSpec.Method, expandVarArgs: true);
method = method.Specialize(new TypeParameterSubstitution(context.ClassTypeParameters, methodTypeArgs));
} else {
method = ResolveMethodReference(metadata, (SRM.MemberReferenceHandle)methodSpec.Method, context, methodTypeArgs);
}
return method;
case HandleKind.MethodDefinition:
return ResolveMethodDefinition((MethodDefinitionHandle)methodReference, expandVarArgs: true);
case HandleKind.MemberReference:
return ResolveMethodReference((MemberReferenceHandle)methodReference, context, expandVarArgs: true);
case HandleKind.MethodSpecification:
return ResolveMethodSpecification((MethodSpecificationHandle)methodReference, context, expandVarArgs: true);
default:
throw new ArgumentException("HandleKind must be either a MethodDefinition, MemberReference or MethodSpecification", nameof(methodReference));
}
}
IMethod ResolveMethodDefinition(SRM.MetadataReader metadata, SRM.MethodDefinitionHandle methodDefHandle, bool expandVarArgs)
IMethod ResolveMethodDefinition(MethodDefinitionHandle methodDefHandle, bool expandVarArgs)
{
var method = GetDefinition(methodDefHandle);
if (method == null) {
@ -290,6 +280,21 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -290,6 +280,21 @@ namespace ICSharpCode.Decompiler.TypeSystem
return method;
}
IMethod ResolveMethodSpecification(MethodSpecificationHandle methodSpecHandle, GenericContext context, bool expandVarArgs)
{
var methodSpec = metadata.GetMethodSpecification(methodSpecHandle);
var methodTypeArgs = methodSpec.DecodeSignature(TypeProvider, context);
IMethod method;
if (methodSpec.Method.Kind == HandleKind.MethodDefinition) {
// generic instance of a methoddef (=generic method in non-generic class in current assembly)
method = ResolveMethodDefinition((MethodDefinitionHandle)methodSpec.Method, expandVarArgs);
method = method.Specialize(new TypeParameterSubstitution(context.ClassTypeParameters, methodTypeArgs));
} else {
method = ResolveMethodReference((MemberReferenceHandle)methodSpec.Method, context, methodTypeArgs, expandVarArgs);
}
return method;
}
/// <summary>
/// Resolves a method reference.
/// </summary>
@ -297,15 +302,15 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -297,15 +302,15 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Class type arguments are provided by the declaring type stored in the memberRef.
/// Method type arguments are provided by the caller.
/// </remarks>
IMethod ResolveMethodReference(SRM.MetadataReader metadata, SRM.MemberReferenceHandle memberRefHandle, GenericContext context, IReadOnlyList<IType> methodTypeArguments = null)
IMethod ResolveMethodReference(MemberReferenceHandle memberRefHandle, GenericContext context, IReadOnlyList<IType> methodTypeArguments = null, bool expandVarArgs = true)
{
var memberRef = metadata.GetMemberReference(memberRefHandle);
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Method);
SRM.MethodSignature<IType> signature;
Debug.Assert(memberRef.GetKind() == MemberReferenceKind.Method);
MethodSignature<IType> signature;
IReadOnlyList<IType> classTypeArguments = null;
IMethod method;
if (memberRef.Parent.Kind == SRM.HandleKind.MethodDefinition) {
method = ResolveMethodDefinition(metadata, (SRM.MethodDefinitionHandle)memberRef.Parent, expandVarArgs: false);
if (memberRef.Parent.Kind == HandleKind.MethodDefinition) {
method = ResolveMethodDefinition((MethodDefinitionHandle)memberRef.Parent, expandVarArgs: false);
signature = memberRef.DecodeMethodSignature(TypeProvider, context);
} else {
var declaringType = ResolveDeclaringType(memberRef.Parent, context);
@ -331,7 +336,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -331,7 +336,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
// Determine the expected parameters from the signature:
ImmutableArray<IType> parameterTypes;
if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
parameterTypes = signature.ParameterTypes
.Take(signature.RequiredParameterCount)
.Concat(new[] { SpecialType.ArgList })
@ -359,7 +364,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -359,7 +364,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (classTypeArguments != null || methodTypeArguments != null) {
method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments));
}
if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
if (expandVarArgs && signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
method = new VarArgInstanceMethod(method, signature.ParameterTypes.Skip(signature.RequiredParameterCount));
}
return method;
@ -391,7 +396,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -391,7 +396,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary>
/// Create a dummy IMethod from the specified MethodReference
/// </summary>
IMethod CreateFakeMethod(IType declaringType, string name, SRM.MethodSignature<IType> signature)
IMethod CreateFakeMethod(IType declaringType, string name, MethodSignature<IType> signature)
{
SymbolKind symbolKind = SymbolKind.Method;
if (name == ".ctor" || name == ".cctor")
@ -425,6 +430,76 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -425,6 +430,76 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
#endregion
#region Resolve Entity
/// <summary>
/// Resolves a symbol.
/// </summary>
/// <remarks>
/// * Types are resolved to their definition, as IType does not implement ISymbol.
/// * types without definition will resolve to <c>null</c>
/// * use ResolveType() properly resolve types
/// * When resolving methods, varargs signatures are not expanded.
/// * use ResolveMethod() instead to get an IMethod instance suitable for call-sites
/// * May return specialized members, where generics are involved.
/// * Other types of handles that don't correspond to TS entities, will return <c>null</c>.
/// </remarks>
public IEntity ResolveEntity(EntityHandle entityHandle, GenericContext context)
{
switch (entityHandle.Kind) {
case HandleKind.TypeReference:
case HandleKind.TypeDefinition:
case HandleKind.TypeSpecification:
case HandleKind.ExportedType:
return ResolveType(entityHandle, context).GetDefinition();
case HandleKind.MemberReference:
var memberReferenceHandle = (MemberReferenceHandle)entityHandle;
switch (metadata.GetMemberReference(memberReferenceHandle).GetKind()) {
case MemberReferenceKind.Method:
// for consistency with the MethodDefinition case, never expand varargs
return ResolveMethodReference(memberReferenceHandle, context, expandVarArgs: false);
case MemberReferenceKind.Field:
return ResolveFieldReference(memberReferenceHandle, context);
default:
throw new BadImageFormatException("Unknown MemberReferenceKind");
}
case HandleKind.MethodDefinition:
return GetDefinition((MethodDefinitionHandle)entityHandle);
case HandleKind.MethodSpecification:
return ResolveMethodSpecification((MethodSpecificationHandle)entityHandle, context, expandVarArgs: false);
case HandleKind.FieldDefinition:
return GetDefinition((FieldDefinitionHandle)entityHandle);
case HandleKind.EventDefinition:
return GetDefinition((EventDefinitionHandle)entityHandle);
case HandleKind.PropertyDefinition:
return GetDefinition((PropertyDefinitionHandle)entityHandle);
default:
return null;
}
}
IField ResolveFieldReference(MemberReferenceHandle memberReferenceHandle, GenericContext context)
{
var memberRef = metadata.GetMemberReference(memberReferenceHandle);
var declaringType = ResolveDeclaringType(memberRef.Parent, context);
var declaringTypeDefinition = declaringType.GetDefinition();
string name = metadata.GetString(memberRef.Name);
// field signature is for the definition, not the generic instance
var signature = memberRef.DecodeFieldSignature(TypeProvider,
new GenericContext(declaringTypeDefinition?.TypeParameters));
// 'f' in the predicate is also the definition, even if declaringType is a ParameterizedType
var field = declaringType.GetFields(f => f.Name == name && CompareTypes(f.ReturnType, signature),
GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
if (field == null) {
field = new FakeField(Compilation) {
ReturnType = signature,
Name = name,
DeclaringType = declaringType,
};
}
return field;
}
#endregion
#region Module / Assembly attributes
IAttribute[] assemblyAttributes;
IAttribute[] moduleAttributes;

3
ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs

@ -144,6 +144,9 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -144,6 +144,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
public IType GetTypeFromSerializedName(string name)
{
if (name == null) {
return null;
}
return ReflectionHelper.ParseReflectionName(name)
.Resolve(assembly != null ? new SimpleTypeResolveContext(assembly) : new SimpleTypeResolveContext(compilation));
}

19
ICSharpCode.Decompiler/Util/CollectionExtensions.cs

@ -17,6 +17,25 @@ namespace ICSharpCode.Decompiler.Util @@ -17,6 +17,25 @@ namespace ICSharpCode.Decompiler.Util
return input1.Zip(input2, (a, b) => (a, b));
}
public static IEnumerable<(A, B)> ZipLongest<A, B>(this IEnumerable<A> input1, IEnumerable<B> input2)
{
using (var it1 = input1.GetEnumerator()) {
using (var it2 = input2.GetEnumerator()) {
bool hasElements1 = true;
bool hasElements2 = true;
while (true) {
if (hasElements1)
hasElements1 = it1.MoveNext();
if (hasElements2)
hasElements2 = it2.MoveNext();
if (!(hasElements1 || hasElements2))
break;
yield return ((hasElements1 ? it1.Current : default), (hasElements2 ? it2.Current : default));
}
}
}
}
public static IEnumerable<T> Slice<T>(this IReadOnlyList<T> input, int offset, int length)
{
for (int i = offset; i < offset + length; i++) {

Loading…
Cancel
Save