diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
index 2af568fbe..0119f4ba8 100644
--- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
+++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
@@ -1359,6 +1359,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
var f = type.GetFields().Single(x => x.Name == name);
Assert.IsTrue(f.IsConst);
Assert.AreEqual(expected, f.ConstantValue);
+ Assert.AreEqual(0, f.Attributes.Count);
}
[Test]
@@ -1613,6 +1614,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{
ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition();
Assert.IsNotNull(c, "System.Void not found");
+ Assert.AreEqual(TypeKind.Void, c.Kind);
Assert.AreEqual(0, c.GetMethods().Count());
Assert.AreEqual(0, c.GetProperties().Count());
Assert.AreEqual(0, c.GetEvents().Count());
diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
index 7bad20aca..f323f9a29 100644
--- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
+++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
@@ -293,7 +293,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
WriteSecurityDeclarations(module, methodDefinition.GetDeclarativeSecurityAttributes());
- if (handle.HasBody(metadata)) {
+ if (methodDefinition.HasBody()) {
methodBodyDisassembler.Disassemble(module, handle);
}
var declaringType = metadata.GetTypeDefinition(methodDefinition.GetDeclaringType());
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index b4afb1b72..779af3792 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -345,7 +345,9 @@
+
+
diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
index be97cf60f..975769c3c 100644
--- a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
+++ b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
@@ -366,10 +366,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
{
var typeSystem = context.TypeSystem;
var metadata = typeSystem.GetMetadata();
- if (method.IsNil || !method.HasBody(metadata))
+ if (method.IsNil)
throw new SymbolicAnalysisFailedException();
var methodDef = metadata.GetMethodDefinition(method);
+ if (!methodDef.HasBody())
+ throw new SymbolicAnalysisFailedException();
var sdtp = typeSystem as SpecializingDecompilerTypeSystem;
if (sdtp != null) {
diff --git a/ICSharpCode.Decompiler/SRMExtensions.cs b/ICSharpCode.Decompiler/SRMExtensions.cs
index ca301aeff..1eb2df690 100644
--- a/ICSharpCode.Decompiler/SRMExtensions.cs
+++ b/ICSharpCode.Decompiler/SRMExtensions.cs
@@ -92,13 +92,7 @@ namespace ICSharpCode.Decompiler
}
return false;
}
-
- public static bool HasBody(this MethodDefinitionHandle handle, MetadataReader reader)
- {
- var methodDefinition = reader.GetMethodDefinition(handle);
- return methodDefinition.HasBody();
- }
-
+
public static bool HasBody(this MethodDefinition methodDefinition)
{
const MethodAttributes noBodyAttrs = MethodAttributes.Abstract | MethodAttributes.PinvokeImpl;
diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
index 7e3984ed3..146b5101c 100644
--- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
@@ -237,7 +237,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region Resolve Field
public IField ResolveAsField(SRM.EntityHandle fieldReference)
{
- if (fieldReference.IsNil)
+ /*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));
@@ -248,21 +248,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
switch (fieldReference.Kind) {
case SRM.HandleKind.FieldDefinition:
var fieldDefHandle = (SRM.FieldDefinitionHandle)fieldReference;
- var fieldDef = metadata.GetFieldDefinition(fieldDefHandle);
- declaringType = ResolveDeclaringType(fieldDef.GetDeclaringType());
- var declaringTypeDefinition = declaringType.GetDefinition();
- if (declaringTypeDefinition != null) {
- field = declaringTypeDefinition.GetFields(f => f.MetadataToken == fieldReference, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
- } else {
- field = null;
- }
+ field = mainAssembly.GetDefinition(fieldDefHandle);
if (field == null) {
- field = new FakeField(compilation) {
- DeclaringType = declaringType,
- Name = metadata.GetString(fieldDef.Name),
- ReturnType = FieldTypeReference.Resolve(fieldDefHandle, metadata, context, typeSystemOptions),
- IsStatic = (fieldDef.Attributes & System.Reflection.FieldAttributes.Static) != 0,
- };
+ throw new NotImplementedException();
}
break;
case SRM.HandleKind.MemberReference:
@@ -281,9 +269,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
fieldLookupCache.Add(fieldReference, field);
}
return field;
- }
+ }*/
+ throw new NotImplementedException();
}
+ /*
IField FindNonGenericField(SRM.MetadataReader metadata, SRM.MemberReferenceHandle memberRefHandle, IType declaringType)
{
var memberRef = metadata.GetMemberReference(memberRefHandle);
@@ -303,196 +293,15 @@ namespace ICSharpCode.Decompiler.TypeSystem
ReturnType = returnType
};
}
+ */
#endregion
#region Resolve Method
public IMethod ResolveAsMethod(SRM.EntityHandle methodReference)
{
- if (methodReference.IsNil)
- throw new ArgumentNullException(nameof(methodReference));
- if (methodReference.Kind != SRM.HandleKind.MethodDefinition && methodReference.Kind != SRM.HandleKind.MemberReference && methodReference.Kind != SRM.HandleKind.MethodSpecification)
- throw new ArgumentException("HandleKind must be either a MethodDefinition, MemberReference or MethodSpecification", nameof(methodReference));
- lock (methodLookupCache) {
- if (!methodLookupCache.TryGetValue(methodReference, out IMethod method)) {
- var metadata = moduleDefinition.Metadata;
- switch (methodReference.Kind) {
- case SRM.HandleKind.MethodDefinition:
- method = ResolveMethodDefinition(metadata, (SRM.MethodDefinitionHandle)methodReference);
- break;
- case SRM.HandleKind.MemberReference:
- method = ResolveMethodReference(metadata, (SRM.MemberReferenceHandle)methodReference);
- break;
- case SRM.HandleKind.MethodSpecification:
- var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference);
- var methodTypeArgs = methodSpec.DecodeSignature(mainAssembly.TypeProvider, new GenericContext(context));
- 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);
- method = method.Specialize(new TypeParameterSubstitution(null, methodTypeArgs));
- } else {
- method = ResolveMethodReference(metadata, (SRM.MemberReferenceHandle)methodSpec.Method, methodTypeArgs);
- }
- break;
- default:
- throw new NotSupportedException();
- }
- methodLookupCache.Add(methodReference, method);
- }
- return method;
- }
- }
-
- IMethod ResolveMethodDefinition(SRM.MetadataReader metadata, SRM.MethodDefinitionHandle methodDefHandle, bool expandVarArgs = true)
- {
- var method = mainAssembly.GetDefinition(methodDefHandle);
- if (method == null) {
- throw new NotImplementedException();
- }
- if (expandVarArgs && method.Parameters.LastOrDefault()?.Type.Kind == TypeKind.ArgList) {
- method = new VarArgInstanceMethod(method, EmptyList.Instance);
- }
- return method;
+ return MainAssembly.ResolveMethod(methodReference);
}
- ///
- /// Resolves a method reference.
- ///
- ///
- /// Class type arguments are provided by the declaring type stored in the memberRef.
- /// Method type arguments are provided by the caller.
- ///
- IMethod ResolveMethodReference(SRM.MetadataReader metadata, SRM.MemberReferenceHandle memberRefHandle, IReadOnlyList methodTypeArguments = null)
- {
- var memberRef = metadata.GetMemberReference(memberRefHandle);
- Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Method);
- SRM.MethodSignature signature;
- IReadOnlyList classTypeArguments = null;
- IMethod method;
- if (memberRef.Parent.Kind == SRM.HandleKind.MethodDefinition) {
- method = ResolveMethodDefinition(metadata, (SRM.MethodDefinitionHandle)memberRef.Parent, expandVarArgs: false);
- signature = memberRef.DecodeMethodSignature(mainAssembly.TypeProvider, new GenericContext(context));
- } else {
- var declaringType = ResolveDeclaringType(memberRef.Parent);
- var declaringTypeDefinition = declaringType.GetDefinition();
- if (declaringType.TypeArguments.Count > 0) {
- classTypeArguments = declaringType.TypeArguments;
- }
- // Note: declaringType might be parameterized, but the signature is for the original method definition.
- // We'll have to search the member directly on declaringTypeDefinition.
- string name = metadata.GetString(memberRef.Name);
- signature = memberRef.DecodeMethodSignature(mainAssembly.TypeProvider,
- new GenericContext(declaringTypeDefinition?.TypeParameters));
- if (declaringTypeDefinition != null) {
- // Find the set of overloads to search:
- IEnumerable methods;
- if (name == ".ctor") {
- methods = declaringTypeDefinition.GetConstructors();
- } else if (name == ".cctor") {
- methods = declaringTypeDefinition.Methods.Where(m => m.IsConstructor && m.IsStatic);
- } else {
- methods = declaringTypeDefinition.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers)
- .Concat(declaringTypeDefinition.GetAccessors(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers));
- }
- // Determine the expected parameters from the signature:
- ImmutableArray parameterTypes;
- if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
- parameterTypes = signature.ParameterTypes
- .Take(signature.RequiredParameterCount)
- .Concat(new[] { SpecialType.ArgList })
- .ToImmutableArray();
- } else {
- parameterTypes = signature.ParameterTypes;
- }
- // Search for the matching method:
- method = null;
- foreach (var m in methods) {
- if (m.TypeParameters.Count != signature.GenericParameterCount)
- continue;
- if (CompareSignatures(m.Parameters, parameterTypes) && CompareTypes(m.ReturnType, signature.ReturnType)) {
- method = m;
- break;
- }
- }
- } else {
- method = null;
- }
- if (method == null) {
- method = CreateFakeMethod(declaringType, name, signature);
- }
- }
- if (classTypeArguments != null || methodTypeArguments != null) {
- method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments));
- }
- if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
- method = new VarArgInstanceMethod(method, signature.ParameterTypes.Skip(signature.RequiredParameterCount));
- }
- return method;
- }
-
- static readonly NormalizeTypeVisitor normalizeTypeVisitor = new NormalizeTypeVisitor {
- ReplaceClassTypeParametersWithDummy = true,
- ReplaceMethodTypeParametersWithDummy = true,
- };
-
- static bool CompareTypes(IType a, IType b)
- {
- IType type1 = a.AcceptVisitor(normalizeTypeVisitor);
- IType type2 = b.AcceptVisitor(normalizeTypeVisitor);
- return type1.Equals(type2);
- }
-
- static bool IsVarArgMethod(IMethod method)
- {
- return method.Parameters.Count > 0 && method.Parameters[method.Parameters.Count - 1].Type.Kind == TypeKind.ArgList;
- }
-
- static bool CompareSignatures(IReadOnlyList parameters, ImmutableArray parameterTypes)
- {
- if (parameterTypes.Length != parameters.Count)
- return false;
- for (int i = 0; i < parameterTypes.Length; i++) {
- if (!CompareTypes(parameterTypes[i], parameters[i].Type))
- return false;
- }
- return true;
- }
-
- ///
- /// Create a dummy IMethod from the specified MethodReference
- ///
- IMethod CreateFakeMethod(IType declaringType, string name, SRM.MethodSignature signature)
- {
- SymbolKind symbolKind = SymbolKind.Method;
- if (name == ".ctor" || name == ".cctor")
- symbolKind = SymbolKind.Constructor;
- var m = new FakeMethod(compilation, symbolKind);
- m.DeclaringType = declaringType;
- m.Name = name;
- m.ReturnType = signature.ReturnType;
- m.IsStatic = !signature.Header.IsInstance;
-
- var metadata = moduleDefinition.Metadata;
- TypeParameterSubstitution substitution = null;
- if (signature.GenericParameterCount > 0) {
- var typeParameters = new List();
- for (int i = 0; i < signature.GenericParameterCount; i++) {
- typeParameters.Add(new DefaultTypeParameter(m, i));
- }
- m.TypeParameters = typeParameters;
- substitution = new TypeParameterSubstitution(null, typeParameters);
- }
- var parameters = new List();
- for (int i = 0; i < signature.RequiredParameterCount; i++) {
- var type = signature.ParameterTypes[i];
- if (substitution != null) {
- // replace the dummy method type parameters with the owned instances we just created
- type = type.AcceptVisitor(substitution);
- }
- parameters.Add(new DefaultParameter(type, ""));
- }
- m.Parameters = parameters;
- return m;
- }
#endregion
#region Resolve Property
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
index 0319742f8..4d51afb13 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
@@ -89,6 +89,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return Implementation.CustomAttribute.MakeNamedArg(assembly.Compilation, attrType, name, rr);
}
+ internal KeyValuePair MakeNamedArg(IType attrType, string name, bool value)
+ {
+ return MakeNamedArg(attrType, name, assembly.Compilation.FindType(KnownTypeCode.Boolean), value);
+ }
+
#region MarshalAsAttribute (ConvertMarshalInfo)
internal void AddMarshalInfo(BlobHandle marshalInfo)
{
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
index 8f7215fa7..edd5f75ba 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
@@ -38,6 +38,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
NonSerialized,
// Method attributes:
+ DllImport,
+ PreserveSig,
+ MethodImpl,
// Parameter attributes:
ParamArray,
@@ -70,6 +73,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
// Field attributes:
new TopLevelTypeName("System.Runtime.InteropServices", nameof(FieldOffsetAttribute)),
new TopLevelTypeName("System", nameof(NonSerializedAttribute)),
+ // Method attributes:
+ new TopLevelTypeName("System.Runtime.InteropServices", nameof(DllImportAttribute)),
+ new TopLevelTypeName("System.Runtime.InteropServices", nameof(PreserveSigAttribute)),
+ new TopLevelTypeName("System.Runtime.CompilerServices", nameof(MethodImplAttribute)),
// Parameter attributes:
new TopLevelTypeName("System", nameof(ParamArrayAttribute)),
// Marshalling attributes:
@@ -88,5 +95,5 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
return compilation.FindType(attrType.GetTypeName());
}
-
+ }
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
index c9e09f532..5a9e9d940 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
@@ -22,9 +22,7 @@ using System.Diagnostics;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using System.Runtime.InteropServices;
using System.Threading;
-using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
@@ -32,7 +30,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
///
/// Field definition backed by System.Reflection.Metadata
///
- class MetadataField : IField
+ sealed class MetadataField : IField
{
readonly MetadataAssembly assembly;
readonly FieldDefinitionHandle handle;
@@ -149,7 +147,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public string FullName => $"{DeclaringType?.FullName}.{Name}";
public string ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}";
- public string Namespace => DeclaringType?.Namespace;
+ public string Namespace => DeclaringType?.Namespace ?? string.Empty;
public bool IsVolatile {
get {
@@ -179,6 +177,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
Volatile.Write(ref this.isVolatile, true);
ty = mod.ElementType;
}
+ ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, Compilation,
+ fieldDef.GetCustomAttributes(), metadata, assembly.TypeSystemOptions);
return LazyInit.GetOrSet(ref this.type, ty);
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
new file mode 100644
index 000000000..50ca1fed4
--- /dev/null
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
@@ -0,0 +1,416 @@
+// 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.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.Decompiler.Semantics;
+using ICSharpCode.Decompiler.Util;
+
+namespace ICSharpCode.Decompiler.TypeSystem.Implementation
+{
+ sealed class MetadataMethod : IMethod
+ {
+ readonly MetadataAssembly assembly;
+ readonly MethodDefinitionHandle handle;
+
+ // eagerly loaded fields:
+ readonly MethodAttributes attributes;
+ readonly SymbolKind symbolKind;
+ readonly ITypeParameter[] typeParameters;
+ public bool IsExtensionMethod { get; }
+
+ // lazy-loaded fields:
+ ITypeDefinition declaringType;
+ string name;
+ IAttribute[] customAttributes;
+ IAttribute[] returnTypeAttributes;
+ IParameter[] parameters;
+ IType returnType;
+
+ internal MetadataMethod(MetadataAssembly assembly, MethodDefinitionHandle handle)
+ {
+ Debug.Assert(assembly != null);
+ Debug.Assert(!handle.IsNil);
+ this.assembly = assembly;
+ this.handle = handle;
+ var metadata = assembly.metadata;
+ var def = metadata.GetMethodDefinition(handle);
+ this.attributes = def.Attributes;
+
+ this.symbolKind = SymbolKind.Method;
+ if ((attributes & (MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)) != 0) {
+ string name = this.Name;
+ if (name == ".cctor" || name == ".ctor")
+ this.symbolKind = SymbolKind.Constructor;
+ else if (name.StartsWith("op_", StringComparison.Ordinal))
+ this.symbolKind = SymbolKind.Operator;
+ }
+ this.typeParameters = MetadataTypeParameter.Create(assembly, this, def.GetGenericParameters());
+ this.IsExtensionMethod = (attributes & MethodAttributes.Static) == MethodAttributes.Static
+ && (assembly.TypeSystemOptions & TypeSystemOptions.ExtensionMethods) == TypeSystemOptions.ExtensionMethods
+ && def.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.Extension);
+ }
+
+ public EntityHandle MetadataToken => handle;
+
+ public override string ToString()
+ {
+ return $"{MetadataTokens.GetToken(handle):X8} {DeclaringType?.ReflectionName}.{Name}";
+ }
+
+ public string Name {
+ get {
+ string name = LazyInit.VolatileRead(ref this.name);
+ if (name != null)
+ return name;
+ var metadata = assembly.metadata;
+ var methodDef = metadata.GetMethodDefinition(handle);
+ return LazyInit.GetOrSet(ref this.name, metadata.GetString(methodDef.Name));
+ }
+ }
+
+ public IReadOnlyList TypeParameters => typeParameters;
+ IReadOnlyList IMethod.TypeArguments => typeParameters;
+
+ public SymbolKind SymbolKind => symbolKind;
+ public bool IsConstructor => symbolKind == SymbolKind.Constructor;
+ public bool IsDestructor => symbolKind == SymbolKind.Destructor;
+ public bool IsOperator => symbolKind == SymbolKind.Operator;
+ public bool IsAccessor => symbolKind == SymbolKind.Accessor;
+
+ public bool HasBody => assembly.metadata.GetMethodDefinition(handle).HasBody();
+
+
+ public IMember AccessorOwner => throw new NotImplementedException();
+
+ #region Signature (ReturnType + Parameters)
+ public IReadOnlyList Parameters {
+ get {
+ var parameters = LazyInit.VolatileRead(ref this.parameters);
+ if (parameters != null)
+ return parameters;
+ DecodeSignature();
+ return this.parameters;
+ }
+ }
+
+ public IType ReturnType {
+ get {
+ var returnType = LazyInit.VolatileRead(ref this.returnType);
+ if (returnType != null)
+ return returnType;
+ DecodeSignature();
+ return this.returnType;
+ }
+ }
+
+ private void DecodeSignature()
+ {
+ var metadata = assembly.metadata;
+ var methodDef = metadata.GetMethodDefinition(handle);
+ var genericContext = new GenericContext(DeclaringType.TypeParameters, this.TypeParameters);
+ var signature = methodDef.DecodeSignature(assembly.TypeProvider, genericContext);
+ int i = 0;
+ CustomAttributeHandleCollection? returnTypeAttributes = null;
+ IParameter[] parameters = new IParameter[signature.RequiredParameterCount
+ + (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs ? 1 : 0)];
+ foreach (var parameterHandle in methodDef.GetParameters()) {
+ var par = metadata.GetParameter(parameterHandle);
+ if (par.SequenceNumber == 0) {
+ // "parameter" holds return type attributes
+ returnTypeAttributes = par.GetCustomAttributes();
+ } else if (par.SequenceNumber > 0 && i < signature.RequiredParameterCount) {
+ Debug.Assert(par.SequenceNumber - 1 == i);
+ var parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType(
+ signature.ParameterTypes[i], Compilation,
+ par.GetCustomAttributes(), metadata, assembly.TypeSystemOptions);
+ parameters[i] = new MetadataParameter(assembly, this, parameterType, parameterHandle);
+ i++;
+ }
+ }
+ while (i < signature.RequiredParameterCount) {
+ var parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType(
+ signature.ParameterTypes[i], Compilation, null, metadata, assembly.TypeSystemOptions);
+ parameters[i] = new DefaultParameter(parameterType, name: string.Empty, owner: this,
+ isRef: parameterType.Kind == TypeKind.ByReference);
+ i++;
+ }
+ if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
+ parameters[i] = new DefaultParameter(SpecialType.ArgList, name: string.Empty, owner: this);
+ i++;
+ }
+ Debug.Assert(i == parameters.Length);
+ var returnType = ApplyAttributeTypeVisitor.ApplyAttributesToType(signature.ReturnType,
+ Compilation, returnTypeAttributes, metadata, assembly.TypeSystemOptions);
+ LazyInit.GetOrSet(ref this.returnType, returnType);
+ LazyInit.GetOrSet(ref this.parameters, parameters);
+ }
+ #endregion
+
+ public IReadOnlyList ImplementedInterfaceMembers => throw new NotImplementedException();
+
+ public bool IsExplicitInterfaceImplementation => throw new NotImplementedException();
+
+ IMember IMember.MemberDefinition => this;
+ IMethod IMethod.ReducedFrom => this;
+ TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity;
+
+ public ITypeDefinition DeclaringTypeDefinition {
+ get {
+ var declType = LazyInit.VolatileRead(ref this.declaringType);
+ if (declType != null) {
+ return declType;
+ } else {
+ var def = assembly.metadata.GetMethodDefinition(handle);
+ return LazyInit.GetOrSet(ref this.declaringType,
+ assembly.GetDefinition(def.GetDeclaringType()));
+ }
+ }
+ }
+
+ public IType DeclaringType => DeclaringTypeDefinition;
+
+ public IAssembly ParentAssembly => assembly;
+ public ICompilation Compilation => assembly.Compilation;
+
+ #region Attributes
+ public IReadOnlyList Attributes {
+ get {
+ var attr = LazyInit.VolatileRead(ref this.customAttributes);
+ if (attr != null)
+ return attr;
+ return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes());
+ }
+ }
+
+ IType FindInteropType(string name)
+ {
+ return assembly.Compilation.FindType(new TopLevelTypeName(
+ "System.Runtime.InteropServices", name, 0
+ ));
+ }
+
+ IAttribute[] DecodeAttributes()
+ {
+ var b = new AttributeListBuilder(assembly);
+
+ var metadata = assembly.metadata;
+ var def = metadata.GetMethodDefinition(handle);
+ MethodImplAttributes implAttributes = def.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
+
+ #region DllImportAttribute
+ var info = def.GetImport();
+ if ((attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl && !info.Module.IsNil) {
+ var dllImportType = assembly.GetAttributeType(KnownAttribute.DllImport);
+ var positionalArguments = new ResolveResult[] {
+ new ConstantResolveResult(assembly.Compilation.FindType(KnownTypeCode.String),
+ metadata.GetString(metadata.GetModuleReference(info.Module).Name))
+ };
+ var namedArgs = new List>();
+
+ var importAttrs = info.Attributes;
+ if ((importAttrs & MethodImportAttributes.BestFitMappingDisable) == MethodImportAttributes.BestFitMappingDisable)
+ namedArgs.Add(b.MakeNamedArg(dllImportType, "BestFitMapping", false));
+ if ((importAttrs & MethodImportAttributes.BestFitMappingEnable) == MethodImportAttributes.BestFitMappingEnable)
+ namedArgs.Add(b.MakeNamedArg(dllImportType, "BestFitMapping", true));
+
+ CallingConvention callingConvention;
+ switch (info.Attributes & MethodImportAttributes.CallingConventionMask) {
+ case 0:
+ Debug.WriteLine($"P/Invoke calling convention not set on: {this}");
+ callingConvention = 0;
+ break;
+ case MethodImportAttributes.CallingConventionCDecl:
+ callingConvention = CallingConvention.Cdecl;
+ break;
+ case MethodImportAttributes.CallingConventionFastCall:
+ callingConvention = CallingConvention.FastCall;
+ break;
+ case MethodImportAttributes.CallingConventionStdCall:
+ callingConvention = CallingConvention.StdCall;
+ break;
+ case MethodImportAttributes.CallingConventionThisCall:
+ callingConvention = CallingConvention.ThisCall;
+ break;
+ case MethodImportAttributes.CallingConventionWinApi:
+ callingConvention = CallingConvention.Winapi;
+ break;
+ default:
+ throw new NotSupportedException("unknown calling convention");
+ }
+ if (callingConvention != CallingConvention.Winapi) {
+ var callingConventionType = FindInteropType(nameof(CallingConvention));
+ namedArgs.Add(b.MakeNamedArg(dllImportType, "CallingConvention", callingConventionType, (int)callingConvention));
+ }
+
+ CharSet charSet = CharSet.None;
+ switch (info.Attributes & MethodImportAttributes.CharSetMask) {
+ case MethodImportAttributes.CharSetAnsi:
+ charSet = CharSet.Ansi;
+ break;
+ case MethodImportAttributes.CharSetAuto:
+ charSet = CharSet.Auto;
+ break;
+ case MethodImportAttributes.CharSetUnicode:
+ charSet = CharSet.Unicode;
+ break;
+ }
+ if (charSet != CharSet.None) {
+ var charSetType = FindInteropType(nameof(CharSet));
+ namedArgs.Add(b.MakeNamedArg(dllImportType, "CharSet", charSetType, (int)charSet));
+ }
+
+ if (!info.Name.IsNil && info.Name != def.Name) {
+ namedArgs.Add(b.MakeNamedArg(dllImportType,
+ "EntryPoint", KnownTypeCode.String, metadata.GetString(info.Name)));
+ }
+
+ if ((info.Attributes & MethodImportAttributes.ExactSpelling) == MethodImportAttributes.ExactSpelling) {
+ namedArgs.Add(b.MakeNamedArg(dllImportType, "ExactSpelling", true));
+ }
+
+ if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig) {
+ implAttributes &= ~MethodImplAttributes.PreserveSig;
+ } else {
+ namedArgs.Add(b.MakeNamedArg(dllImportType, "PreserveSig", true));
+ }
+
+ if ((info.Attributes & MethodImportAttributes.SetLastError) == MethodImportAttributes.SetLastError)
+ namedArgs.Add(b.MakeNamedArg(dllImportType, "SetLastError", true));
+
+ if ((info.Attributes & MethodImportAttributes.ThrowOnUnmappableCharDisable) == MethodImportAttributes.ThrowOnUnmappableCharDisable)
+ namedArgs.Add(b.MakeNamedArg(dllImportType, "ThrowOnUnmappableChar", false));
+ if ((info.Attributes & MethodImportAttributes.ThrowOnUnmappableCharEnable) == MethodImportAttributes.ThrowOnUnmappableCharEnable)
+ namedArgs.Add(b.MakeNamedArg(dllImportType, "ThrowOnUnmappableChar", true));
+
+ b.Add(new DefaultAttribute(dllImportType, positionalArguments, namedArgs));
+ }
+ #endregion
+
+ #region PreserveSigAttribute
+ if (implAttributes == MethodImplAttributes.PreserveSig) {
+ b.Add(KnownAttribute.PreserveSig);
+ implAttributes = 0;
+ }
+ #endregion
+
+ #region MethodImplAttribute
+ if (implAttributes != 0) {
+ b.Add(KnownAttribute.MethodImpl, new ConstantResolveResult(
+ Compilation.FindType(new TopLevelTypeName("System.Runtime.CompilerServices", nameof(MethodImplOptions))),
+ (int)implAttributes
+ ));
+ }
+ #endregion
+
+ b.Add(def.GetCustomAttributes());
+ b.AddSecurityAttributes(def.GetDeclarativeSecurityAttributes());
+
+ return b.Build();
+ }
+ #endregion
+
+ #region Return type attributes
+ public IReadOnlyList ReturnTypeAttributes {
+ get {
+ var attr = LazyInit.VolatileRead(ref this.returnTypeAttributes);
+ if (attr != null)
+ return attr;
+ return LazyInit.GetOrSet(ref this.returnTypeAttributes, DecodeReturnTypeAttributes());
+ }
+ }
+
+ private IAttribute[] DecodeReturnTypeAttributes()
+ {
+ var b = new AttributeListBuilder(assembly);
+ var metadata = assembly.metadata;
+ var methodDefinition = metadata.GetMethodDefinition(handle);
+ var parameters = methodDefinition.GetParameters();
+ if (parameters.Count > 0) {
+ var retParam = metadata.GetParameter(parameters.First());
+ if (retParam.SequenceNumber == 0) {
+ b.AddMarshalInfo(retParam.GetMarshallingDescriptor());
+ b.Add(retParam.GetCustomAttributes());
+ }
+ }
+ return b.Build();
+ }
+ #endregion
+
+ public Accessibility Accessibility => GetAccessibility(attributes);
+
+ internal static Accessibility GetAccessibility(MethodAttributes attr)
+ {
+ switch (attr & MethodAttributes.MemberAccessMask) {
+ case MethodAttributes.Public:
+ return Accessibility.Public;
+ case MethodAttributes.Assembly:
+ return Accessibility.Internal;
+ case MethodAttributes.Private:
+ return Accessibility.Private;
+ case MethodAttributes.Family:
+ return Accessibility.Protected;
+ case MethodAttributes.FamANDAssem:
+ return Accessibility.ProtectedAndInternal;
+ case MethodAttributes.FamORAssem:
+ return Accessibility.ProtectedOrInternal;
+ default:
+ return Accessibility.None;
+ }
+ }
+
+ public bool IsStatic => (attributes & MethodAttributes.Static) != 0;
+ public bool IsAbstract => (attributes & MethodAttributes.Abstract) != 0;
+ public bool IsSealed => (attributes & (MethodAttributes.Abstract | MethodAttributes.Final | MethodAttributes.NewSlot | MethodAttributes.Static)) == MethodAttributes.Final;
+ public bool IsVirtual => (attributes & (MethodAttributes.Abstract | MethodAttributes.Virtual | MethodAttributes.NewSlot)) == (MethodAttributes.Virtual | MethodAttributes.NewSlot);
+ public bool IsOverride => (attributes & (MethodAttributes.NewSlot | MethodAttributes.Static)) == 0;
+ public bool IsOverridable
+ => (attributes & (MethodAttributes.Abstract | MethodAttributes.Virtual)) != 0
+ && (attributes & MethodAttributes.Final) == 0;
+
+ bool IEntity.IsShadowing => throw new NotImplementedException();
+
+ public string FullName => $"{DeclaringType?.FullName}.{Name}";
+ public string ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}";
+ public string Namespace => DeclaringType?.Namespace ?? string.Empty;
+
+ bool IMember.Equals(IMember obj, TypeVisitor typeNormalization)
+ {
+ return obj == this;
+ }
+
+ public IMethod Specialize(TypeParameterSubstitution substitution)
+ {
+ return SpecializedMethod.Create(this, substitution);
+ }
+
+ IMember IMember.Specialize(TypeParameterSubstitution substitution)
+ {
+ return SpecializedMethod.Create(this, substitution);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
new file mode 100644
index 000000000..35a35de9a
--- /dev/null
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
@@ -0,0 +1,73 @@
+// 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.Generic;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using System.Text;
+
+namespace ICSharpCode.Decompiler.TypeSystem.Implementation
+{
+ sealed class MetadataParameter : IParameter
+ {
+ readonly MetadataAssembly assembly;
+ readonly ParameterHandle handle;
+ readonly ParameterAttributes attributes;
+
+ public IType Type { get; }
+ public IParameterizedMember Owner { get; }
+
+ internal MetadataParameter(MetadataAssembly assembly, IParameterizedMember owner, IType type, ParameterHandle handle)
+ {
+ this.assembly = assembly;
+ this.Owner = owner;
+ this.Type = type;
+ this.handle = handle;
+
+ var param = assembly.metadata.GetParameter(handle);
+ this.attributes = param.Attributes;
+ }
+
+ public EntityHandle MetadataToken => handle;
+
+ public IReadOnlyList Attributes => throw new NotImplementedException();
+
+ const ParameterAttributes inOut = ParameterAttributes.In | ParameterAttributes.Out;
+ public bool IsRef => Type.Kind == TypeKind.ByReference && (attributes & inOut) != ParameterAttributes.Out;
+ public bool IsOut => Type.Kind == TypeKind.ByReference && (attributes & inOut) == ParameterAttributes.Out;
+
+ public bool IsParams => throw new NotImplementedException();
+
+ public bool IsOptional => (attributes & ParameterAttributes.HasDefault) != 0;
+
+ public string Name => throw new NotImplementedException();
+
+ bool IVariable.IsConst => false;
+
+ public object ConstantValue => throw new NotImplementedException();
+
+ SymbolKind ISymbol.SymbolKind => SymbolKind.Parameter;
+
+ public override string ToString()
+ {
+ return $"{MetadataTokens.GetToken(handle):X8} {DefaultParameter.ToString(this)}";
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs
index 1546bf93f..2f243e97b 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs
@@ -82,7 +82,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.Kind = TypeKind.Enum;
this.EnumUnderlyingType = assembly.Compilation.FindType(underlyingType.ToKnownTypeCode());
} else if (td.IsValueType(metadata)) {
- this.Kind = TypeKind.Struct;
+ if (KnownTypeCode == KnownTypeCode.Void) {
+ this.Kind = TypeKind.Void;
+ } else {
+ this.Kind = TypeKind.Struct;
+ }
} else if (td.IsDelegate(metadata)) {
this.Kind = TypeKind.Delegate;
} else {
@@ -97,8 +101,24 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return $"{MetadataTokens.GetToken(handle):X8} {fullTypeName}";
}
- public IReadOnlyList NestedTypes => throw new NotImplementedException();
+ ITypeDefinition[] nestedTypes;
+
+ public IReadOnlyList NestedTypes {
+ get {
+ var nestedTypes = LazyInit.VolatileRead(ref this.nestedTypes);
+ if (nestedTypes != null)
+ return nestedTypes;
+ var metadata = assembly.metadata;
+ var nestedTypeCollection = metadata.GetTypeDefinition(handle).GetNestedTypes();
+ var nestedTypeList = new List(nestedTypeCollection.Length);
+ foreach (TypeDefinitionHandle h in nestedTypeCollection) {
+ nestedTypeList.Add(assembly.GetDefinition(h));
+ }
+ return LazyInit.GetOrSet(ref this.nestedTypes, nestedTypeList.ToArray());
+ }
+ }
+ #region Members
IMember[] members;
public IReadOnlyList Members {
@@ -132,13 +152,57 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
- public IEnumerable Methods => throw new NotImplementedException();
+ IProperty[] properties;
+
+ public IEnumerable Properties {
+ get {
+ var properties = LazyInit.VolatileRead(ref this.properties);
+ if (properties != null)
+ return properties;
+ var metadata = assembly.metadata;
+ var propertyCollection = metadata.GetTypeDefinition(handle).GetProperties();
+ var propertyList = new List(propertyCollection.Count);
+ foreach (PropertyDefinitionHandle h in propertyCollection) {
+ propertyList.Add(assembly.GetDefinition(h));
+ }
+ return LazyInit.GetOrSet(ref this.properties, propertyList.ToArray());
+ }
+ }
- public IEnumerable Properties => throw new NotImplementedException();
+ IEvent[] events;
- public IEnumerable Events => throw new NotImplementedException();
+ public IEnumerable Events {
+ get {
+ var events = LazyInit.VolatileRead(ref this.events);
+ if (events != null)
+ return events;
+ var metadata = assembly.metadata;
+ var eventCollection = metadata.GetTypeDefinition(handle).GetEvents();
+ var eventList = new List(eventCollection.Count);
+ foreach (EventDefinitionHandle h in eventCollection) {
+ eventList.Add(assembly.GetDefinition(h));
+ }
+ return LazyInit.GetOrSet(ref this.events, eventList.ToArray());
+ }
+ }
+ IMethod[] methods;
+ public IEnumerable Methods {
+ get {
+ var methods = LazyInit.VolatileRead(ref this.methods);
+ if (methods != null)
+ return methods;
+ var metadata = assembly.metadata;
+ var methodsCollection = metadata.GetTypeDefinition(handle).GetMethods();
+ var methodsList = new List(methodsCollection.Count);
+ foreach (MethodDefinitionHandle h in methodsCollection) {
+ methodsList.Add(assembly.GetDefinition(h));
+ }
+ return LazyInit.GetOrSet(ref this.methods, methodsList.ToArray());
+ }
+ }
+ #endregion
public IType DeclaringType => DeclaringTypeDefinition;
@@ -161,7 +225,28 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IReadOnlyList IType.TypeArguments => TypeParameters;
- public IEnumerable DirectBaseTypes => throw new NotImplementedException();
+ List directBaseTypes;
+
+ public IEnumerable DirectBaseTypes {
+ get {
+ var baseTypes = LazyInit.VolatileRead(ref this.directBaseTypes);
+ if (baseTypes != null)
+ return baseTypes;
+ var metadata = assembly.metadata;
+ var td = metadata.GetTypeDefinition(handle);
+ var context = new GenericContext(TypeParameters);
+ var interfaceImplCollection = td.GetInterfaceImplementations();
+ baseTypes = new List(1 + interfaceImplCollection.Count);
+ if (!td.BaseType.IsNil) {
+ baseTypes.Add(assembly.ResolveType(td.BaseType, context));
+ }
+ foreach (var h in interfaceImplCollection) {
+ var iface = metadata.GetInterfaceImplementation(h);
+ baseTypes.Add(assembly.ResolveType(iface.Interface, context, iface.GetCustomAttributes()));
+ }
+ return LazyInit.GetOrSet(ref this.directBaseTypes, baseTypes);
+ }
+ }
public EntityHandle MetadataToken => handle;
@@ -285,7 +370,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public ICompilation Compilation => assembly.Compilation;
- public string FullName => throw new NotImplementedException();
+ public string FullName {
+ get {
+ if (DeclaringType != null)
+ return DeclaringType.FullName + "." + Name;
+ else if (!string.IsNullOrEmpty(this.Namespace))
+ return this.Namespace + "." + Name;
+ else
+ return Name;
+ }
+ }
+
public string ReflectionName => fullTypeName.ReflectionName;
public string Namespace => fullTypeName.TopLevelTypeName.Namespace;
@@ -344,6 +439,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None)
{
+ if (Kind == TypeKind.Void)
+ return EmptyList.Instance;
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Methods, ExtensionMethods.And(m => !m.IsConstructor, filter));
} else {
@@ -353,11 +450,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IEnumerable GetMethods(IReadOnlyList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None)
{
+ if (Kind == TypeKind.Void)
+ return EmptyList.Instance;
return GetMembersHelper.GetMethods(this, typeArguments, filter, options);
}
public IEnumerable GetConstructors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers)
{
+ if (Kind == TypeKind.Void)
+ return EmptyList.Instance;
if (ComHelper.IsComImport(this)) {
IType coClass = ComHelper.GetCoClass(this);
using (var busyLock = BusyManager.Enter(this)) {
@@ -377,6 +478,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None)
{
+ if (Kind == TypeKind.Void)
+ return EmptyList.Instance;
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Properties, filter);
} else {
@@ -386,6 +489,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IEnumerable GetFields(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None)
{
+ if (Kind == TypeKind.Void)
+ return EmptyList.Instance;
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Fields, filter);
} else {
@@ -395,6 +500,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IEnumerable GetEvents(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None)
{
+ if (Kind == TypeKind.Void)
+ return EmptyList.Instance;
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Events, filter);
} else {
@@ -404,6 +511,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None)
{
+ if (Kind == TypeKind.Void)
+ return EmptyList.Instance;
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Members, filter);
} else {
@@ -413,6 +522,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None)
{
+ if (Kind == TypeKind.Void)
+ return EmptyList.Instance;
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFilteredAccessors(filter);
} else {
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs
index 100870cb6..6da3f7594 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs
@@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
@@ -36,23 +37,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IReadOnlyList customAttributes;
IReadOnlyList constraints;
- public static IReadOnlyList Create(MetadataAssembly assembly, IEntity owner, GenericParameterHandleCollection handles)
+ public static ITypeParameter[] Create(MetadataAssembly assembly, IEntity owner, GenericParameterHandleCollection handles)
{
if (handles.Count == 0)
- return EmptyList.Instance;
+ return Empty.Array;
var tps = new ITypeParameter[handles.Count];
int i = 0;
foreach (var handle in handles) {
- tps[i] = Create(assembly, owner, handle);
+ tps[i] = Create(assembly, owner, i, handle);
+ i++;
}
return tps;
}
- public static MetadataTypeParameter Create(MetadataAssembly assembly, IEntity owner, GenericParameterHandle handle)
+ public static MetadataTypeParameter Create(MetadataAssembly assembly, IEntity owner, int index, GenericParameterHandle handle)
{
var metadata = assembly.metadata;
var gp = metadata.GetGenericParameter(handle);
- return new MetadataTypeParameter(assembly, owner, gp.Index, assembly.GetString(gp.Name), handle, gp.Attributes);
+ Debug.Assert(gp.Index == index);
+ return new MetadataTypeParameter(assembly, owner, index, assembly.GetString(gp.Name), handle, gp.Attributes);
}
private MetadataTypeParameter(MetadataAssembly assembly, IEntity owner, int index, string name,
diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs
index 7abb95089..298ee55b8 100644
--- a/ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs
@@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
@@ -48,6 +49,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
readonly MetadataNamespace rootNamespace;
readonly MetadataTypeDefinition[] typeDefs;
readonly MetadataField[] fieldDefs;
+ readonly MetadataMethod[] methodDefs;
internal MetadataAssembly(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options)
{
@@ -67,9 +69,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
this.AssemblyName = metadata.GetString(moddef.Name);
this.FullAssemblyName = this.AssemblyName;
}
+ this.rootNamespace = new MetadataNamespace(this, null, string.Empty, metadata.GetNamespaceDefinitionRoot());
+
// create arrays for resolved entities, indexed by row index
this.typeDefs = new MetadataTypeDefinition[metadata.TypeDefinitions.Count + 1];
this.fieldDefs = new MetadataField[metadata.FieldDefinitions.Count + 1];
+ this.methodDefs = new MetadataMethod[metadata.MethodDefinitions.Count + 1];
}
internal string GetString(StringHandle name)
@@ -181,7 +186,14 @@ namespace ICSharpCode.Decompiler.TypeSystem
public IMethod GetDefinition(MethodDefinitionHandle handle)
{
- throw new NotImplementedException();
+ int row = MetadataTokens.GetRowNumber(handle);
+ if (row >= methodDefs.Length)
+ return null;
+ var method = LazyInit.VolatileRead(ref methodDefs[row]);
+ if (method != null || handle.IsNil)
+ return method;
+ method = new MetadataMethod(this, handle);
+ return LazyInit.GetOrSet(ref methodDefs[row], method);
}
public IProperty GetDefinition(PropertyDefinitionHandle handle)
@@ -195,16 +207,199 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
#endregion
- public IMethod ResolveMethod(EntityHandle methodRefDefSpec, GenericContext context = default)
+ #region Resolve Type
+ public IType ResolveType(EntityHandle typeRefDefSpec, GenericContext context, CustomAttributeHandleCollection? typeAttributes = null)
{
- throw new NotImplementedException();
+ return ResolveType(typeRefDefSpec, context, options, typeAttributes);
+ }
+
+ public IType ResolveType(SRM.EntityHandle typeRefDefSpec, GenericContext context, TypeSystemOptions customOptions, CustomAttributeHandleCollection? typeAttributes = null)
+ {
+ return MetadataTypeReference.Resolve(typeRefDefSpec, metadata, TypeProvider, context, customOptions, typeAttributes);
+ }
+
+ IType ResolveDeclaringType(SRM.EntityHandle declaringTypeReference, GenericContext context)
+ {
+ // resolve without substituting dynamic/tuple types
+ return ResolveType(declaringTypeReference, context,
+ options & ~(TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple));
+ }
+ #endregion
+
+ #region ResolveMethod
+ 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;
+ 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)
+ {
+ var method = GetDefinition(methodDefHandle);
+ if (method == null) {
+ throw new NotImplementedException();
+ }
+ if (expandVarArgs && method.Parameters.LastOrDefault()?.Type.Kind == TypeKind.ArgList) {
+ method = new VarArgInstanceMethod(method, EmptyList.Instance);
+ }
+ return method;
+ }
+
+ ///
+ /// Resolves a method reference.
+ ///
+ ///
+ /// Class type arguments are provided by the declaring type stored in the memberRef.
+ /// Method type arguments are provided by the caller.
+ ///
+ IMethod ResolveMethodReference(SRM.MetadataReader metadata, SRM.MemberReferenceHandle memberRefHandle, GenericContext context, IReadOnlyList methodTypeArguments = null)
+ {
+ var memberRef = metadata.GetMemberReference(memberRefHandle);
+ Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Method);
+ SRM.MethodSignature signature;
+ IReadOnlyList classTypeArguments = null;
+ IMethod method;
+ if (memberRef.Parent.Kind == SRM.HandleKind.MethodDefinition) {
+ method = ResolveMethodDefinition(metadata, (SRM.MethodDefinitionHandle)memberRef.Parent, expandVarArgs: false);
+ signature = memberRef.DecodeMethodSignature(TypeProvider, context);
+ } else {
+ var declaringType = ResolveDeclaringType(memberRef.Parent, context);
+ var declaringTypeDefinition = declaringType.GetDefinition();
+ if (declaringType.TypeArguments.Count > 0) {
+ classTypeArguments = declaringType.TypeArguments;
+ }
+ // Note: declaringType might be parameterized, but the signature is for the original method definition.
+ // We'll have to search the member directly on declaringTypeDefinition.
+ string name = metadata.GetString(memberRef.Name);
+ signature = memberRef.DecodeMethodSignature(TypeProvider,
+ new GenericContext(declaringTypeDefinition?.TypeParameters));
+ if (declaringTypeDefinition != null) {
+ // Find the set of overloads to search:
+ IEnumerable methods;
+ if (name == ".ctor") {
+ methods = declaringTypeDefinition.GetConstructors();
+ } else if (name == ".cctor") {
+ methods = declaringTypeDefinition.Methods.Where(m => m.IsConstructor && m.IsStatic);
+ } else {
+ methods = declaringTypeDefinition.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers)
+ .Concat(declaringTypeDefinition.GetAccessors(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers));
+ }
+ // Determine the expected parameters from the signature:
+ ImmutableArray parameterTypes;
+ if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
+ parameterTypes = signature.ParameterTypes
+ .Take(signature.RequiredParameterCount)
+ .Concat(new[] { SpecialType.ArgList })
+ .ToImmutableArray();
+ } else {
+ parameterTypes = signature.ParameterTypes;
+ }
+ // Search for the matching method:
+ method = null;
+ foreach (var m in methods) {
+ if (m.TypeParameters.Count != signature.GenericParameterCount)
+ continue;
+ if (CompareSignatures(m.Parameters, parameterTypes) && CompareTypes(m.ReturnType, signature.ReturnType)) {
+ method = m;
+ break;
+ }
+ }
+ } else {
+ method = null;
+ }
+ if (method == null) {
+ method = CreateFakeMethod(declaringType, name, signature);
+ }
+ }
+ if (classTypeArguments != null || methodTypeArguments != null) {
+ method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments));
+ }
+ if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
+ method = new VarArgInstanceMethod(method, signature.ParameterTypes.Skip(signature.RequiredParameterCount));
+ }
+ return method;
}
- public IType ResolveType(EntityHandle typeRefDefSpec, GenericContext context = default, CustomAttributeHandleCollection? typeAttributes = null)
+ static readonly NormalizeTypeVisitor normalizeTypeVisitor = new NormalizeTypeVisitor {
+ ReplaceClassTypeParametersWithDummy = true,
+ ReplaceMethodTypeParametersWithDummy = true,
+ };
+
+ static bool CompareTypes(IType a, IType b)
{
- return MetadataTypeReference.Resolve(typeRefDefSpec, metadata, TypeProvider, context, options, typeAttributes);
+ IType type1 = a.AcceptVisitor(normalizeTypeVisitor);
+ IType type2 = b.AcceptVisitor(normalizeTypeVisitor);
+ return type1.Equals(type2);
}
+ static bool CompareSignatures(IReadOnlyList parameters, ImmutableArray parameterTypes)
+ {
+ if (parameterTypes.Length != parameters.Count)
+ return false;
+ for (int i = 0; i < parameterTypes.Length; i++) {
+ if (!CompareTypes(parameterTypes[i], parameters[i].Type))
+ return false;
+ }
+ return true;
+ }
+
+ ///
+ /// Create a dummy IMethod from the specified MethodReference
+ ///
+ IMethod CreateFakeMethod(IType declaringType, string name, SRM.MethodSignature signature)
+ {
+ SymbolKind symbolKind = SymbolKind.Method;
+ if (name == ".ctor" || name == ".cctor")
+ symbolKind = SymbolKind.Constructor;
+ var m = new FakeMethod(Compilation, symbolKind);
+ m.DeclaringType = declaringType;
+ m.Name = name;
+ m.ReturnType = signature.ReturnType;
+ m.IsStatic = !signature.Header.IsInstance;
+
+ TypeParameterSubstitution substitution = null;
+ if (signature.GenericParameterCount > 0) {
+ var typeParameters = new List();
+ for (int i = 0; i < signature.GenericParameterCount; i++) {
+ typeParameters.Add(new DefaultTypeParameter(m, i));
+ }
+ m.TypeParameters = typeParameters;
+ substitution = new TypeParameterSubstitution(null, typeParameters);
+ }
+ var parameters = new List();
+ for (int i = 0; i < signature.RequiredParameterCount; i++) {
+ var type = signature.ParameterTypes[i];
+ if (substitution != null) {
+ // replace the dummy method type parameters with the owned instances we just created
+ type = type.AcceptVisitor(substitution);
+ }
+ parameters.Add(new DefaultParameter(type, ""));
+ }
+ m.Parameters = parameters;
+ return m;
+ }
+ #endregion
+
#region Module / Assembly attributes
IAttribute[] assemblyAttributes;
IAttribute[] moduleAttributes;
diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs
index e987bafa2..5b0fc90ed 100644
--- a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs
@@ -144,8 +144,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
public IType GetTypeFromSerializedName(string name)
{
- // TODO: aren't we missing support for assembly-qualified names?
- return new GetClassTypeReference(new FullTypeName(name))
+ return ReflectionHelper.ParseReflectionName(name)
.Resolve(assembly != null ? new SimpleTypeResolveContext(assembly) : new SimpleTypeResolveContext(compilation));
}