diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 78a107ea1..c5c935db3 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -112,6 +112,7 @@ + diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index d1ca322e1..191ee8b0f 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -827,7 +827,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!IsLocalFunctionMethod(module, method, context)) continue; var md = metadata.GetMethodDefinition(method); - if (md.DecodeSignature(new FindTypeDecoder(typeHandle), default).ParameterTypes.Any()) + if (md.DecodeSignature(new FindTypeDecoder(typeHandle, module, 0), default).ParameterTypes.Any()) return true; } @@ -852,43 +852,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms return match.Success; } - struct FindTypeDecoder : ISignatureTypeProvider - { - readonly TypeDefinitionHandle handle; - - public FindTypeDecoder(TypeDefinitionHandle handle) - { - this.handle = handle; - } - - public bool GetArrayType(bool elementType, ArrayShape shape) => elementType; - public bool GetByReferenceType(bool elementType) => elementType; - public bool GetFunctionPointerType(MethodSignature signature) => false; - public bool GetGenericInstantiation(bool genericType, ImmutableArray typeArguments) => genericType; - public bool GetGenericMethodParameter(Unit genericContext, int index) => false; - public bool GetGenericTypeParameter(Unit genericContext, int index) => false; - public bool GetModifiedType(bool modifier, bool unmodifiedType, bool isRequired) => unmodifiedType; - public bool GetPinnedType(bool elementType) => elementType; - public bool GetPointerType(bool elementType) => elementType; - public bool GetPrimitiveType(PrimitiveTypeCode typeCode) => false; - public bool GetSZArrayType(bool elementType) => false; - - public bool GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) - { - return this.handle == handle; - } - - public bool GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) - { - return false; - } - - public bool GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) - { - return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext); - } - } - class FindRefStructParameters : ISignatureTypeProvider { public readonly List RefStructTypes = new List(); diff --git a/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs b/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs new file mode 100644 index 000000000..7b5847fad --- /dev/null +++ b/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs @@ -0,0 +1,126 @@ +// Copyright (c) 2022 Siegfried Pammer +// +// 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. + +#nullable enable + +using System; +using System.Collections.Immutable; +using System.Reflection.Metadata; + +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Util; + +namespace ICSharpCode.Decompiler.Metadata +{ + public class FindTypeDecoder : ISignatureTypeProvider + { + readonly PEFile declaringModule; + readonly MetadataModule? currentModule; + readonly TypeDefinitionHandle handle; + readonly string? typeName; + readonly string? namespaceName; + readonly PrimitiveTypeCode primitiveType; + + public FindTypeDecoder(TypeDefinitionHandle handle, PEFile declaringModule, PrimitiveTypeCode primitiveType) + { + this.handle = handle; + this.declaringModule = declaringModule; + this.primitiveType = primitiveType; + this.currentModule = null; + } + + public FindTypeDecoder(MetadataModule currentModule, ITypeDefinition type) + { + this.currentModule = currentModule; + this.declaringModule = type.ParentModule.PEFile ?? throw new InvalidOperationException("Cannot use MetadataModule without PEFile as context."); + this.handle = (TypeDefinitionHandle)type.MetadataToken; + this.primitiveType = type.KnownTypeCode == KnownTypeCode.None ? 0 : type.KnownTypeCode.ToPrimitiveTypeCode(); + this.typeName = type.MetadataName; + this.namespaceName = type.Namespace; + } + + public bool GetArrayType(bool elementType, ArrayShape shape) => elementType; + public bool GetByReferenceType(bool elementType) => elementType; + public bool GetFunctionPointerType(MethodSignature signature) + { + if (signature.ReturnType) + return true; + foreach (bool type in signature.ParameterTypes) + { + if (type) + return true; + } + return false; + } + + public bool GetGenericInstantiation(bool genericType, ImmutableArray typeArguments) + { + if (genericType) + return true; + foreach (bool ta in typeArguments) + { + if (ta) + return true; + } + return false; + } + + public bool GetGenericMethodParameter(Unit genericContext, int index) => false; + public bool GetGenericTypeParameter(Unit genericContext, int index) => false; + public bool GetModifiedType(bool modifier, bool unmodifiedType, bool isRequired) => unmodifiedType || modifier; + public bool GetPinnedType(bool elementType) => elementType; + public bool GetPointerType(bool elementType) => elementType; + + public bool GetPrimitiveType(PrimitiveTypeCode typeCode) + { + return typeCode == primitiveType; + } + + public bool GetSZArrayType(bool elementType) => elementType; + + public bool GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) + { + return this.handle == handle && reader == declaringModule.Metadata; + } + + public bool GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) + { + if (currentModule == null || typeName == null || namespaceName == null) + return false; + + var tr = reader.GetTypeReference(handle); + if (!reader.StringComparer.Equals(tr.Name, typeName)) + return false; + if (!((tr.Namespace.IsNil && namespaceName.Length == 0) || reader.StringComparer.Equals(tr.Namespace, namespaceName))) + return false; + + var t = currentModule.ResolveType(handle, default); + var td = t.GetDefinition(); + if (td == null) + return false; + + return td.MetadataToken == this.handle && td.ParentModule.PEFile == declaringModule; + } + + public bool GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) + { + return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext); + } + } + +}