From b97fc4d486e958e3e8ff502576d3eae297acfa2b Mon Sep 17 00:00:00 2001 From: Washi Date: Tue, 7 Nov 2023 19:47:05 +0100 Subject: [PATCH 1/3] Add resolution typenameparser tests. --- .../CustomAttributeTest.cs | 23 +++++++++++-------- .../ReferenceImporterTest.cs | 8 ++++--- .../Signatures/TypeNameParserTest.cs | 18 +++++++++++---- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/test/AsmResolver.DotNet.Tests/CustomAttributeTest.cs b/test/AsmResolver.DotNet.Tests/CustomAttributeTest.cs index 352ddb998..79e4faa9c 100644 --- a/test/AsmResolver.DotNet.Tests/CustomAttributeTest.cs +++ b/test/AsmResolver.DotNet.Tests/CustomAttributeTest.cs @@ -85,7 +85,7 @@ private static CustomAttribute GetCustomAttributeTestCase( attributeName += "`1"; var attribute = method.CustomAttributes - .First(c => c.Constructor!.DeclaringType!.Name.Value.StartsWith(attributeName)); + .First(c => c.Constructor!.DeclaringType!.Name!.Value.StartsWith(attributeName)); if (access) { @@ -197,10 +197,13 @@ public void FixedComplexTypeArgument(bool rebuild, bool access) var argument = attribute.Signature.FixedArguments[0]; var factory = attribute.Constructor!.Module!.CorLibTypeFactory; - var listRef = new TypeReference(factory.CorLibScope, "System.Collections.Generic", "KeyValuePair`2"); - var instance = new GenericInstanceTypeSignature(listRef, false, - new SzArrayTypeSignature(factory.String), - new SzArrayTypeSignature(factory.Int32)); + var instance = factory.CorLibScope + .CreateTypeReference("System.Collections.Generic", "KeyValuePair`2") + .MakeGenericInstanceType( + false, + factory.String.MakeSzArrayType(), + factory.Int32.MakeSzArrayType() + ); Assert.Equal(instance, argument.Element as TypeSignature, _comparer); } @@ -293,7 +296,7 @@ public void GenericTypeArgument(bool rebuild, bool access) var module = attribute.Constructor!.Module!; var nestedClass = (TypeDefinition) module.LookupMember(typeof(TestGenericType<>).MetadataToken); - var expected = new GenericInstanceTypeSignature(nestedClass, false, module.CorLibTypeFactory.Object); + var expected = nestedClass.MakeGenericInstanceType(false, module.CorLibTypeFactory.Object); var element = Assert.IsAssignableFrom(argument.Element); Assert.Equal(expected, element, _comparer); @@ -312,9 +315,9 @@ public void ArrayGenericTypeArgument(bool rebuild, bool access) var module = attribute.Constructor!.Module!; var nestedClass = (TypeDefinition) module.LookupMember(typeof(TestGenericType<>).MetadataToken); - var expected = new SzArrayTypeSignature( - new GenericInstanceTypeSignature(nestedClass, false, module.CorLibTypeFactory.Object) - ); + var expected = nestedClass + .MakeGenericInstanceType(false, module.CorLibTypeFactory.Object) + .MakeSzArrayType(); var element = Assert.IsAssignableFrom(argument.Element); Assert.Equal(expected, element, _comparer); @@ -413,7 +416,7 @@ public void FixedInt32EmptyArrayAsObject(bool rebuild, bool access) var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedInt32ArrayAsObjectEmptyArgument),rebuild, access); var argument = attribute.Signature!.FixedArguments[0]; - var boxedArgument =Assert.IsAssignableFrom(argument.Element); + var boxedArgument = Assert.IsAssignableFrom(argument.Element); Assert.Equal(Array.Empty(), boxedArgument.Value); } diff --git a/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs b/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs index 2bbd52f5b..4f745efc9 100644 --- a/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs +++ b/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs @@ -421,9 +421,10 @@ public void ImportCustomModifierTypeWithNonImportedModifierTypeShouldResultInNew [Fact] public void ImportFullyImportedCustomModifierTypeShouldResultInSameInstance() { - var signature = new TypeReference(_module, _dummyAssembly, "SomeNamespace", "SomeType") + var assembly = _importer.ImportScope(_dummyAssembly); + var signature = new TypeReference(_module, assembly, "SomeNamespace", "SomeType") .ToTypeSignature() - .MakeModifierType(new TypeReference(_module, _dummyAssembly, "SomeNamespace", "SomeModifierType"), true); + .MakeModifierType(new TypeReference(_module, assembly, "SomeNamespace", "SomeModifierType"), true); var imported = _importer.ImportTypeSignature(signature); @@ -470,10 +471,11 @@ public void ImportFunctionPointerTypeWithNonImportedReturnTypeShouldResultInNewI [Fact] public void ImportFullyImportedFunctionPointerTypeShouldResultInSameInstance() { + var assembly = _importer.ImportScope(_dummyAssembly); var signature = MethodSignature .CreateStatic( _module.CorLibTypeFactory.Void, - new TypeReference(_module, _dummyAssembly, "SomeNamespace", "SomeType").ToTypeSignature()) + new TypeReference(_module, assembly, "SomeNamespace", "SomeType").ToTypeSignature()) .MakeFunctionPointerType(); var imported = _importer.ImportTypeSignature(signature); diff --git a/test/AsmResolver.DotNet.Tests/Signatures/TypeNameParserTest.cs b/test/AsmResolver.DotNet.Tests/Signatures/TypeNameParserTest.cs index c79e85572..25f841ad8 100644 --- a/test/AsmResolver.DotNet.Tests/Signatures/TypeNameParserTest.cs +++ b/test/AsmResolver.DotNet.Tests/Signatures/TypeNameParserTest.cs @@ -82,9 +82,7 @@ public void TypeWithAssemblyName() var assemblyRef = new AssemblyReference("MyAssembly", new Version(1, 2, 3, 4)); var expected = new TypeReference(assemblyRef, ns, name).ToTypeSignature(); - - var actual = TypeNameParser.Parse(_module, - $"{ns}.{name}, {assemblyRef.FullName}"); + var actual = TypeNameParser.Parse(_module, $"{ns}.{name}, {assemblyRef.FullName}"); Assert.Equal(expected, actual, _comparer); } @@ -141,7 +139,7 @@ public void GenericTypeSingleBrackets() var elementType = new TypeReference(_module, ns, name); var argumentType = _module.CorLibTypeFactory.Object; - var expected = new GenericInstanceTypeSignature(elementType, false, argumentType); + var expected = elementType.MakeGenericInstanceType(false, argumentType); var actual = TypeNameParser.Parse(_module, $"{ns}.{name}[{argumentType.Namespace}.{argumentType.Name}]"); Assert.Equal(expected, actual, _comparer); @@ -299,5 +297,17 @@ public void ReadTypeShouldUseNewScopeInstanceIfNotImportedYet() "SomeNamespace.SomeType, SomeAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=0123456789abcdef"); Assert.DoesNotContain(type.Scope!.GetAssembly(), _module.AssemblyReferences); } + + [Fact] + public void ReadTypeNameFromLocalModuleShouldResultInResolvableType() + { + var module = ModuleDefinition.FromFile(typeof(TypeNameParserTest).Assembly.Location); + var type = TypeNameParser + .Parse(module, typeof(TypeNameParserTest).AssemblyQualifiedName!) + .GetUnderlyingTypeDefOrRef()!; + + Assert.NotNull(type.Resolve()); + Assert.NotNull(type.ImportWith(module.DefaultImporter).Resolve()); + } } } From 9d4cf16ac57c5799b1081f62e224a2a8fa082340 Mon Sep 17 00:00:00 2001 From: Washi Date: Tue, 7 Nov 2023 19:48:53 +0100 Subject: [PATCH 2/3] BUGFIX: Consider scope in type.IsImportedInModule. --- src/AsmResolver.DotNet/Signatures/CustomAttributeArgument.cs | 4 +++- src/AsmResolver.DotNet/TypeReference.cs | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/AsmResolver.DotNet/Signatures/CustomAttributeArgument.cs b/src/AsmResolver.DotNet/Signatures/CustomAttributeArgument.cs index 8683f8925..2ae57418d 100644 --- a/src/AsmResolver.DotNet/Signatures/CustomAttributeArgument.cs +++ b/src/AsmResolver.DotNet/Signatures/CustomAttributeArgument.cs @@ -19,7 +19,9 @@ public class CustomAttributeArgument /// The type of the argument to read. /// The input stream. /// The argument. - public static CustomAttributeArgument FromReader(in BlobReaderContext context, TypeSignature argumentType, + public static CustomAttributeArgument FromReader( + in BlobReaderContext context, + TypeSignature argumentType, ref BinaryStreamReader reader) { var elementReader = CustomAttributeArgumentReader.Create(); diff --git a/src/AsmResolver.DotNet/TypeReference.cs b/src/AsmResolver.DotNet/TypeReference.cs index 5e5294d7b..23abe8a89 100644 --- a/src/AsmResolver.DotNet/TypeReference.cs +++ b/src/AsmResolver.DotNet/TypeReference.cs @@ -140,7 +140,8 @@ public TypeSignature ToTypeSignature(bool isValueType) } /// - public bool IsImportedInModule(ModuleDefinition module) => Module == module; + public bool IsImportedInModule(ModuleDefinition module) => + Module == module && (Scope?.IsImportedInModule(module) ?? false); /// /// Imports the type reference using the provided reference importer object. From 740369250ba86ab675dbfc7aba06fcf7d39b3959 Mon Sep 17 00:00:00 2001 From: Washi Date: Tue, 7 Nov 2023 20:37:03 +0100 Subject: [PATCH 3/3] BUGFIX: Test whether type's scope is the current assembly. --- src/AsmResolver.DotNet/DefaultMetadataResolver.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/AsmResolver.DotNet/DefaultMetadataResolver.cs b/src/AsmResolver.DotNet/DefaultMetadataResolver.cs index e80d5cae4..519e769da 100644 --- a/src/AsmResolver.DotNet/DefaultMetadataResolver.cs +++ b/src/AsmResolver.DotNet/DefaultMetadataResolver.cs @@ -177,6 +177,13 @@ public TypeResolution(IAssemblyResolver resolver) switch (scope.MetadataToken.Table) { case TableIndex.AssemblyRef: + if (reference.Module?.Assembly is { } assembly) + { + // Are we referencing the current assembly the reference was declared in? + if (SignatureComparer.Default.Equals(scope.GetAssembly(), assembly)) + return FindTypeInModule(reference.Module, reference.Namespace, reference.Name); + } + var assemblyDefScope = _assemblyResolver.Resolve((AssemblyReference) scope); return assemblyDefScope is not null ? FindTypeInAssembly(assemblyDefScope, reference.Namespace, reference.Name)