diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
index 53e57c88b..150ae6665 100644
--- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
@@ -985,7 +985,8 @@ namespace ICSharpCode.Decompiler.CSharp
// Field data as specified in II.16.3.2 of ECMA-335 6th edition:
// .data I_X = int32(123)
// .field public static int32 _x at I_X
- var message = string.Format(" Not supported: data({0}) ", BitConverter.ToString(fieldDefinition.GetInitialValue(typeSystem.ModuleDefinition.Reader)).Replace('-', ' '));
+ var initVal = fieldDefinition.GetInitialValue(typeSystem.ModuleDefinition.Reader);
+ var message = string.Format(" Not supported: data({0}) ", BitConverter.ToString(initVal.ReadBytes(initVal.RemainingBytes)).Replace('-', ' '));
((FieldDeclaration)fieldDecl).Variables.Single().AddChild(new Comment(message, CommentType.MultiLine), Roles.Comment);
}
return fieldDecl;
diff --git a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
index f50b32dca..eab00bde4 100644
--- a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
+++ b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
@@ -156,9 +156,9 @@ namespace ICSharpCode.Decompiler.CSharp
var metadata = reader.GetMetadataReader();
if (!method.LocalSignature.IsNil) {
- var localSignature = metadata.GetStandaloneSignature(method.LocalSignature).DecodeLocalSignature(TypeReferenceSignatureDecoder.Instance, default);
+ var localSignature = typeSystem.DecodeLocalSignature(method.LocalSignature);
foreach (var type in localSignature)
- CollectNamespacesForTypeReference(typeSystem.ResolveFromSignature(type), namespaces);
+ CollectNamespacesForTypeReference(type, namespaces);
}
foreach (var region in method.ExceptionRegions) {
diff --git a/ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs b/ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs
index a39c030ef..e3bb19e53 100644
--- a/ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs
+++ b/ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs
@@ -198,12 +198,12 @@ namespace ICSharpCode.Decompiler.Documentation
public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired)
{
- throw new NotImplementedException();
+ return unmodifiedType;
}
public string GetPinnedType(string elementType)
{
- throw new NotImplementedException();
+ return elementType;
}
public string GetPointerType(string elementType)
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index e87d87739..bfa6aa47d 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -338,11 +338,14 @@
+
+
+
diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs
index e45d0695a..273a74c89 100644
--- a/ICSharpCode.Decompiler/IL/ILReader.cs
+++ b/ICSharpCode.Decompiler/IL/ILReader.cs
@@ -54,7 +54,6 @@ namespace ICSharpCode.Decompiler.IL
IMethod method;
MethodBodyBlock body;
Metadata.IDebugInfoProvider debugInfo;
- MethodSignature methodSignature;
StackType methodReturnStackType;
BlobReader reader;
ImmutableStack currentStack;
@@ -78,14 +77,13 @@ namespace ICSharpCode.Decompiler.IL
this.metadata = module.Metadata;
this.method = typeSystem.ResolveAsMethod(methodDefinitionHandle);
var methodDefinition = metadata.GetMethodDefinition(methodDefinitionHandle);
- this.methodSignature = methodDefinition.DecodeSignature(TypeSystem.Implementation.TypeReferenceSignatureDecoder.Instance, default);
this.body = body;
this.reader = body.GetILReader();
this.debugInfo = module.DebugInfo;
this.currentStack = ImmutableStack.Empty;
this.unionFind = new UnionFind();
this.stackMismatchPairs = new List<(ILVariable, ILVariable)>();
- this.methodReturnStackType = typeSystem.ResolveFromSignature(TypeSystem.Implementation.DynamicTypeReference.Create(methodSignature.ReturnType, methodDefinition.GetCustomAttributes(), metadata)).GetStackType();
+ this.methodReturnStackType = method.ReturnType.GetStackType();
InitParameterVariables();
localVariables = InitLocalVariables();
if (body.LocalVariablesInitialized) {
@@ -126,12 +124,10 @@ namespace ICSharpCode.Decompiler.IL
ILVariable[] InitLocalVariables()
{
if (body.LocalSignature.IsNil) return Empty.Array;
- var standaloneSignature = metadata.GetStandaloneSignature(body.LocalSignature);
- Debug.Assert(standaloneSignature.GetKind() == StandaloneSignatureKind.LocalVariables);
- var variableTypes = standaloneSignature.DecodeLocalSignature(TypeSystem.Implementation.TypeReferenceSignatureDecoder.Instance, default);
+ var variableTypes = typeSystem.DecodeLocalSignature(body.LocalSignature);
var localVariables = new ILVariable[variableTypes.Length];
foreach (var (index, type) in variableTypes.WithIndex()) {
- localVariables[index] = CreateILVariable(index, typeSystem.ResolveFromSignature(type));
+ localVariables[index] = CreateILVariable(index, type);
}
return localVariables;
}
@@ -144,14 +140,16 @@ namespace ICSharpCode.Decompiler.IL
if (method.Parameters.LastOrDefault()?.Type == SpecialType.ArgList)
popCount--;
parameterVariables = new ILVariable[popCount];
- int paramIndex = 0; int offset = 0;
- if (methodSignature.Header.IsInstance) {
+ int paramIndex = 0;
+ int offset = 0;
+ if (!method.IsStatic) {
offset = 1;
parameterVariables[paramIndex++] = CreateILVariable(-1, method.DeclaringType, "this");
}
while (paramIndex < parameterVariables.Length) {
- var type = typeSystem.ResolveFromSignature(methodSignature.ParameterTypes[paramIndex - offset]);
- parameterVariables[paramIndex] = CreateILVariable(paramIndex - offset, type, method.Parameters[paramIndex - offset].Name);
+ IType type = method.Parameters[paramIndex - offset].Type;
+ string name = method.Parameters[paramIndex - offset].Name;
+ parameterVariables[paramIndex] = CreateILVariable(paramIndex - offset, type, name);
paramIndex++;
}
Debug.Assert(paramIndex == parameterVariables.Length);
@@ -181,16 +179,16 @@ namespace ICSharpCode.Decompiler.IL
ILVariable CreateILVariable(int index, IType parameterType, string name)
{
- ITypeDefinition def = parameterType.GetDefinition();
- if (def != null && index < 0 && def.IsReferenceType == false) {
- parameterType = new ByReferenceType(parameterType);
- }
Debug.Assert(!parameterType.IsUnbound());
if (parameterType.IsUnbound()) {
// parameter types should not be unbound, the only known cause for these is a Cecil bug:
Debug.Assert(index < 0); // cecil bug occurs only for "this"
parameterType = new ParameterizedType(parameterType.GetDefinition(), parameterType.TypeArguments);
}
+ ITypeDefinition def = parameterType.GetDefinition();
+ if (def != null && index < 0 && def.IsReferenceType == false) {
+ parameterType = new ByReferenceType(parameterType);
+ }
var ilVar = new ILVariable(VariableKind.Parameter, parameterType, index);
Debug.Assert(ilVar.StoreCount == 1); // count the initial store when the method is called with an argument
if (index < 0)
@@ -1289,21 +1287,18 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction DecodeCallIndirect()
{
- var standaloneSignature = metadata.GetStandaloneSignature((StandaloneSignatureHandle)ReadAndDecodeMetadataToken());
- Debug.Assert(standaloneSignature.GetKind() == StandaloneSignatureKind.Method);
- var signature = standaloneSignature.DecodeMethodSignature(TypeSystem.Implementation.TypeReferenceSignatureDecoder.Instance, default);
+ var signatureHandle = (StandaloneSignatureHandle)ReadAndDecodeMetadataToken();
+ var signature = typeSystem.DecodeMethodSignature(signatureHandle);
var functionPointer = Pop(StackType.I);
Debug.Assert(!signature.Header.IsInstance);
- var parameterTypes = new IType[signature.ParameterTypes.Length];
- var arguments = new ILInstruction[parameterTypes.Length];
+ var arguments = new ILInstruction[signature.ParameterTypes.Length];
for (int i = signature.ParameterTypes.Length - 1; i >= 0; i--) {
- parameterTypes[i] = typeSystem.ResolveFromSignature(signature.ParameterTypes[i]);
- arguments[i] = Pop(parameterTypes[i].GetStackType());
+ arguments[i] = Pop(signature.ParameterTypes[i].GetStackType());
}
var call = new CallIndirect(
signature.Header.CallingConvention,
- typeSystem.ResolveFromSignature(signature.ReturnType),
- parameterTypes.ToImmutableArray(),
+ signature.ReturnType,
+ signature.ParameterTypes,
arguments,
functionPointer
);
diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs
index b64697f67..d7bc19fc8 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs
@@ -19,8 +19,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Reflection.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.IL.Transforms
@@ -337,7 +337,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (MatchInitializeArrayCall(body.Instructions[pos], out var method, out var v2, out var field) && array == v2) {
if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) {
var valuesList = new List();
- if (DecodeArrayInitializer(arrayType, array, field.GetInitialValue(context.TypeSystem.ModuleDefinition.Reader), arrayLength, valuesList)) {
+ var initialValue = field.GetInitialValue(context.TypeSystem.ModuleDefinition.Reader);
+ if (DecodeArrayInitializer(arrayType, array, initialValue, arrayLength, valuesList)) {
values = valuesList.ToArray();
foundPos = pos;
return true;
@@ -349,30 +350,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
}
- static bool DecodeArrayInitializer(IType type, ILVariable array, byte[] initialValue, int[] arrayLength, List output)
+ static bool DecodeArrayInitializer(IType type, ILVariable array, BlobReader initialValue, int[] arrayLength, List output)
{
TypeCode typeCode = ReflectionHelper.GetTypeCode(type);
switch (typeCode) {
case TypeCode.Boolean:
case TypeCode.Byte:
- return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI4((int)d[i]));
+ return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI4(r.ReadByte()));
case TypeCode.SByte:
- return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI4((int)unchecked((sbyte)d[i])));
+ return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI4(r.ReadSByte()));
case TypeCode.Int16:
- return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI4((int)BitConverter.ToInt16(d, i)));
+ return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI4(r.ReadInt16()));
case TypeCode.Char:
case TypeCode.UInt16:
- return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI4((int)BitConverter.ToUInt16(d, i)));
+ return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI4(r.ReadUInt16()));
case TypeCode.Int32:
case TypeCode.UInt32:
- return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI4(BitConverter.ToInt32(d, i)));
+ return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI4(r.ReadInt32()));
case TypeCode.Int64:
case TypeCode.UInt64:
- return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI8(BitConverter.ToInt64(d, i)));
+ return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI8(r.ReadInt64()));
case TypeCode.Single:
- return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcF4(BitConverter.ToSingle(d, i)));
+ return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcF4(r.ReadSingle()));
case TypeCode.Double:
- return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcF8(BitConverter.ToDouble(d, i)));
+ return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcF8(r.ReadDouble()));
case TypeCode.Object:
case TypeCode.Empty:
var typeDef = type.GetDefinition();
@@ -384,15 +385,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
- static bool DecodeArrayInitializer(byte[] initialValue, ILVariable array, int[] arrayLength, List output, TypeCode elementType, IType type, Func decoder)
+ delegate ILInstruction ValueDecoder(ref BlobReader reader);
+
+ static bool DecodeArrayInitializer(BlobReader initialValue, ILVariable array, int[] arrayLength,
+ List output, TypeCode elementType, IType type, ValueDecoder decoder)
{
int elementSize = ElementSizeOf(elementType);
var totalLength = arrayLength.Aggregate(1, (t, l) => t * l);
- if (initialValue.Length < (totalLength * elementSize))
+ if (initialValue.RemainingBytes < (totalLength * elementSize))
return false;
for (int i = 0; i < totalLength; i++) {
- output.Add(decoder(initialValue, i * elementSize));
+ output.Add(decoder(ref initialValue));
int next = i;
for (int j = arrayLength.Length - 1; j >= 0; j--) {
output.Add(new LdcI4(next % arrayLength[j]));
diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
index b6fbf6df3..a178c1b77 100644
--- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
+++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
@@ -170,7 +170,16 @@ namespace ICSharpCode.Decompiler.Metadata
return type.GetDefaultMemberName(reader, out var attr);
}
- static readonly ITypeResolveContext minimalCorlibContext = new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation());
+ internal static readonly TypeProvider minimalCorlibTypeProvider =
+ new TypeProvider(MinimalCorlib.Instance.CreateCompilation().MainAssembly);
+
+ ///
+ /// An attribute type provider that can be used to decode attribute signatures
+ /// that only mention built-in types.
+ ///
+ public static ICustomAttributeTypeProvider MinimalAttributeTypeProvider {
+ get => minimalCorlibTypeProvider;
+ }
public static string GetDefaultMemberName(this TypeDefinitionHandle type, MetadataReader reader, out CustomAttributeHandle defaultMemberAttribute)
{
@@ -178,8 +187,8 @@ namespace ICSharpCode.Decompiler.Metadata
foreach (var h in td.GetCustomAttributes()) {
var ca = reader.GetCustomAttribute(h);
- if (ca.GetAttributeType(reader).ToString() == "System.Reflection.DefaultMemberAttribute") {
- var decodedValues = ca.DecodeValue(new TypeSystemAttributeTypeProvider(minimalCorlibContext));
+ if (ca.GetAttributeType(reader).IsTopLevelType(reader, "System.Reflection", "DefaultMemberAttribute")) {
+ var decodedValues = ca.DecodeValue(minimalCorlibTypeProvider);
if (decodedValues.FixedArguments.Length == 1 && decodedValues.FixedArguments[0].Value is string value) {
defaultMemberAttribute = h;
return value;
@@ -190,7 +199,7 @@ namespace ICSharpCode.Decompiler.Metadata
defaultMemberAttribute = default(CustomAttributeHandle);
return null;
}
-
+
public static bool HasOverrides(this MethodDefinitionHandle handle, MetadataReader reader)
{
for (int row = 1; row <= reader.GetTableRowCount(TableIndex.MethodImpl); row++) {
@@ -214,7 +223,7 @@ namespace ICSharpCode.Decompiler.Metadata
return false;
}
- public static PrimitiveTypeCode ToPrimtiveTypeCode(this KnownTypeCode typeCode)
+ public static PrimitiveTypeCode ToPrimitiveTypeCode(this KnownTypeCode typeCode)
{
switch (typeCode) {
case KnownTypeCode.Object:
diff --git a/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs b/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
index 3efc4c159..81bf49425 100644
--- a/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
+++ b/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
@@ -360,7 +360,7 @@ namespace ICSharpCode.Decompiler.Metadata
for (; i < totalParameterCount; i++) {
if (!IsSameCompressedInteger(ref a, ref b, out typeCode))
return false;
- //
+ // varargs sentinel
if (typeCode == 65)
break;
if (!TypesAreEqual(ref a, ref b, contextForA, contextForB, typeCode))
diff --git a/ICSharpCode.Decompiler/SRMExtensions.cs b/ICSharpCode.Decompiler/SRMExtensions.cs
index a971e4731..11992b89a 100644
--- a/ICSharpCode.Decompiler/SRMExtensions.cs
+++ b/ICSharpCode.Decompiler/SRMExtensions.cs
@@ -183,6 +183,16 @@ namespace ICSharpCode.Decompiler
}
}
+ public static bool IsTopLevelType(this EntityHandle handle, MetadataReader reader, string namespaceName, string name, int typeParameterCount = 0)
+ {
+ return GetFullTypeName(handle, reader) == new TopLevelTypeName(namespaceName, name, typeParameterCount);
+ }
+
+ public static bool IsAttributeType(this CustomAttribute attr, MetadataReader reader, string namespaceName, string name)
+ {
+ return attr.GetAttributeType(reader).IsTopLevelType(reader, namespaceName, name);
+ }
+
public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader)
{
if (handle.IsNil)
@@ -362,24 +372,13 @@ namespace ICSharpCode.Decompiler
}
#endregion
- public static byte[] GetInitialValue(this FieldDefinition field, PEReader pefile)
+ public static unsafe BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile)
{
if (!field.HasFlag(FieldAttributes.HasFieldRVA) || field.GetRelativeVirtualAddress() == 0)
- return Empty.Array;
+ return default;
int rva = field.GetRelativeVirtualAddress();
int size = field.DecodeSignature(new FieldValueSizeDecoder(), default);
- var headers = pefile.PEHeaders;
- int index = headers.GetContainingSectionIndex(rva);
- var sectionHeader = headers.SectionHeaders[index];
- var sectionData = pefile.GetEntireImage();
- int totalOffset = rva + sectionHeader.PointerToRawData - sectionHeader.VirtualAddress;
- var reader = sectionData.GetReader();
- reader.Offset += totalOffset;
- int offset = field.GetOffset();
- if (offset > 0)
- reader.Offset += offset;
- return reader.ReadBytes(size);
-
+ return pefile.GetSectionData(rva).GetReader(0, size);
}
class FieldValueSizeDecoder : ISignatureTypeProvider
@@ -387,14 +386,14 @@ namespace ICSharpCode.Decompiler
public int GetArrayType(int elementType, ArrayShape shape) => elementType;
public int GetByReferenceType(int elementType) => elementType;
public int GetFunctionPointerType(MethodSignature signature) => IntPtr.Size;
- public int GetGenericInstantiation(int genericType, ImmutableArray typeArguments) => throw new NotSupportedException();
- public int GetGenericMethodParameter(Unit genericContext, int index) => throw new NotSupportedException();
- public int GetGenericTypeParameter(Unit genericContext, int index) => throw new NotSupportedException();
+ public int GetGenericInstantiation(int genericType, ImmutableArray typeArguments) => genericType;
+ public int GetGenericMethodParameter(Unit genericContext, int index) => 0;
+ public int GetGenericTypeParameter(Unit genericContext, int index) => 0;
public int GetModifiedType(int modifier, int unmodifiedType, bool isRequired) => unmodifiedType;
public int GetPinnedType(int elementType) => elementType;
public int GetPointerType(int elementType) => elementType;
- public int GetPrimitiveType(PrimitiveTypeCode typeCode)
+ public int GetPrimitiveType(PrimitiveTypeCode typeCode)
{
switch (typeCode) {
case PrimitiveTypeCode.Boolean:
@@ -421,7 +420,7 @@ namespace ICSharpCode.Decompiler
}
}
- public int GetSZArrayType(int elementType) => throw new NotSupportedException();
+ public int GetSZArrayType(int elementType) => 0;
public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
@@ -431,12 +430,12 @@ namespace ICSharpCode.Decompiler
public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
- throw new NotImplementedException();
+ return 0;
}
public int GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
- throw new NotImplementedException();
+ return 0;
}
}
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs b/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
new file mode 100644
index 000000000..bdf5b423c
--- /dev/null
+++ b/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
@@ -0,0 +1,202 @@
+// Copyright (c) 2018 Daniel Grunwald
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Linq;
+using ICSharpCode.Decompiler.Util;
+using SRM = System.Reflection.Metadata;
+
+namespace ICSharpCode.Decompiler.TypeSystem
+{
+ ///
+ /// Options for converting builtin
+ ///
+ [Flags]
+ enum TypeAttributeOptions
+ {
+ None = 0,
+ Dynamic = 1,
+ Tuple = 2,
+ Default = Dynamic | Tuple
+ }
+
+ ///
+ /// Introduces 'dynamic' and tuple types based on attribute values.
+ ///
+ class ApplyAttributeTypeVisitor : TypeVisitor
+ {
+ public static IType ApplyAttributesToType(
+ IType inputType,
+ ICompilation compilation,
+ SRM.CustomAttributeHandleCollection? attributes,
+ SRM.MetadataReader metadata,
+ TypeAttributeOptions options)
+ {
+ if (options == TypeAttributeOptions.None) {
+ return inputType;
+ }
+ bool hasDynamicAttribute = false;
+ bool[] dynamicAttributeData = null;
+ bool useTupleTypes = (options & TypeAttributeOptions.Tuple) != 0;
+ string[] tupleElementNames = null;
+ if (attributes != null) {
+ foreach (var attrHandle in attributes.Value) {
+ var attr = metadata.GetCustomAttribute(attrHandle);
+ var attrType = attr.GetAttributeType(metadata);
+ if ((options & TypeAttributeOptions.Dynamic) != 0
+ && attrType.IsTopLevelType(metadata, "System.Runtime.CompilerServices", "DynamicAttribute")) {
+ hasDynamicAttribute = true;
+ var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider);
+ if (ctor.FixedArguments.Length == 1) {
+ var arg = ctor.FixedArguments[0];
+ if (arg.Value is ImmutableArray> values
+ && values.All(v => v.Value is bool)) {
+ dynamicAttributeData = values.SelectArray(v => (bool)v.Value);
+ }
+ }
+ } else if (useTupleTypes && attrType.IsTopLevelType(metadata, "System.Runtime.CompilerServices", "TupleElementNamesAttribute")) {
+ var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider);
+ if (ctor.FixedArguments.Length == 1) {
+ var arg = ctor.FixedArguments[0];
+ if (arg.Value is ImmutableArray> values
+ && values.All(v => v.Value is string || v.Value == null)) {
+ tupleElementNames = values.SelectArray(v => (string)v.Value);
+ }
+ }
+ }
+ }
+ }
+ if (hasDynamicAttribute || useTupleTypes) {
+ return inputType.AcceptVisitor(new ApplyAttributeTypeVisitor(
+ compilation, hasDynamicAttribute, dynamicAttributeData, useTupleTypes, tupleElementNames
+ ));
+ } else {
+ return inputType;
+ }
+ }
+
+ readonly ICompilation compilation;
+ readonly bool hasDynamicAttribute;
+ readonly bool[] dynamicAttributeData;
+ readonly bool useTupleTypes;
+ readonly string[] tupleElementNames;
+ int dynamicTypeIndex = 0;
+ int tupleTypeIndex = 0;
+
+ public ApplyAttributeTypeVisitor(ICompilation compilation, bool hasDynamicAttribute, bool[] dynamicAttributeData, bool useTupleTypes, string[] tupleElementNames)
+ {
+ this.compilation = compilation ?? throw new ArgumentNullException(nameof(compilation));
+ this.hasDynamicAttribute = hasDynamicAttribute;
+ this.dynamicAttributeData = dynamicAttributeData;
+ this.useTupleTypes = useTupleTypes;
+ this.tupleElementNames = tupleElementNames;
+ }
+
+ public override IType VisitPointerType(PointerType type)
+ {
+ dynamicTypeIndex++;
+ return base.VisitPointerType(type);
+ }
+
+ public override IType VisitArrayType(ArrayType type)
+ {
+ dynamicTypeIndex++;
+ return base.VisitArrayType(type);
+ }
+
+ public override IType VisitByReferenceType(ByReferenceType type)
+ {
+ dynamicTypeIndex++;
+ return base.VisitByReferenceType(type);
+ }
+
+ public override IType VisitParameterizedType(ParameterizedType type)
+ {
+ if (useTupleTypes && TupleType.IsTupleCompatible(type, out int tupleCardinality)) {
+ if (tupleCardinality > 1) {
+ var valueTupleAssembly = type.GetDefinition()?.ParentAssembly;
+ ImmutableArray elementNames = default;
+ if (tupleElementNames != null && tupleTypeIndex < tupleElementNames.Length) {
+ string[] extractedValues = new string[tupleCardinality];
+ Array.Copy(tupleElementNames, tupleTypeIndex, extractedValues, 0,
+ Math.Min(tupleCardinality, tupleElementNames.Length - tupleTypeIndex));
+ elementNames = ImmutableArray.CreateRange(extractedValues);
+ }
+ tupleTypeIndex += tupleCardinality;
+ var elementTypes = ImmutableArray.CreateBuilder(tupleCardinality);
+ do {
+ int normalArgCount = Math.Min(type.TypeArguments.Count, TupleType.RestPosition - 1);
+ for (int i = 0; i < normalArgCount; i++) {
+ dynamicTypeIndex++;
+ elementTypes.Add(type.TypeArguments[i].AcceptVisitor(this));
+ }
+ if (type.TypeArguments.Count == TupleType.RestPosition) {
+ type = type.TypeArguments.Last() as ParameterizedType;
+ dynamicTypeIndex++;
+ if (type != null && TupleType.IsTupleCompatible(type, out int nestedCardinality)) {
+ tupleTypeIndex += nestedCardinality;
+ } else {
+ Debug.Fail("TRest should be another value tuple");
+ type = null;
+ }
+ } else {
+ type = null;
+ }
+ } while (type != null);
+ Debug.Assert(elementTypes.Count == tupleCardinality);
+ return new TupleType(
+ compilation,
+ elementTypes.ToImmutable(),
+ elementNames,
+ valueTupleAssembly
+ );
+ } else {
+ // C# doesn't have syntax for tuples of cardinality <= 1
+ tupleTypeIndex += tupleCardinality;
+ }
+ }
+ // Visit generic type and type arguments.
+ // Like base implementation, except that it increments typeIndex.
+ var genericType = type.GenericType.AcceptVisitor(this);
+ bool changed = type.GenericType != genericType;
+ var arguments = new IType[type.TypeArguments.Count];
+ for (int i = 0; i < type.TypeArguments.Count; i++) {
+ dynamicTypeIndex++;
+ arguments[i] = type.TypeArguments[i].AcceptVisitor(this);
+ changed = changed || arguments[i] != type.TypeArguments[i];
+ }
+ if (!changed)
+ return type;
+ return new ParameterizedType(genericType, arguments);
+ }
+
+ public override IType VisitTypeDefinition(ITypeDefinition type)
+ {
+ if (type.KnownTypeCode == KnownTypeCode.Object && hasDynamicAttribute) {
+ if (dynamicAttributeData == null || dynamicTypeIndex >= dynamicAttributeData.Length)
+ return SpecialType.Dynamic;
+ if (dynamicAttributeData[dynamicTypeIndex])
+ return SpecialType.Dynamic;
+ return type;
+ }
+ return type;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
index fe65b2c92..09aa9b294 100644
--- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
@@ -7,6 +7,7 @@ using ICSharpCode.Decompiler.Util;
using static ICSharpCode.Decompiler.Metadata.MetadataExtensions;
using System.Diagnostics;
+using System.Collections.Immutable;
namespace ICSharpCode.Decompiler.TypeSystem
{
@@ -21,12 +22,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
readonly Metadata.PEFile moduleDefinition;
readonly ICompilation compilation;
readonly ITypeResolveContext context;
-
- ///
- /// CecilLoader used for converting cecil type references to ITypeReference.
- /// May only be accessed within lock(typeReferenceCecilLoader).
- ///
- readonly MetadataLoader typeReferenceCecilLoader;
+ readonly TypeAttributeOptions typeAttributeOptions;
Dictionary fieldLookupCache = new Dictionary();
Dictionary propertyLookupCache = new Dictionary();
@@ -44,19 +40,18 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (settings == null)
throw new ArgumentNullException(nameof(settings));
this.moduleDefinition = moduleDefinition;
- typeReferenceCecilLoader = new MetadataLoader {
- UseDynamicType = settings.Dynamic,
- UseTupleTypes = settings.TupleTypes,
- };
- MetadataLoader cecilLoader = new MetadataLoader {
+ typeAttributeOptions = TypeAttributeOptions.None;
+ if (settings.Dynamic)
+ typeAttributeOptions |= TypeAttributeOptions.Dynamic;
+ if (settings.TupleTypes)
+ typeAttributeOptions |= TypeAttributeOptions.Tuple;
+ MetadataLoader loader = new MetadataLoader {
IncludeInternalMembers = true,
- LazyLoad = true,
ShortenInterfaceImplNames = false,
UseDynamicType = settings.Dynamic,
UseTupleTypes = settings.TupleTypes,
};
- typeReferenceCecilLoader.SetCurrentModule(moduleDefinition);
- IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition);
+ IUnresolvedAssembly mainAssembly = loader.LoadModule(moduleDefinition);
// Load referenced assemblies and type-forwarder references.
// This is necessary to make .NET Core/PCL binaries work better.
var referencedAssemblies = new List();
@@ -68,7 +63,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
continue;
var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef);
if (asm != null) {
- IUnresolvedAssembly unresolvedAsm = cecilLoader.LoadModule(asm);
+ IUnresolvedAssembly unresolvedAsm = loader.LoadModule(asm);
referencedAssemblies.Add(unresolvedAsm);
moduleLookup.Add(unresolvedAsm, asm);
var metadata = asm.Metadata;
@@ -111,12 +106,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
return null;
return file;
}
-
- public IType ResolveFromSignature(ITypeReference typeReference)
- {
- return typeReference.Resolve(context);
- }
-
+
public IMember ResolveAsMember(SRM.EntityHandle memberReference)
{
switch (memberReference.Kind) {
@@ -147,14 +137,37 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region Resolve Type
public IType ResolveAsType(SRM.EntityHandle typeReference)
{
- if (typeReference.IsNil)
- return SpecialType.UnknownType;
- ITypeReference typeRef;
- lock (typeReferenceCecilLoader)
- typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference);
- return typeRef.Resolve(context);
+ return MetadataTypeReference.Resolve(
+ typeReference,
+ moduleDefinition.Metadata,
+ context,
+ typeAttributes: null,
+ typeAttributeOptions
+ );
}
#endregion
+
+ public SRM.MethodSignature DecodeMethodSignature(SRM.StandaloneSignatureHandle handle)
+ {
+ var standaloneSignature = moduleDefinition.Metadata.GetStandaloneSignature(handle);
+ if (standaloneSignature.GetKind() != SRM.StandaloneSignatureKind.Method)
+ throw new InvalidOperationException("Expected Method signature");
+ return standaloneSignature.DecodeMethodSignature(
+ new TypeProvider(compilation.MainAssembly),
+ context
+ );
+ }
+
+ public ImmutableArray DecodeLocalSignature(SRM.StandaloneSignatureHandle handle)
+ {
+ var standaloneSignature = moduleDefinition.Metadata.GetStandaloneSignature(handle);
+ if (standaloneSignature.GetKind() != SRM.StandaloneSignatureKind.LocalVariables)
+ throw new InvalidOperationException("Expected Local signature");
+ return standaloneSignature.DecodeLocalSignature(
+ new TypeProvider(compilation.MainAssembly),
+ context
+ );
+ }
#region Resolve Field
public IField ResolveAsField(SRM.EntityHandle fieldReference)
@@ -171,9 +184,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
ITypeReference returnType;
switch (fieldReference.Kind) {
case SRM.HandleKind.FieldDefinition:
- var fieldDef = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)fieldReference);
+ var fieldDefHandle = (SRM.FieldDefinitionHandle)fieldReference;
+ var fieldDef = metadata.GetFieldDefinition(fieldDefHandle);
declaringType = ResolveAsType(fieldDef.GetDeclaringType());
- returnType = DynamicTypeReference.Create(fieldDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default), fieldDef.GetCustomAttributes(), metadata);
+ returnType = new FieldTypeReference(fieldDefHandle, metadata, typeAttributeOptions);
var declaringTypeDefinition = declaringType.GetDefinition();
if (declaringTypeDefinition == null)
field = CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType);
@@ -412,14 +426,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
m.ReturnType = signature.ReturnType;
m.IsStatic = !signature.Header.IsInstance;
- lock (typeReferenceCecilLoader) {
- var metadata = moduleDefinition.Metadata;
- for (int i = 0; i < signature.GenericParameterCount; i++) {
- m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, i, ""));
- }
- for (int i = 0; i < signature.ParameterTypes.Length; i++) {
- m.Parameters.Add(new DefaultUnresolvedParameter(signature.ParameterTypes[i], ""));
- }
+ var metadata = moduleDefinition.Metadata;
+ for (int i = 0; i < signature.GenericParameterCount; i++) {
+ m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, i, ""));
+ }
+ for (int i = 0; i < signature.ParameterTypes.Length; i++) {
+ m.Parameters.Add(new DefaultUnresolvedParameter(signature.ParameterTypes[i], ""));
}
return new ResolvedFakeMethod(m, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType);
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs b/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs
index ab259a7e8..30975b443 100644
--- a/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs
@@ -122,6 +122,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
///
/// Gets the type definition from the metadata token, or null if not found.
///
- ITypeDefinition ResolveTypeDefToken(EntityHandle token);
+ ITypeDefinition ResolveTypeDefToken(TypeDefinitionHandle token);
}
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs
index f1865c4f5..714a500ce 100644
--- a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs
@@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+using System.Collections.Immutable;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
@@ -28,7 +29,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
ICompilation Compilation { get; }
- IType ResolveFromSignature(ITypeReference typeReference);
+ MethodSignature DecodeMethodSignature(StandaloneSignatureHandle standaloneSignatureHandle);
+ ImmutableArray DecodeLocalSignature(StandaloneSignatureHandle standaloneSignatureHandle);
+
IType ResolveAsType(EntityHandle typeReference);
IField ResolveAsField(EntityHandle fieldReference);
IMethod ResolveAsMethod(EntityHandle methodReference);
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
index 12ae00679..151f75da0 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
@@ -297,10 +297,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return lookup;
}
- internal IUnresolvedTypeDefinition GetTypeDefByToken(System.Reflection.Metadata.EntityHandle token)
+ internal IUnresolvedTypeDefinition GetTypeDefByToken(System.Reflection.Metadata.TypeDefinitionHandle token)
{
- if (token.Kind != System.Reflection.Metadata.HandleKind.TypeDefinition)
- throw new ArgumentException("Token must be typedef-token.");
var lookup = LazyInit.VolatileRead(ref allTypesByMetadata);
if (lookup == null) {
lookup = LazyInit.GetOrSet(ref allTypesByMetadata, BuildMetadataLookup());
@@ -445,7 +443,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
- public ITypeDefinition ResolveTypeDefToken(System.Reflection.Metadata.EntityHandle token)
+ public ITypeDefinition ResolveTypeDefToken(System.Reflection.Metadata.TypeDefinitionHandle token)
{
var td = unresolvedAssembly.GetTypeDefByToken(token);
if (td != null)
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeReference.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeReference.cs
new file mode 100644
index 000000000..0af15894a
--- /dev/null
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeReference.cs
@@ -0,0 +1,259 @@
+// Copyright (c) 2018 Daniel Grunwald
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using SRM = System.Reflection.Metadata;
+using System.Diagnostics;
+using System;
+using ICSharpCode.Decompiler.Util;
+using System.Linq;
+using System.Collections.Immutable;
+
+namespace ICSharpCode.Decompiler.TypeSystem.Implementation
+{
+ sealed class MetadataTypeReference : ITypeReference
+ {
+ readonly SRM.EntityHandle type;
+ readonly SRM.MetadataReader metadata;
+ readonly SRM.CustomAttributeHandleCollection? typeAttributes;
+ readonly TypeAttributeOptions attributeOptions;
+
+ public MetadataTypeReference(SRM.EntityHandle type,
+ SRM.MetadataReader metadata,
+ SRM.CustomAttributeHandleCollection? typeAttributes = null,
+ TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
+ {
+ this.type = type;
+ this.metadata = metadata;
+ this.typeAttributes = typeAttributes;
+ this.attributeOptions = attributeOptions;
+ }
+
+ public IType Resolve(ITypeResolveContext context)
+ {
+ return Resolve(type, metadata, context,
+ typeAttributes, attributeOptions);
+ }
+
+ public static IType Resolve(SRM.EntityHandle type,
+ SRM.MetadataReader metadata,
+ ITypeResolveContext context,
+ SRM.CustomAttributeHandleCollection? typeAttributes = null,
+ TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
+ {
+ if (type.IsNil)
+ return SpecialType.UnknownType;
+ var tp = new TypeProvider(context.CurrentAssembly);
+ IType ty;
+ switch (type.Kind) {
+ case SRM.HandleKind.TypeDefinition:
+ ty = tp.GetTypeFromDefinition(metadata, (SRM.TypeDefinitionHandle)type, 0);
+ break;
+ case SRM.HandleKind.TypeReference:
+ ty = tp.GetTypeFromReference(metadata, (SRM.TypeReferenceHandle)type, 0);
+ break;
+ case SRM.HandleKind.TypeSpecification:
+ var typeSpec = metadata.GetTypeSpecification((SRM.TypeSpecificationHandle)type);
+ ty = typeSpec.DecodeSignature(tp, context);
+ break;
+ default:
+ Debug.Fail("Not a type handle");
+ ty = SpecialType.UnknownType;
+ break;
+ }
+ ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation,
+ typeAttributes, metadata, attributeOptions);
+ return ty;
+ }
+ }
+
+ sealed class FieldTypeReference : ITypeReference
+ {
+ readonly SRM.FieldDefinitionHandle fieldHandle;
+ readonly SRM.MetadataReader metadata;
+ readonly TypeAttributeOptions attributeOptions;
+
+ public FieldTypeReference(SRM.FieldDefinitionHandle fieldHandle,
+ SRM.MetadataReader metadata,
+ TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
+ {
+ this.fieldHandle = fieldHandle;
+ this.metadata = metadata;
+ this.attributeOptions = attributeOptions;
+ }
+
+ IType ITypeReference.Resolve(ITypeResolveContext context)
+ {
+ return Resolve(fieldHandle, metadata, context, attributeOptions);
+ }
+
+ public static IType Resolve(SRM.FieldDefinitionHandle fieldHandle,
+ SRM.MetadataReader metadata,
+ ITypeResolveContext context,
+ TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
+ {
+ var fieldDef = metadata.GetFieldDefinition(fieldHandle);
+ IType ty = fieldDef.DecodeSignature(new TypeProvider(context.CurrentAssembly), context);
+ ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation,
+ fieldDef.GetCustomAttributes(), metadata, attributeOptions);
+ return ty;
+ }
+ }
+
+ ///
+ /// Represents an unresolved method signature.
+ ///
+ sealed class UnresolvedMethodSignature
+ {
+ readonly SRM.EntityHandle handle;
+ readonly SRM.MetadataReader metadata;
+ readonly TypeAttributeOptions attributeOptions;
+
+ public UnresolvedMethodSignature(SRM.MethodDefinitionHandle handle, SRM.MetadataReader metadata,
+ TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
+ {
+ this.handle = handle;
+ this.metadata = metadata;
+ this.attributeOptions = attributeOptions;
+ }
+
+ public UnresolvedMethodSignature(SRM.PropertyDefinitionHandle handle, SRM.MetadataReader metadata,
+ TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
+ {
+ this.handle = handle;
+ this.metadata = metadata;
+ this.attributeOptions = attributeOptions;
+ }
+
+ public SRM.MethodSignature Resolve(ITypeResolveContext context)
+ {
+ return (SRM.MethodSignature)context.Compilation.CacheManager.GetOrAddShared(
+ this, key => {
+ Debug.Assert(key == this);
+ switch (handle.Kind) {
+ case SRM.HandleKind.MethodDefinition:
+ return GetSignature(
+ metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)handle),
+ metadata, context
+ );
+ case SRM.HandleKind.PropertyDefinition:
+ return GetSignature(
+ metadata.GetPropertyDefinition((SRM.PropertyDefinitionHandle)handle),
+ metadata, context
+ );
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+ );
+ }
+
+ public static SRM.MethodSignature GetSignature(SRM.MethodDefinition methodDef,
+ SRM.MetadataReader metadata, ITypeResolveContext context,
+ TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
+ {
+ var typeProvider = new TypeProvider(context.CurrentAssembly);
+ var signature = methodDef.DecodeSignature(typeProvider, context);
+ return ApplyAttributes(signature, methodDef.GetParameters(), context.Compilation, metadata, attributeOptions);
+ }
+
+ public static SRM.MethodSignature GetSignature(SRM.PropertyDefinition propertyDef,
+ SRM.MetadataReader metadata, ITypeResolveContext context,
+ TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
+ {
+ var typeProvider = new TypeProvider(context.CurrentAssembly);
+ var signature = propertyDef.DecodeSignature(typeProvider, context);
+ var accessors = propertyDef.GetAccessors();
+ SRM.ParameterHandleCollection? parameterHandles = null;
+ if (!accessors.Getter.IsNil) {
+ var getter = metadata.GetMethodDefinition(accessors.Getter);
+ parameterHandles = getter.GetParameters();
+ } else {
+ if (!accessors.Setter.IsNil) {
+ var setter = metadata.GetMethodDefinition(accessors.Setter);
+ parameterHandles = setter.GetParameters();
+ }
+ }
+ return ApplyAttributes(signature, parameterHandles, context.Compilation, metadata, attributeOptions);
+ }
+
+ static SRM.MethodSignature ApplyAttributes(SRM.MethodSignature signature, SRM.ParameterHandleCollection? parameterHandles, ICompilation compilation, SRM.MetadataReader metadata, TypeAttributeOptions attributeOptions)
+ {
+ SRM.CustomAttributeHandleCollection? returnTypeAttributes = null;
+ var parameterAttributes = new SRM.CustomAttributeHandleCollection?[signature.ParameterTypes.Length];
+ if (parameterHandles != null) {
+ foreach (var parameterHandle in parameterHandles) {
+ var par = metadata.GetParameter(parameterHandle);
+ if (par.SequenceNumber == 0) {
+ returnTypeAttributes = par.GetCustomAttributes();
+ } else if (par.SequenceNumber <= parameterAttributes.Length) {
+ parameterAttributes[par.SequenceNumber - 1] = par.GetCustomAttributes();
+ }
+ }
+ }
+ IType returnType = ApplyAttributeTypeVisitor.ApplyAttributesToType(
+ signature.ReturnType, compilation, returnTypeAttributes, metadata, attributeOptions
+ );
+ var parameterTypes = signature.ParameterTypes.SelectWithIndex(
+ (i, p) => ApplyAttributeTypeVisitor.ApplyAttributesToType(
+ p, compilation, parameterAttributes[i], metadata, attributeOptions
+ )
+ ).ToImmutableArray();
+ return new SRM.MethodSignature(
+ signature.Header, returnType,
+ signature.RequiredParameterCount, signature.GenericParameterCount,
+ parameterTypes
+ );
+ }
+ }
+
+ sealed class SignatureParameterTypeReference : ITypeReference
+ {
+ readonly UnresolvedMethodSignature unresolvedSig;
+ readonly int index;
+
+ public SignatureParameterTypeReference(UnresolvedMethodSignature unresolvedSig, int index)
+ {
+ this.unresolvedSig = unresolvedSig;
+ this.index = index;
+ }
+
+ public IType Resolve(ITypeResolveContext context)
+ {
+ var sig = unresolvedSig.Resolve(context);
+ if (index < sig.ParameterTypes.Length)
+ return sig.ParameterTypes[index];
+ else
+ return SpecialType.UnknownType;
+ }
+ }
+
+ sealed class SignatureReturnTypeReference : ITypeReference
+ {
+ readonly UnresolvedMethodSignature unresolvedSig;
+
+ public SignatureReturnTypeReference(UnresolvedMethodSignature unresolvedSig)
+ {
+ this.unresolvedSig = unresolvedSig;
+ }
+
+ public IType Resolve(ITypeResolveContext context)
+ {
+ return unresolvedSig.Resolve(context).ReturnType;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
index 4479ce47b..55d0df833 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
@@ -23,6 +23,7 @@ using SRM = System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util;
using System.Collections.Generic;
+using System.Diagnostics;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
@@ -81,120 +82,37 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return ElementType.Resolve(context);
}
}
-
- public sealed class DynamicTypeReference : TypeVisitor, ITypeReference
+
+ sealed class TypeDefTokenTypeReference : ITypeReference
{
- readonly ITypeReference reference;
- readonly bool[] dynamicInfo;
- int typeIndex;
-
- static readonly ITypeResolveContext minimalCorlibContext = new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation());
-
- public static ITypeReference Create(ITypeReference reference, SRM.CustomAttributeHandleCollection? customAttributes, SRM.MetadataReader metadata)
- {
- if (HasDynamicAttribute(customAttributes, metadata, out var dynamicInfo))
- return new DynamicTypeReference(reference, dynamicInfo);
- return reference;
- }
-
- public static bool HasDynamicAttribute(SRM.CustomAttributeHandleCollection? attributes, SRM.MetadataReader metadata, out bool[] mapping)
- {
- mapping = null;
- if (attributes == null)
- return false;
-
- foreach (var handle in attributes) {
- var a = metadata.GetCustomAttribute(handle);
- var type = a.GetAttributeType(metadata);
- if (type.GetFullTypeName(metadata).ToString() == "System.Runtime.CompilerServices.DynamicAttribute") {
- var ctor = a.DecodeValue(new TypeSystemAttributeTypeProvider(minimalCorlibContext));
- if (ctor.FixedArguments.Length == 1) {
- var arg = ctor.FixedArguments[0];
- if (arg.Type.ReflectionName == "System.Boolean[]" && arg.Value is ImmutableArray> values) {
- mapping = values.SelectArray(v => (bool)v.Value);
- return true;
- }
- }
- return true;
- }
- }
- return false;
- }
+ readonly SRM.TypeDefinitionHandle token;
- DynamicTypeReference(ITypeReference reference, bool[] dynamicInfo)
+ public TypeDefTokenTypeReference(SRM.TypeDefinitionHandle token)
{
- this.reference = reference;
- this.dynamicInfo = dynamicInfo;
+ this.token = token;
}
public IType Resolve(ITypeResolveContext context)
{
- return reference.Resolve(context).AcceptVisitor(this);
- }
-
- public override IType VisitPointerType(PointerType type)
- {
- typeIndex++;
- return base.VisitPointerType(type);
- }
-
- public override IType VisitArrayType(ArrayType type)
- {
- typeIndex++;
- return base.VisitArrayType(type);
- }
-
- public override IType VisitByReferenceType(ByReferenceType type)
- {
- typeIndex++;
- return base.VisitByReferenceType(type);
- }
-
- public override IType VisitParameterizedType(ParameterizedType type)
- {
- var genericType = type.GenericType.AcceptVisitor(this);
- bool changed = type.GenericType != genericType;
- var arguments = new IType[type.TypeArguments.Count];
- for (int i = 0; i < type.TypeArguments.Count; i++) {
- typeIndex++;
- arguments[i] = type.TypeArguments[i].AcceptVisitor(this);
- changed = changed || arguments[i] != type.TypeArguments[i];
- }
- if (!changed)
- return type;
- return new ParameterizedType(genericType, arguments);
- }
-
- public override IType VisitTypeDefinition(ITypeDefinition type)
- {
- if (type.KnownTypeCode == KnownTypeCode.Object) {
- if (dynamicInfo == null || typeIndex >= dynamicInfo.Length)
- return SpecialType.Dynamic;
- if (dynamicInfo[typeIndex])
- return SpecialType.Dynamic;
- return type;
- }
- return type;
+ ITypeDefinition td = context.CurrentAssembly.ResolveTypeDefToken(token);
+ if (td != null)
+ return td;
+ return SpecialType.UnknownType;
}
}
- sealed class TypeDefTokenTypeReference : ITypeReference
+ sealed class TypeSpecTypeReference : ITypeReference
{
- readonly SRM.EntityHandle token;
+ readonly SRM.TypeSpecification typeSpec;
- public TypeDefTokenTypeReference(SRM.EntityHandle token)
+ public TypeSpecTypeReference(SRM.TypeSpecification typeSpec)
{
- if (token.Kind != SRM.HandleKind.TypeDefinition)
- throw new ArgumentException(nameof(token), "must be TypeDef token");
- this.token = token;
+ this.typeSpec = typeSpec;
}
public IType Resolve(ITypeResolveContext context)
{
- ITypeDefinition td = context.CurrentAssembly.ResolveTypeDefToken(token);
- if (td != null)
- return td;
- return SpecialType.UnknownType;
+ return typeSpec.DecodeSignature(new TypeProvider(context.CurrentAssembly), context);
}
}
@@ -279,60 +197,4 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
.DecodeSignature(this, default);
}
}
-
- public class TypeSystemAttributeTypeProvider : SRM.ICustomAttributeTypeProvider
- {
- readonly ITypeResolveContext context;
-
- public static TypeSystemAttributeTypeProvider CreateDefault() => new TypeSystemAttributeTypeProvider(new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation()));
-
- public TypeSystemAttributeTypeProvider(ITypeResolveContext context)
- {
- this.context = context;
- }
-
- public IType GetPrimitiveType(SRM.PrimitiveTypeCode typeCode)
- {
- return context.Compilation.FindType(typeCode.ToKnownTypeCode());
- }
-
- public IType GetSystemType()
- {
- return context.Compilation.FindType(KnownTypeCode.Type);
- }
-
- public IType GetSZArrayType(IType elementType)
- {
- return new ArrayType(context.Compilation, elementType);
- }
-
- public IType GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
- {
- var type = reader.GetTypeDefinition(handle);
- return new DefaultUnresolvedTypeDefinition(type.GetFullTypeName(reader).ToString()).Resolve(context);
- }
-
- public IType GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)
- {
- return new DefaultUnresolvedTypeDefinition(handle.GetFullTypeName(reader).ToString()).Resolve(context);
- }
-
- public IType GetTypeFromSerializedName(string name)
- {
- return new GetClassTypeReference(new FullTypeName(name)).Resolve(context);
- }
-
- public SRM.PrimitiveTypeCode GetUnderlyingEnumType(IType type)
- {
- var def = type.GetEnumUnderlyingType().GetDefinition();
- if (def == null)
- throw new InvalidOperationException();
- return def.KnownTypeCode.ToPrimtiveTypeCode();
- }
-
- public bool IsSystemType(IType type)
- {
- return type.IsKnownType(KnownTypeCode.Type);
- }
- }
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs
index e4b5441a3..4c7deadc5 100644
--- a/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs
@@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
@@ -91,19 +92,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// for every delay-loading operation.
/// If you access the Cecil objects directly in your application, you may need to take the same lock.
///
- public bool LazyLoad { get; set; }
-
- ///
- /// This delegate gets executed whenever an entity was loaded.
- ///
- ///
- /// This callback may be to build a dictionary that maps between
- /// entities and cecil objects.
- /// Warning: if delay-loading is used and the type system is accessed by multiple threads,
- /// the callback may be invoked concurrently on multiple threads.
- ///
- public Action OnEntityLoaded { get; set; }
-
+ public bool LazyLoad { get; private set; } = true;
+
bool shortenInterfaceImplNames = true;
///
@@ -140,8 +130,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
// use a shared typeSystemTranslationTable
this.IncludeInternalMembers = loader.IncludeInternalMembers;
this.LazyLoad = loader.LazyLoad;
- this.OnEntityLoaded = loader.OnEntityLoaded;
this.ShortenInterfaceImplNames = loader.ShortenInterfaceImplNames;
+ this.UseDynamicType = loader.UseDynamicType;
+ this.UseTupleTypes = loader.UseTupleTypes;
this.currentModule = loader.currentModule;
this.currentMetadata = loader.currentMetadata;
this.currentAssembly = loader.currentAssembly;
@@ -222,7 +213,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (this.LazyLoad) {
var t = new LazySRMTypeDefinition(cecilLoaderCloneForLazyLoading, module, h);
currentAssembly.AddTypeDefinition(t);
- RegisterCecilObject(t);
} else {
var t = CreateTopLevelTypeDefinition(h, td);
cecilTypeDefs.Add(h);
@@ -295,32 +285,24 @@ namespace ICSharpCode.Decompiler.TypeSystem
///
/// Reads a type reference.
///
- /// The Cecil type reference that should be converted into
+ /// The metadata type token that should be converted into
/// a type system type reference.
- /// Attributes associated with the Cecil type reference.
- /// This is used to support the 'dynamic' type.
+ /// Attributes associated with the type.
+ /// This is used to support the 'dynamic' type, and for tuple element names.
+ ///
public ITypeReference ReadTypeReference(EntityHandle type, CustomAttributeHandleCollection? typeAttributes = null)
{
- ITypeReference CreateTypeReference(TypeReferenceHandle handle)
- {
- var t = currentMetadata.GetTypeReference(handle);
- var asmref = handle.GetDeclaringAssembly(currentMetadata);
- if (asmref.IsNil)
- return new GetClassTypeReference(handle.GetFullTypeName(currentMetadata), DefaultAssemblyReference.CurrentAssembly);
- var asm = currentMetadata.GetAssemblyReference(asmref);
- return new GetClassTypeReference(handle.GetFullTypeName(currentMetadata), new DefaultAssemblyReference(currentMetadata.GetString(asm.Name)));
- }
-
- switch (type.Kind) {
- case HandleKind.TypeSpecification:
- return DynamicTypeReference.Create(currentMetadata.GetTypeSpecification((TypeSpecificationHandle)type)
- .DecodeSignature(TypeReferenceSignatureDecoder.Instance, default), typeAttributes, currentMetadata);
- case HandleKind.TypeReference:
- return CreateTypeReference((TypeReferenceHandle)type);
- case HandleKind.TypeDefinition:
- return new TypeDefTokenTypeReference(type);
- default:
- throw new NotSupportedException();
+ return new MetadataTypeReference(type, currentMetadata, typeAttributes, TypeAttributeOptions);
+ }
+
+ private TypeAttributeOptions TypeAttributeOptions {
+ get {
+ TypeAttributeOptions options = TypeAttributeOptions.None;
+ if (UseDynamicType)
+ options |= TypeAttributeOptions.Dynamic;
+ if (UseTupleTypes)
+ options |= TypeAttributeOptions.Tuple;
+ return options;
}
}
#endregion
@@ -808,7 +790,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
InitMembers(typeDefinition, td, td.Members);
td.ApplyInterningProvider(interningProvider);
td.Freeze();
- RegisterCecilObject(td);
}
void InitBaseTypes(TypeDefinitionHandle handle, IList baseTypes)
@@ -986,10 +967,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
foreach (var h in typeDefinition.GetCustomAttributes()) {
var a = reader.GetCustomAttribute(h);
- var type = a.GetAttributeType(reader).GetFullTypeName(reader);
- if (type.ToString() != typeof(System.Reflection.DefaultMemberAttribute).FullName)
+ var type = a.GetAttributeType(reader);
+ if (!type.IsTopLevelType(reader, "System.Reflection", "DefaultMemberAttribute"))
continue;
- var value = a.DecodeValue(new TypeSystemAttributeTypeProvider(minimalCorlibContext));
+ var value = a.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider);
if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is string name)
return name;
}
@@ -998,14 +979,14 @@ namespace ICSharpCode.Decompiler.TypeSystem
static bool IsAccessor(MethodSemanticsAttributes semantics)
{
- return semantics > (MethodSemanticsAttributes)0 && semantics != MethodSemanticsAttributes.Other;
+ return semantics != 0 && semantics != MethodSemanticsAttributes.Other;
}
#endregion
#region Lazy-Loaded Type Definition
sealed class LazySRMTypeDefinition : AbstractUnresolvedEntity, IUnresolvedTypeDefinition
{
- // loader + cecilTypeDef, used for lazy-loading; and set to null after lazy loading is complete
+ // loader + cecilTypeDef, used for lazy-loading
readonly MetadataLoader loader;
readonly Metadata.PEFile module;
readonly MetadataReader metadata;
@@ -1224,31 +1205,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
AddAttributes(method, m.Attributes, m.ReturnTypeAttributes);
TranslateModifiers(handle, m);
- var declaringType = currentMetadata.GetTypeDefinition(method.GetDeclaringType());
- var reader = currentMetadata.GetBlobReader(method.Signature);
- var signature = method.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
-
- var parameters = method.GetParameters().ToArray();
- m.ReturnType = HandleReturnType(parameters.FirstOrDefault(), signature.ReturnType);
-
- int j = 0;
- if (signature.RequiredParameterCount > parameters.Length) {
- foreach (var parameterType in signature.ParameterTypes) {
- m.Parameters.Add(new DefaultUnresolvedParameter(DynamicTypeReference.Create(parameterType, null, currentMetadata), string.Empty));
- }
- } else {
- foreach (var p in parameters) {
- var par = currentMetadata.GetParameter(p);
- if (par.SequenceNumber > 0) {
- m.Parameters.Add(ReadParameter(par, signature.ParameterTypes[j]));
- j++;
- }
- }
- }
-
- if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
- m.Parameters.Add(new DefaultUnresolvedParameter(SpecialType.ArgList, string.Empty));
- }
+ var signature = method.DecodeSignature(TypeCodeProvider.Instance, default);
+ var unresolvedSig = new UnresolvedMethodSignature(handle, currentMetadata, TypeAttributeOptions);
+ var (retType, parameters) = TranslateSignature(signature, unresolvedSig, method.GetParameters());
+ m.ReturnType = retType;
+ m.Parameters.AddRange(parameters);
// mark as extension method if the attribute is set
if ((method.Attributes & MethodAttributes.Static) == MethodAttributes.Static && HasExtensionAttribute(currentMetadata, method.GetCustomAttributes())) {
@@ -1297,24 +1258,79 @@ namespace ICSharpCode.Decompiler.TypeSystem
return m;
}
- ITypeReference HandleReturnType(ParameterHandle parameterHandle, ITypeReference returnType)
+ private (ITypeReference, List) TranslateSignature(
+ MethodSignature signature,
+ UnresolvedMethodSignature unresolvedSig, ParameterHandleCollection? parameterHandleCollection)
{
- CustomAttributeHandleCollection? attributes = null;
- if (!parameterHandle.IsNil) {
- var par = currentMetadata.GetParameter(parameterHandle);
- if (par.SequenceNumber == 0) {
- attributes = par.GetCustomAttributes();
+ var returnType = new SignatureReturnTypeReference(unresolvedSig);
+ var parameters = new List();
+ int i = 0;
+ if (parameterHandleCollection != null) {
+ foreach (var p in parameterHandleCollection) {
+ var par = currentMetadata.GetParameter(p);
+ if (par.SequenceNumber > 0 && i < signature.RequiredParameterCount) {
+ Debug.Assert(par.SequenceNumber - 1 == i);
+ var paramTypeRef = new SignatureParameterTypeReference(unresolvedSig, i);
+ parameters.Add(ReadParameter(par, paramTypeRef, signature.ParameterTypes[i]));
+ i++;
+ }
}
}
- return DynamicTypeReference.Create(returnType, attributes, currentMetadata);
+ Debug.Assert(i == parameters.Count);
+ while (i < signature.RequiredParameterCount) {
+ parameters.Add(new DefaultUnresolvedParameter(
+ new SignatureParameterTypeReference(unresolvedSig, i),
+ name: string.Empty
+ ));
+ i++;
+ }
+
+ if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
+ parameters.Add(new DefaultUnresolvedParameter(SpecialType.ArgList, string.Empty));
+ }
+ return (returnType, parameters);
}
- static bool HasExtensionAttribute(MetadataReader currentModule, CustomAttributeHandleCollection attributes)
+ ///
+ /// Allows decoding a signature without decoding the types,
+ /// e.g. for counting the number of parameters in a method signature.
+ ///
+ sealed class TypeCodeProvider : ISignatureTypeProvider
+ {
+ public static readonly TypeCodeProvider Instance = new TypeCodeProvider();
+
+ public SignatureTypeCode GetArrayType(SignatureTypeCode elementType, ArrayShape shape) => SignatureTypeCode.Array;
+ public SignatureTypeCode GetByReferenceType(SignatureTypeCode elementType) => SignatureTypeCode.ByReference;
+ public SignatureTypeCode GetFunctionPointerType(MethodSignature signature) => SignatureTypeCode.FunctionPointer;
+ public SignatureTypeCode GetGenericInstantiation(SignatureTypeCode genericType, ImmutableArray typeArguments) => SignatureTypeCode.GenericTypeInstance;
+ public SignatureTypeCode GetGenericMethodParameter(Unit genericContext, int index) => SignatureTypeCode.GenericMethodParameter;
+ public SignatureTypeCode GetGenericTypeParameter(Unit genericContext, int index) => SignatureTypeCode.GenericTypeParameter;
+
+ public SignatureTypeCode GetModifiedType(SignatureTypeCode modifier, SignatureTypeCode unmodifiedType, bool isRequired)
+ {
+ // skip modifiers
+ return unmodifiedType;
+ }
+
+ public SignatureTypeCode GetPinnedType(SignatureTypeCode elementType) => SignatureTypeCode.Pinned;
+ public SignatureTypeCode GetPointerType(SignatureTypeCode elementType) => SignatureTypeCode.Pointer;
+ public SignatureTypeCode GetPrimitiveType(PrimitiveTypeCode typeCode) => (SignatureTypeCode)typeCode;
+ public SignatureTypeCode GetSZArrayType(SignatureTypeCode elementType) => SignatureTypeCode.SZArray;
+
+ public SignatureTypeCode GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
+ => SignatureTypeCode.TypeHandle;
+ public SignatureTypeCode GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
+ => SignatureTypeCode.TypeHandle;
+ public SignatureTypeCode GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
+ => SignatureTypeCode.TypeHandle;
+ }
+
+ static bool HasExtensionAttribute(MetadataReader metadata, CustomAttributeHandleCollection attributes)
{
foreach (var h in attributes) {
- var attr = currentModule.GetCustomAttribute(h);
- var type = attr.GetAttributeType(currentModule);
- if (type.GetFullTypeName(currentModule).ToString() == "System.Runtime.CompilerServices.ExtensionAttribute")
+ var attr = metadata.GetCustomAttribute(h);
+ var type = attr.GetAttributeType(metadata);
+ if (type.IsTopLevelType(metadata, "System.Runtime.CompilerServices", "ExtensionAttribute"))
return true;
}
return false;
@@ -1376,11 +1392,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
#endregion
#region Read Parameter
- public IUnresolvedParameter ReadParameter(Parameter parameter, ITypeReference type)
+ public IUnresolvedParameter ReadParameter(Parameter parameter, ITypeReference typeRef, SignatureTypeCode type)
{
- var p = new DefaultUnresolvedParameter(DynamicTypeReference.Create(type, parameter.GetCustomAttributes(), currentMetadata), interningProvider.Intern(currentMetadata.GetString(parameter.Name)));
+ var p = new DefaultUnresolvedParameter(typeRef, interningProvider.Intern(currentMetadata.GetString(parameter.Name)));
- if (type is ByReferenceTypeReference) {
+ if (type == SignatureTypeCode.ByReference) {
if ((parameter.Attributes & ParameterAttributes.In) == 0 && (parameter.Attributes & ParameterAttributes.Out) != 0)
p.IsOut = true;
else
@@ -1393,16 +1409,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (!constantHandle.IsNil) {
var constant = currentMetadata.GetConstant(constantHandle);
var blobReader = currentMetadata.GetBlobReader(constant.Value);
- p.DefaultValue = CreateSimpleConstantValue(type, blobReader.ReadConstant(constant.TypeCode));
+ p.DefaultValue = CreateSimpleConstantValue(typeRef, blobReader.ReadConstant(constant.TypeCode));
} else {
- p.DefaultValue = CreateSimpleConstantValue(type, null);
+ p.DefaultValue = CreateSimpleConstantValue(typeRef, null);
}
}
- if (type is ArrayTypeReference) {
+ if (type == SignatureTypeCode.SZArray) {
foreach (CustomAttributeHandle h in parameter.GetCustomAttributes()) {
var att = currentMetadata.GetCustomAttribute(h);
- if (att.GetAttributeType(currentMetadata).GetFullTypeName(currentMetadata).ToString() == typeof(ParamArrayAttribute).FullName) {
+ if (att.IsAttributeType(currentMetadata, "System", "ParamArrayAttribute")) {
p.IsParams = true;
break;
}
@@ -1426,55 +1442,28 @@ namespace ICSharpCode.Decompiler.TypeSystem
decimal? TryDecodeDecimalConstantAttribute(CustomAttributeHandle handle)
{
var attribute = currentMetadata.GetCustomAttribute(handle);
-
- ITypeReference attributeType = ReadTypeReference(attribute.GetAttributeType(currentMetadata));
- MethodSignature signature;
- switch (attribute.Constructor.Kind) {
- case HandleKind.MethodDefinition:
- var md = currentMetadata.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
- signature = md.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
- break;
- case HandleKind.MemberReference:
- var mr = currentMetadata.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
- Debug.Assert(mr.GetKind() == MemberReferenceKind.Method);
- signature = mr.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default);
- break;
- default:
- throw new NotSupportedException();
- }
-
- if (signature.RequiredParameterCount != 5)
+ var attrValue = attribute.DecodeValue(minimalCorlibTypeProvider);
+ if (attrValue.FixedArguments.Length != 5)
return null;
-
- var reader = new Implementation.BlobReader(currentMetadata.GetBlobBytes(attribute.Value), null);
- if (reader.ReadUInt16() != 0x0001) {
- Debug.WriteLine("Unknown blob prolog");
- return null;
- }
-
// DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low)
// Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required.
- var ctorArgs = new object[signature.RequiredParameterCount];
- for (int i = 0; i < ctorArgs.Length; i++) {
- switch (signature.ParameterTypes[i].Resolve(minimalCorlibContext).FullName) {
- case "System.Byte":
- ctorArgs[i] = reader.ReadByte();
- break;
- case "System.Int32":
- ctorArgs[i] = reader.ReadInt32();
- break;
- case "System.UInt32":
- ctorArgs[i] = unchecked((int)reader.ReadUInt32());
- break;
- default:
- return null;
+ if (!(attrValue.FixedArguments[0].Value is byte scale && attrValue.FixedArguments[1].Value is byte sign))
+ return null;
+ unchecked {
+ if (attrValue.FixedArguments[2].Value is uint hi
+ && attrValue.FixedArguments[3].Value is uint mid
+ && attrValue.FixedArguments[4].Value is uint lo) {
+ return new decimal((int)lo, (int)mid, (int)hi, sign != 0, scale);
}
}
-
- if (!ctorArgs.Select(a => a.GetType()).SequenceEqual(new[] { typeof(byte), typeof(byte), typeof(int), typeof(int), typeof(int) }))
- return null;
-
- return new decimal((int)ctorArgs[4], (int)ctorArgs[3], (int)ctorArgs[2], (byte)ctorArgs[1] != 0, (byte)ctorArgs[0]);
+ {
+ if (attrValue.FixedArguments[2].Value is int hi
+ && attrValue.FixedArguments[3].Value is int mid
+ && attrValue.FixedArguments[4].Value is int lo) {
+ return new decimal(lo, mid, hi, sign != 0, scale);
+ }
+ }
+ return null;
}
public IUnresolvedField ReadField(FieldDefinitionHandle handle, IUnresolvedTypeDefinition parentType)
@@ -1489,7 +1478,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
f.Accessibility = GetAccessibility(field.Attributes);
f.IsReadOnly = (field.Attributes & FieldAttributes.InitOnly) == FieldAttributes.InitOnly;
f.IsStatic = (field.Attributes & FieldAttributes.Static) == FieldAttributes.Static;
- f.ReturnType = DynamicTypeReference.Create(field.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default), field.GetCustomAttributes(), currentMetadata);
+ f.ReturnType = new FieldTypeReference(handle, currentMetadata, TypeAttributeOptions);
var constantHandle = field.GetDefaultValue();
if (!constantHandle.IsNil) {
var constant = currentMetadata.GetConstant(constantHandle);
@@ -1599,37 +1588,23 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (!accessors.Getter.IsNil && !accessors.Setter.IsNil)
p.Accessibility = MergePropertyAccessibility(GetAccessibility(currentMetadata.GetMethodDefinition(accessors.Getter).Attributes), GetAccessibility(currentMetadata.GetMethodDefinition(accessors.Setter).Attributes));
- var signature = property.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
p.Getter = ReadMethod(accessors.Getter, parentType, SymbolKind.Accessor, p);
p.Setter = ReadMethod(accessors.Setter, parentType, SymbolKind.Accessor, p);
- var parameterHandles = Empty.Array;
+ ParameterHandleCollection? parameterHandles = null;
if (!accessors.Getter.IsNil) {
var getter = currentMetadata.GetMethodDefinition(accessors.Getter);
- parameterHandles = getter.GetParameters().ToArray();
- } else {
- if (!accessors.Setter.IsNil) {
- var setter = currentMetadata.GetMethodDefinition(accessors.Setter);
- parameterHandles = setter.GetParameters().ToArray();
- }
+ parameterHandles = getter.GetParameters();
+ } else if (!accessors.Setter.IsNil) {
+ var setter = currentMetadata.GetMethodDefinition(accessors.Setter);
+ parameterHandles = setter.GetParameters();
}
- p.ReturnType = HandleReturnType(parameterHandles.FirstOrDefault(), signature.ReturnType);
-
- int i = 0;
- if (signature.RequiredParameterCount > parameterHandles.Length) {
- foreach (var parameterType in signature.ParameterTypes) {
- p.Parameters.Add(new DefaultUnresolvedParameter(DynamicTypeReference.Create(parameterType, null, currentMetadata), string.Empty));
- }
- } else {
- foreach (var h in parameterHandles) {
- var par = currentMetadata.GetParameter(h);
- if (par.SequenceNumber > 0 && i < signature.ParameterTypes.Length) {
- p.Parameters.Add(ReadParameter(par, signature.ParameterTypes[i]));
- i++;
- }
- }
- }
+ var signature = property.DecodeSignature(TypeCodeProvider.Instance, default);
+ var unresolvedSig = new UnresolvedMethodSignature(handle, currentMetadata, TypeAttributeOptions);
+ var (retType, parameters) = TranslateSignature(signature, unresolvedSig, parameterHandles);
+ p.ReturnType = retType;
+ p.Parameters.AddRange(parameters);
AddAttributes(property, p);
var accessor = p.Getter ?? p.Setter;
@@ -1691,14 +1666,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
member.MetadataToken = cecilDefinition;
member.ApplyInterningProvider(interningProvider);
member.Freeze();
- RegisterCecilObject(member);
- }
- #endregion
-
- #region Type system translation table
- void RegisterCecilObject(IUnresolvedEntity typeSystemObject)
- {
- OnEntityLoaded?.Invoke(typeSystemObject);
}
#endregion
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs
index 68c76762b..b5d78a80a 100644
--- a/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs
@@ -17,6 +17,8 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Collections.Immutable;
+using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem
@@ -53,18 +55,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
public TypeParameterSubstitution Substitution {
get { return substitution; }
}
-
- public IType ResolveFromSignature(ITypeReference typeReference)
- {
- return context.ResolveFromSignature(typeReference).AcceptVisitor(substitution);
- }
-
- public IType ResolveAsType(System.Reflection.Metadata.EntityHandle typeReference)
+
+ public IType ResolveAsType(EntityHandle typeReference)
{
return context.ResolveAsType(typeReference).AcceptVisitor(substitution);
}
- public IField ResolveAsField(System.Reflection.Metadata.EntityHandle fieldReference)
+ public IField ResolveAsField(EntityHandle fieldReference)
{
IField field = context.ResolveAsField(fieldReference);
if (field != null)
@@ -72,7 +69,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
return field;
}
- public IMethod ResolveAsMethod(System.Reflection.Metadata.EntityHandle methodReference)
+ public IMethod ResolveAsMethod(EntityHandle methodReference)
{
IMethod method = context.ResolveAsMethod(methodReference);
if (method != null)
@@ -88,12 +85,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
return context.GetSpecializingTypeSystem(newSubstitution);
}
- public System.Reflection.Metadata.MetadataReader GetMetadata()
+ public MetadataReader GetMetadata()
{
return context.GetMetadata();
}
- public IMember ResolveAsMember(System.Reflection.Metadata.EntityHandle memberReference)
+ public IMember ResolveAsMember(EntityHandle memberReference)
{
IMember member = context.ResolveAsMember(memberReference);
if (member != null)
@@ -105,5 +102,27 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
return context.GetModuleDefinition(assembly);
}
+
+ MethodSignature IDecompilerTypeSystem.DecodeMethodSignature(StandaloneSignatureHandle standaloneSignatureHandle)
+ {
+ var sig = context.DecodeMethodSignature(standaloneSignatureHandle);
+ return new MethodSignature(
+ sig.Header,
+ sig.ReturnType.AcceptVisitor(substitution),
+ sig.RequiredParameterCount,
+ sig.GenericParameterCount,
+ ImmutableArray.CreateRange(
+ sig.ParameterTypes, t => t.AcceptVisitor(substitution)
+ )
+ );
+ }
+
+ ImmutableArray IDecompilerTypeSystem.DecodeLocalSignature(StandaloneSignatureHandle standaloneSignatureHandle)
+ {
+ var sig = context.DecodeLocalSignature(standaloneSignatureHandle);
+ return ImmutableArray.CreateRange(
+ sig, t => t.AcceptVisitor(substitution)
+ );
+ }
}
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs
new file mode 100644
index 000000000..93a33d89b
--- /dev/null
+++ b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs
@@ -0,0 +1,166 @@
+// Copyright (c) 2018 Daniel Grunwald
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Immutable;
+using System.Reflection.Metadata.Ecma335;
+using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.Decompiler.TypeSystem.Implementation;
+using SRM = System.Reflection.Metadata;
+
+namespace ICSharpCode.Decompiler.TypeSystem
+{
+ ///
+ /// Allows decoding signatures using decompiler types.
+ ///
+ class TypeProvider : SRM.ISignatureTypeProvider, SRM.ICustomAttributeTypeProvider
+ {
+ readonly IAssembly assembly;
+ readonly ICompilation compilation;
+
+ public TypeProvider(IAssembly assembly)
+ {
+ this.assembly = assembly;
+ this.compilation = assembly.Compilation;
+ }
+
+ public IType GetArrayType(IType elementType, SRM.ArrayShape shape)
+ {
+ return new ArrayType(compilation, elementType, shape.Rank);
+ }
+
+ public IType GetByReferenceType(IType elementType)
+ {
+ return new ByReferenceType(elementType);
+ }
+
+ public IType GetFunctionPointerType(SRM.MethodSignature signature)
+ {
+ return compilation.FindType(KnownTypeCode.IntPtr);
+ }
+
+ public IType GetGenericInstantiation(IType genericType, ImmutableArray typeArguments)
+ {
+ return new ParameterizedType(genericType, typeArguments);
+ }
+
+ public IType GetGenericMethodParameter(ITypeResolveContext genericContext, int index)
+ {
+ // Note: returning type parameter, never type argument.
+ // Otherwise we risk screwing up the counting for dynamicTypeIndex.
+ IMethod method = genericContext.CurrentMember as IMethod;
+ if (method != null && index < method.TypeParameters.Count) {
+ return method.TypeParameters[index];
+ }
+ return DummyTypeParameter.GetMethodTypeParameter(index);
+ }
+
+ public IType GetGenericTypeParameter(ITypeResolveContext genericContext, int index)
+ {
+ ITypeDefinition typeDef = genericContext.CurrentTypeDefinition;
+ if (typeDef != null && index < typeDef.TypeParameters.Count) {
+ return typeDef.TypeParameters[index];
+ }
+ return DummyTypeParameter.GetClassTypeParameter(index);
+ }
+
+ public IType GetModifiedType(IType modifier, IType unmodifiedType, bool isRequired)
+ {
+ return unmodifiedType;
+ }
+
+ public IType GetPinnedType(IType elementType)
+ {
+ return new PinnedType(elementType);
+ }
+
+ public IType GetPointerType(IType elementType)
+ {
+ return new PointerType(elementType);
+ }
+
+ public IType GetPrimitiveType(SRM.PrimitiveTypeCode typeCode)
+ {
+ return compilation.FindType(typeCode.ToKnownTypeCode());
+ }
+
+ public IType GetSystemType()
+ {
+ return compilation.FindType(KnownTypeCode.Type);
+ }
+
+ public IType GetSZArrayType(IType elementType)
+ {
+ return new ArrayType(compilation, elementType);
+ }
+
+ public IType GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
+ {
+ ITypeDefinition td = assembly.ResolveTypeDefToken(handle);
+ if (td != null)
+ return td;
+ return SpecialType.UnknownType;
+ }
+
+ public IType GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)
+ {
+ var asmref = handle.GetDeclaringAssembly(reader);
+ IAssemblyReference nrAsmRef;
+ if (asmref.IsNil)
+ nrAsmRef = DefaultAssemblyReference.CurrentAssembly;
+ else
+ nrAsmRef = new DefaultAssemblyReference(reader.GetString(reader.GetAssemblyReference(asmref).Name));
+ bool? isReferenceType = null;
+ switch (reader.ResolveSignatureTypeKind(handle, rawTypeKind)) {
+ case SRM.SignatureTypeKind.ValueType:
+ isReferenceType = false;
+ break;
+ case SRM.SignatureTypeKind.Class:
+ isReferenceType = true;
+ break;
+ }
+ var gctr = new GetClassTypeReference(handle.GetFullTypeName(reader), nrAsmRef, isReferenceType);
+ return gctr.Resolve(new SimpleTypeResolveContext(assembly));
+ }
+
+ public IType GetTypeFromSerializedName(string name)
+ {
+ // TODO: aren't we missing support for assembly-qualified names?
+ return new GetClassTypeReference(new FullTypeName(name))
+ .Resolve(new SimpleTypeResolveContext(assembly));
+ }
+
+ public IType GetTypeFromSpecification(SRM.MetadataReader reader, ITypeResolveContext genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)
+ {
+ return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext);
+ }
+
+ public SRM.PrimitiveTypeCode GetUnderlyingEnumType(IType type)
+ {
+ var def = type.GetEnumUnderlyingType().GetDefinition();
+ if (def == null)
+ throw new InvalidOperationException();
+ return def.KnownTypeCode.ToPrimitiveTypeCode();
+ }
+
+ public bool IsSystemType(IType type)
+ {
+ return type.IsKnownType(KnownTypeCode.Type);
+ }
+ }
+}
diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs
index 509f45564..9c820d0a2 100644
--- a/ILSpy/Languages/CSharpLanguage.cs
+++ b/ILSpy/Languages/CSharpLanguage.cs
@@ -586,7 +586,7 @@ namespace ICSharpCode.ILSpy
var st = new SyntaxTree();
st.AddChild(astType, Roles.Type);
- st.AcceptVisitor(new InsertDynamicTypeVisitor(metadata, customAttributes));
+ //st.AcceptVisitor(new InsertDynamicTypeVisitor(metadata, customAttributes));
st.FirstChild.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
return w.ToString();
}
@@ -788,41 +788,4 @@ namespace ICSharpCode.ILSpy
return info;
}
}
-
- class InsertDynamicTypeVisitor : DepthFirstAstVisitor
- {
- bool isDynamic;
- bool[] mapping;
- int typeIndex;
-
- public InsertDynamicTypeVisitor(MetadataReader metadata, CustomAttributeHandleCollection? customAttributes)
- {
- isDynamic = DynamicTypeReference.HasDynamicAttribute(customAttributes, metadata, out mapping);
- }
-
- public override void VisitComposedType(ComposedType composedType)
- {
- typeIndex++;
- base.VisitComposedType(composedType);
- }
-
- public override void VisitPrimitiveType(PrimitiveType primitiveType)
- {
- if (isDynamic && primitiveType.KnownTypeCode == KnownTypeCode.Object && (mapping == null || typeIndex >= mapping.Length || mapping[typeIndex])) {
- primitiveType.ReplaceWith(new SimpleType("dynamic"));
- } else {
- base.VisitPrimitiveType(primitiveType);
- }
- }
-
- public override void VisitMemberType(MemberType memberType)
- {
- base.VisitMemberType(memberType);
- }
-
- public override void VisitSimpleType(SimpleType simpleType)
- {
- base.VisitSimpleType(simpleType);
- }
- }
}
diff --git a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs
index 5cdc3a109..24533731d 100644
--- a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs
+++ b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs
@@ -38,7 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
readonly bool provideTypeSystem;
TypeDefinitionHandle typeScopeHandle;
TypeDefinition typeScope;
- static readonly TypeSystemAttributeTypeProvider typeProvider = TypeSystemAttributeTypeProvider.CreateDefault();
readonly Accessibility memberAccessibility = Accessibility.Public;
Accessibility typeAccessibility = Accessibility.Public;
@@ -305,6 +304,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
string typeScopeNamespace = metadata.GetString(typeScope.Namespace);
string typeScopeName = metadata.GetString(typeScope.Name);
+ var typeProvider = Decompiler.Metadata.MetadataExtensions.MinimalAttributeTypeProvider;
var attributes = metadata.CustomAttributes.Select(h => metadata.GetCustomAttribute(h)).Where(ca => ca.GetAttributeType(metadata).GetFullTypeName(metadata).ToString() == "System.Runtime.CompilerServices.InternalsVisibleToAttribute");
var friendAssemblies = new HashSet();
foreach (var attribute in attributes) {