From 30016bbcdb61c12c1a8b094241a871b04ef6b0e4 Mon Sep 17 00:00:00 2001 From: Washi Date: Thu, 5 Jan 2023 20:46:24 +0100 Subject: [PATCH 1/4] Add generic custom attribute test cases. --- .../CustomAttributeTest.cs | 202 ++++++++++++++++-- ...r.DotNet.TestCases.CustomAttributes.csproj | 1 + .../CustomAttributesTestClass.cs | 59 +++++ .../TestCaseAttribute.Generic.cs | 24 +++ 4 files changed, 270 insertions(+), 16 deletions(-) create mode 100644 test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/TestCaseAttribute.Generic.cs diff --git a/test/AsmResolver.DotNet.Tests/CustomAttributeTest.cs b/test/AsmResolver.DotNet.Tests/CustomAttributeTest.cs index b05032774..6c57703a7 100644 --- a/test/AsmResolver.DotNet.Tests/CustomAttributeTest.cs +++ b/test/AsmResolver.DotNet.Tests/CustomAttributeTest.cs @@ -70,13 +70,22 @@ public void ReadParent() Assert.Equal(parentToken, attribute.Parent.MetadataToken); } - private static CustomAttribute GetCustomAttributeTestCase(string methodName, bool rebuild = false, bool access = false) + private static CustomAttribute GetCustomAttributeTestCase( + string methodName, + bool rebuild = false, + bool access = false, + bool generic = false) { var module = ModuleDefinition.FromFile(typeof(CustomAttributesTestClass).Assembly.Location); var type = module.TopLevelTypes.First(t => t.Name == nameof(CustomAttributesTestClass)); var method = type.Methods.First(m => m.Name == methodName); + + string attributeName = nameof(TestCaseAttribute); + if (generic) + attributeName += "`1"; + var attribute = method.CustomAttributes - .First(c => c.Constructor!.DeclaringType!.Name == nameof(TestCaseAttribute)); + .First(c => c.Constructor!.DeclaringType!.Name == attributeName); if (access) { @@ -286,8 +295,8 @@ public void GenericTypeArgument(bool rebuild, bool access) var nestedClass = (TypeDefinition) module.LookupMember(typeof(TestGenericType<>).MetadataToken); var expected = new GenericInstanceTypeSignature(nestedClass, false, module.CorLibTypeFactory.Object); - Assert.IsAssignableFrom(argument.Element); - Assert.Equal(expected, (TypeSignature) argument.Element, _comparer); + var element = Assert.IsAssignableFrom(argument.Element); + Assert.Equal(expected, element, _comparer); } [Theory] @@ -307,8 +316,8 @@ public void ArrayGenericTypeArgument(bool rebuild, bool access) new GenericInstanceTypeSignature(nestedClass, false, module.CorLibTypeFactory.Object) ); - Assert.IsAssignableFrom(argument.Element); - Assert.Equal(expected, (TypeSignature) argument.Element, _comparer); + var element = Assert.IsAssignableFrom(argument.Element); + Assert.Equal(expected, element, _comparer); } [Theory] @@ -322,8 +331,8 @@ public void IntPassedOnAsObject(bool rebuild, bool access) var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.Int32PassedAsObject),rebuild, access); var argument = attribute.Signature!.FixedArguments[0]; - Assert.IsAssignableFrom(argument.Element); - Assert.Equal(123, ((BoxedArgument) argument.Element).Value); + var element = Assert.IsAssignableFrom(argument.Element); + Assert.Equal(123, element.Value); } [Theory] @@ -338,8 +347,8 @@ public void TypePassedOnAsObject(bool rebuild, bool access) var argument = attribute.Signature!.FixedArguments[0]; var module = attribute.Constructor!.Module!; - Assert.IsAssignableFrom(argument.Element); - Assert.Equal(module.CorLibTypeFactory.Int32, (ITypeDescriptor) ((BoxedArgument) argument.Element).Value, _comparer); + var element = Assert.IsAssignableFrom(argument.Element); + Assert.Equal(module.CorLibTypeFactory.Int32, (ITypeDescriptor) element.Value, _comparer); } [Theory] @@ -391,8 +400,7 @@ public void FixedInt32ArrayNullAsObject(bool rebuild, bool access) var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedInt32ArrayAsObjectNullArgument),rebuild, access); var argument = attribute.Signature!.FixedArguments[0]; - Assert.IsAssignableFrom(argument.Element); - var boxedArgument = (BoxedArgument) argument.Element; + var boxedArgument = Assert.IsAssignableFrom(argument.Element); Assert.Null(boxedArgument.Value); } @@ -405,8 +413,7 @@ public void FixedInt32EmptyArrayAsObject(bool rebuild, bool access) var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedInt32ArrayAsObjectEmptyArgument),rebuild, access); var argument = attribute.Signature!.FixedArguments[0]; - Assert.IsAssignableFrom(argument.Element); - var boxedArgument = (BoxedArgument) argument.Element; + var boxedArgument =Assert.IsAssignableFrom(argument.Element); Assert.Equal(Array.Empty(), boxedArgument.Value); } @@ -419,8 +426,7 @@ public void FixedInt32ArrayAsObject(bool rebuild, bool access) var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedInt32ArrayAsObjectArgument),rebuild, access); var argument = attribute.Signature!.FixedArguments[0]; - Assert.IsAssignableFrom(argument.Element); - var boxedArgument = (BoxedArgument) argument.Element; + var boxedArgument = Assert.IsAssignableFrom(argument.Element); Assert.Equal(new[] { 1, 2, 3, 4 @@ -464,5 +470,169 @@ public void CreateNewWithFixedArgumentsViaProperty() var argument = Assert.Single(attribute.Signature.FixedArguments); Assert.Equal("My Message", argument.Element); } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void FixedGenericInt32Argument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericInt32Argument), rebuild, access); + var argument = attribute.Signature!.FixedArguments[0]; + + int value = Assert.IsAssignableFrom(argument.Element); + Assert.Equal(1, value); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void FixedGenericStringArgument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericStringArgument), rebuild, access); + var argument = attribute.Signature!.FixedArguments[0]; + + string value = Assert.IsAssignableFrom(argument.Element); + Assert.Equal("Fixed string generic argument", value); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void FixedGenericInt32ArrayArgument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericInt32ArrayArgument), rebuild, access); + var argument = attribute.Signature!.FixedArguments[0]; + + Assert.Equal(new int[] {1, 2, 3, 4}, argument.Elements.Cast()); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void FixedGenericInt32ArrayAsObjectArgument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericInt32ArrayAsObjectArgument), rebuild, access); + var argument = attribute.Signature!.FixedArguments[0]; + + var boxedArgument = Assert.IsAssignableFrom(argument.Element); + Assert.Equal(new[] + { + 1, 2, 3, 4 + }, boxedArgument.Value); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void FixedGenericTypeArgument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericTypeArgument), rebuild, access); + var argument = attribute.Signature!.FixedArguments[0]; + + var expected = attribute.Constructor!.Module!.CorLibTypeFactory.Int32; + var element = Assert.IsAssignableFrom(argument.Element); + Assert.Equal(expected, element, _comparer); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void FixedGenericTypeNullArgument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericTypeNullArgument), rebuild, access); + var argument = attribute.Signature!.FixedArguments[0]; + + Assert.Null(argument.Element); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void NamedGenericInt32Argument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericInt32Argument), rebuild, access); + var argument = attribute.Signature!.NamedArguments[0]; + + Assert.Equal("Value", argument.MemberName); + int value = Assert.IsAssignableFrom(argument.Argument.Element); + Assert.Equal(1, value); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void NamedGenericStringArgument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericStringArgument), rebuild, access); + var argument = attribute.Signature!.NamedArguments[0]; + + Assert.Equal("Value", argument.MemberName); + string value = Assert.IsAssignableFrom(argument.Argument.Element); + Assert.Equal("Named string generic argument", value); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void NamedGenericInt32ArrayArgument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericInt32ArrayArgument), rebuild, access); + var argument = attribute.Signature!.NamedArguments[0]; + + Assert.Equal("Value", argument.MemberName); + Assert.Equal(new int[] {1,2,3,4}, argument.Argument.Elements.Cast()); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void NamedGenericInt32ArrayAsObjectArgument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericInt32ArrayAsObjectArgument), rebuild, access); + var argument = attribute.Signature!.NamedArguments[0]; + + Assert.Equal("Value", argument.MemberName); + var boxedArgument = Assert.IsAssignableFrom(argument.Argument.Element); + Assert.Equal(new[] + { + 1, 2, 3, 4 + }, boxedArgument.Value); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void NamedGenericTypeArgument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericTypeArgument), rebuild, access); + var argument = attribute.Signature!.NamedArguments[0]; + + var expected = attribute.Constructor!.Module!.CorLibTypeFactory.Int32; + var element = Assert.IsAssignableFrom(argument.Argument.Element); + Assert.Equal(expected, element, _comparer); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(true, true)] + public void NamedGenericTypeNullArgument(bool rebuild, bool access) + { + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericTypeNullArgument), rebuild, access); + var argument = attribute.Signature!.NamedArguments[0]; + + Assert.Null(argument.Argument.Element); + } } } diff --git a/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/AsmResolver.DotNet.TestCases.CustomAttributes.csproj b/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/AsmResolver.DotNet.TestCases.CustomAttributes.csproj index 27560206d..a2f2e3d95 100644 --- a/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/AsmResolver.DotNet.TestCases.CustomAttributes.csproj +++ b/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/AsmResolver.DotNet.TestCases.CustomAttributes.csproj @@ -2,6 +2,7 @@ netstandard2.0 + 11 diff --git a/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/CustomAttributesTestClass.cs b/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/CustomAttributesTestClass.cs index 852f2d44f..f4444fa45 100644 --- a/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/CustomAttributesTestClass.cs +++ b/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/CustomAttributesTestClass.cs @@ -134,5 +134,64 @@ public void FixedNullTypeArgument() { } + [TestCase(1)] + public void FixedGenericInt32Argument() + { + } + + [TestCase("Fixed string generic argument")] + public void FixedGenericStringArgument() + { + } + + [TestCase(new int[] {1,2,3,4})] + public void FixedGenericInt32ArrayArgument() + { + } + + [TestCase(new int[] {1,2,3,4})] + public void FixedGenericInt32ArrayAsObjectArgument() + { + } + + [TestCase(typeof(int))] + public void FixedGenericTypeArgument() + { + } + + [TestCase(null)] + public void FixedGenericTypeNullArgument() + { + } + + [TestCase(Value = 1)] + public void NamedGenericInt32Argument() + { + } + + [TestCase(Value = "Named string generic argument")] + public void NamedGenericStringArgument() + { + } + + [TestCase(Value = new int[] {1,2,3,4})] + public void NamedGenericInt32ArrayArgument() + { + } + + [TestCase(Value = new int[] {1,2,3,4})] + public void NamedGenericInt32ArrayAsObjectArgument() + { + } + + [TestCase(Value = typeof(int))] + public void NamedGenericTypeArgument() + { + } + + [TestCase(Value = null)] + public void NamedGenericTypeNullArgument() + { + } } } diff --git a/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/TestCaseAttribute.Generic.cs b/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/TestCaseAttribute.Generic.cs new file mode 100644 index 000000000..096766fa0 --- /dev/null +++ b/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.CustomAttributes/TestCaseAttribute.Generic.cs @@ -0,0 +1,24 @@ +using System; + +namespace AsmResolver.DotNet.TestCases.CustomAttributes +{ + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] + public class TestCaseAttribute : Attribute + { + public TestCaseAttribute() + { + Value = default; + } + + public TestCaseAttribute(T value) + { + Value = value; + } + + public T Value + { + get; + set; + } + } +} From 220f611c7da36021899343dd2d0e0b3306675b1b Mon Sep 17 00:00:00 2001 From: Washi Date: Thu, 5 Jan 2023 20:57:05 +0100 Subject: [PATCH 2/4] Incorporate GenericContext into custom attribute argument reader. --- .../CustomAttributeNamedArgument.cs | 4 +- .../Signatures/CustomAttributeSignature.cs | 3 +- .../Signatures/Security/SecurityAttribute.cs | 3 +- .../SerializedCustomAttributeSignature.cs | 29 +++++++++---- .../CustomAttributeTest.cs | 42 ++++++++++++------- 5 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/AsmResolver.DotNet/Signatures/CustomAttributeNamedArgument.cs b/src/AsmResolver.DotNet/Signatures/CustomAttributeNamedArgument.cs index 6d4e08f62..0790e15e5 100644 --- a/src/AsmResolver.DotNet/Signatures/CustomAttributeNamedArgument.cs +++ b/src/AsmResolver.DotNet/Signatures/CustomAttributeNamedArgument.cs @@ -67,9 +67,11 @@ public CustomAttributeArgument Argument /// Reads a single named argument from the input stream. /// /// The blob reader context. + /// /// The input stream. /// The argument. - public static CustomAttributeNamedArgument FromReader(in BlobReaderContext context, ref BinaryStreamReader reader) + public static CustomAttributeNamedArgument FromReader(in BlobReaderContext context, + GenericContext genericContext, ref BinaryStreamReader reader) { var memberType = (CustomAttributeArgumentMemberType) reader.ReadByte(); var argumentType = TypeSignature.ReadFieldOrPropType(context, ref reader); diff --git a/src/AsmResolver.DotNet/Signatures/CustomAttributeSignature.cs b/src/AsmResolver.DotNet/Signatures/CustomAttributeSignature.cs index 1a399f616..eaa877fdb 100644 --- a/src/AsmResolver.DotNet/Signatures/CustomAttributeSignature.cs +++ b/src/AsmResolver.DotNet/Signatures/CustomAttributeSignature.cs @@ -90,8 +90,9 @@ public static CustomAttributeSignature FromReader( ICustomAttributeType ctor, in BinaryStreamReader reader) { + var genericContext = GenericContext.FromMethod(ctor); var argumentTypes = ctor.Signature?.ParameterTypes ?? Array.Empty(); - return new SerializedCustomAttributeSignature(context, argumentTypes, reader); + return new SerializedCustomAttributeSignature(context, argumentTypes, genericContext, reader); } /// diff --git a/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs b/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs index abb55b287..68a7038d6 100644 --- a/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs +++ b/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs @@ -38,9 +38,10 @@ public static SecurityAttribute FromReader(in BlobReaderContext context, ref Bin return result; } + var genericContext = GenericContext.FromType(type); for (int i = 0; i < namedArgumentCount; i++) { - var argument = CustomAttributeNamedArgument.FromReader(context, ref reader); + var argument = CustomAttributeNamedArgument.FromReader(context, genericContext, ref reader); result.NamedArguments.Add(argument); } diff --git a/src/AsmResolver.DotNet/Signatures/SerializedCustomAttributeSignature.cs b/src/AsmResolver.DotNet/Signatures/SerializedCustomAttributeSignature.cs index a7e6e6028..91b35e32c 100644 --- a/src/AsmResolver.DotNet/Signatures/SerializedCustomAttributeSignature.cs +++ b/src/AsmResolver.DotNet/Signatures/SerializedCustomAttributeSignature.cs @@ -10,22 +10,25 @@ namespace AsmResolver.DotNet.Signatures /// public class SerializedCustomAttributeSignature : CustomAttributeSignature { - private readonly BlobReaderContext _context; + private readonly BlobReaderContext _readerContext; + private readonly GenericContext _genericContext; private readonly TypeSignature[] _fixedArgTypes; private readonly BinaryStreamReader _reader; /// /// Initializes a new lazy custom attribute signature from an input blob stream reader. /// - /// The blob reading context the signature is situated in. + /// The blob reading context the signature is situated in. /// The types of all fixed arguments. + /// /// The input blob reader. - public SerializedCustomAttributeSignature( - in BlobReaderContext context, + public SerializedCustomAttributeSignature(in BlobReaderContext readerContext, IEnumerable fixedArgTypes, + in GenericContext genericContext, in BinaryStreamReader reader) { - _context = context; + _readerContext = readerContext; + _genericContext = genericContext; _fixedArgTypes = fixedArgTypes.ToArray(); _reader = reader; } @@ -40,16 +43,26 @@ protected override void Initialize( // Verify magic header. ushort prologue = reader.ReadUInt16(); if (prologue != CustomAttributeSignaturePrologue) - _context.ReaderContext.BadImage("Input stream does not point to a valid custom attribute signature."); + _readerContext.ReaderContext.BadImage("Input stream does not point to a valid custom attribute signature."); // Read fixed arguments. for (int i = 0; i < _fixedArgTypes.Length; i++) - fixedArguments.Add(CustomAttributeArgument.FromReader(_context, _fixedArgTypes[i], ref reader)); + { + fixedArguments.Add(CustomAttributeArgument.FromReader( + _readerContext, + _fixedArgTypes[i].InstantiateGenericTypes(_genericContext), + ref reader)); + } // Read named arguments. ushort namedArgumentCount = reader.ReadUInt16(); for (int i = 0; i < namedArgumentCount; i++) - namedArguments.Add(CustomAttributeNamedArgument.FromReader(_context, ref reader)); + { + namedArguments.Add(CustomAttributeNamedArgument.FromReader( + _readerContext, + _genericContext, + ref reader)); + } } /// diff --git a/test/AsmResolver.DotNet.Tests/CustomAttributeTest.cs b/test/AsmResolver.DotNet.Tests/CustomAttributeTest.cs index 6c57703a7..b93e25f7e 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 == attributeName); + .First(c => c.Constructor!.DeclaringType!.Name.Value.StartsWith(attributeName)); if (access) { @@ -477,7 +477,8 @@ public void CreateNewWithFixedArgumentsViaProperty() [InlineData(true, true)] public void FixedGenericInt32Argument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericInt32Argument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericInt32Argument), + rebuild, access, true); var argument = attribute.Signature!.FixedArguments[0]; int value = Assert.IsAssignableFrom(argument.Element); @@ -490,10 +491,11 @@ public void FixedGenericInt32Argument(bool rebuild, bool access) [InlineData(true, true)] public void FixedGenericStringArgument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericStringArgument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericStringArgument), + rebuild, access, true); var argument = attribute.Signature!.FixedArguments[0]; - string value = Assert.IsAssignableFrom(argument.Element); + string value = Assert.IsAssignableFrom(argument.Element); Assert.Equal("Fixed string generic argument", value); } @@ -503,7 +505,8 @@ public void FixedGenericStringArgument(bool rebuild, bool access) [InlineData(true, true)] public void FixedGenericInt32ArrayArgument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericInt32ArrayArgument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericInt32ArrayArgument), + rebuild, access, true); var argument = attribute.Signature!.FixedArguments[0]; Assert.Equal(new int[] {1, 2, 3, 4}, argument.Elements.Cast()); @@ -515,7 +518,8 @@ public void FixedGenericInt32ArrayArgument(bool rebuild, bool access) [InlineData(true, true)] public void FixedGenericInt32ArrayAsObjectArgument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericInt32ArrayAsObjectArgument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericInt32ArrayAsObjectArgument), + rebuild, access, true); var argument = attribute.Signature!.FixedArguments[0]; var boxedArgument = Assert.IsAssignableFrom(argument.Element); @@ -531,7 +535,8 @@ public void FixedGenericInt32ArrayAsObjectArgument(bool rebuild, bool access) [InlineData(true, true)] public void FixedGenericTypeArgument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericTypeArgument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericTypeArgument), + rebuild, access, true); var argument = attribute.Signature!.FixedArguments[0]; var expected = attribute.Constructor!.Module!.CorLibTypeFactory.Int32; @@ -545,7 +550,8 @@ public void FixedGenericTypeArgument(bool rebuild, bool access) [InlineData(true, true)] public void FixedGenericTypeNullArgument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericTypeNullArgument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.FixedGenericTypeNullArgument), + rebuild, access, true); var argument = attribute.Signature!.FixedArguments[0]; Assert.Null(argument.Element); @@ -557,7 +563,8 @@ public void FixedGenericTypeNullArgument(bool rebuild, bool access) [InlineData(true, true)] public void NamedGenericInt32Argument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericInt32Argument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericInt32Argument), + rebuild, access, true); var argument = attribute.Signature!.NamedArguments[0]; Assert.Equal("Value", argument.MemberName); @@ -571,11 +578,12 @@ public void NamedGenericInt32Argument(bool rebuild, bool access) [InlineData(true, true)] public void NamedGenericStringArgument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericStringArgument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericStringArgument), + rebuild, access, true); var argument = attribute.Signature!.NamedArguments[0]; Assert.Equal("Value", argument.MemberName); - string value = Assert.IsAssignableFrom(argument.Argument.Element); + string value = Assert.IsAssignableFrom(argument.Argument.Element); Assert.Equal("Named string generic argument", value); } @@ -585,7 +593,8 @@ public void NamedGenericStringArgument(bool rebuild, bool access) [InlineData(true, true)] public void NamedGenericInt32ArrayArgument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericInt32ArrayArgument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericInt32ArrayArgument), + rebuild, access, true); var argument = attribute.Signature!.NamedArguments[0]; Assert.Equal("Value", argument.MemberName); @@ -598,7 +607,8 @@ public void NamedGenericInt32ArrayArgument(bool rebuild, bool access) [InlineData(true, true)] public void NamedGenericInt32ArrayAsObjectArgument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericInt32ArrayAsObjectArgument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericInt32ArrayAsObjectArgument), + rebuild, access, true); var argument = attribute.Signature!.NamedArguments[0]; Assert.Equal("Value", argument.MemberName); @@ -615,7 +625,8 @@ public void NamedGenericInt32ArrayAsObjectArgument(bool rebuild, bool access) [InlineData(true, true)] public void NamedGenericTypeArgument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericTypeArgument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericTypeArgument), + rebuild, access, true); var argument = attribute.Signature!.NamedArguments[0]; var expected = attribute.Constructor!.Module!.CorLibTypeFactory.Int32; @@ -629,7 +640,8 @@ public void NamedGenericTypeArgument(bool rebuild, bool access) [InlineData(true, true)] public void NamedGenericTypeNullArgument(bool rebuild, bool access) { - var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericTypeNullArgument), rebuild, access); + var attribute = GetCustomAttributeTestCase(nameof(CustomAttributesTestClass.NamedGenericTypeNullArgument), + rebuild, access, true); var argument = attribute.Signature!.NamedArguments[0]; Assert.Null(argument.Argument.Element); From d72edea8bbd6cda38eaa542dd5c79958a6fa0f43 Mon Sep 17 00:00:00 2001 From: Washi Date: Thu, 5 Jan 2023 21:03:13 +0100 Subject: [PATCH 3/4] Remove redundant generic context parameter for named arguments. --- .../Signatures/CustomAttributeNamedArgument.cs | 4 +--- .../Signatures/Security/SecurityAttribute.cs | 2 +- .../SerializedCustomAttributeSignature.cs | 15 ++++----------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/AsmResolver.DotNet/Signatures/CustomAttributeNamedArgument.cs b/src/AsmResolver.DotNet/Signatures/CustomAttributeNamedArgument.cs index 0790e15e5..6d4e08f62 100644 --- a/src/AsmResolver.DotNet/Signatures/CustomAttributeNamedArgument.cs +++ b/src/AsmResolver.DotNet/Signatures/CustomAttributeNamedArgument.cs @@ -67,11 +67,9 @@ public CustomAttributeArgument Argument /// Reads a single named argument from the input stream. /// /// The blob reader context. - /// /// The input stream. /// The argument. - public static CustomAttributeNamedArgument FromReader(in BlobReaderContext context, - GenericContext genericContext, ref BinaryStreamReader reader) + public static CustomAttributeNamedArgument FromReader(in BlobReaderContext context, ref BinaryStreamReader reader) { var memberType = (CustomAttributeArgumentMemberType) reader.ReadByte(); var argumentType = TypeSignature.ReadFieldOrPropType(context, ref reader); diff --git a/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs b/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs index 68a7038d6..4631a5925 100644 --- a/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs +++ b/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs @@ -41,7 +41,7 @@ public static SecurityAttribute FromReader(in BlobReaderContext context, ref Bin var genericContext = GenericContext.FromType(type); for (int i = 0; i < namedArgumentCount; i++) { - var argument = CustomAttributeNamedArgument.FromReader(context, genericContext, ref reader); + var argument = CustomAttributeNamedArgument.FromReader(context, ref reader); result.NamedArguments.Add(argument); } diff --git a/src/AsmResolver.DotNet/Signatures/SerializedCustomAttributeSignature.cs b/src/AsmResolver.DotNet/Signatures/SerializedCustomAttributeSignature.cs index 91b35e32c..4dfadd299 100644 --- a/src/AsmResolver.DotNet/Signatures/SerializedCustomAttributeSignature.cs +++ b/src/AsmResolver.DotNet/Signatures/SerializedCustomAttributeSignature.cs @@ -20,7 +20,7 @@ public class SerializedCustomAttributeSignature : CustomAttributeSignature /// /// The blob reading context the signature is situated in. /// The types of all fixed arguments. - /// + /// The generic context the arguments live in. /// The input blob reader. public SerializedCustomAttributeSignature(in BlobReaderContext readerContext, IEnumerable fixedArgTypes, @@ -48,21 +48,14 @@ protected override void Initialize( // Read fixed arguments. for (int i = 0; i < _fixedArgTypes.Length; i++) { - fixedArguments.Add(CustomAttributeArgument.FromReader( - _readerContext, - _fixedArgTypes[i].InstantiateGenericTypes(_genericContext), - ref reader)); + var instantiatedType = _fixedArgTypes[i].InstantiateGenericTypes(_genericContext); + fixedArguments.Add(CustomAttributeArgument.FromReader(_readerContext, instantiatedType, ref reader)); } // Read named arguments. ushort namedArgumentCount = reader.ReadUInt16(); for (int i = 0; i < namedArgumentCount; i++) - { - namedArguments.Add(CustomAttributeNamedArgument.FromReader( - _readerContext, - _genericContext, - ref reader)); - } + namedArguments.Add(CustomAttributeNamedArgument.FromReader(_readerContext, ref reader)); } /// From d1d53e71380c12d69c33829f3dd5fb775ee458c5 Mon Sep 17 00:00:00 2001 From: Washi Date: Wed, 11 Jan 2023 22:06:23 +0100 Subject: [PATCH 4/4] Remove redundant code in security attribute. --- .../Signatures/Security/SecurityAttribute.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs b/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs index 4631a5925..8ec14c011 100644 --- a/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs +++ b/src/AsmResolver.DotNet/Signatures/Security/SecurityAttribute.cs @@ -38,12 +38,8 @@ public static SecurityAttribute FromReader(in BlobReaderContext context, ref Bin return result; } - var genericContext = GenericContext.FromType(type); for (int i = 0; i < namedArgumentCount; i++) - { - var argument = CustomAttributeNamedArgument.FromReader(context, ref reader); - result.NamedArguments.Add(argument); - } + result.NamedArguments.Add(CustomAttributeNamedArgument.FromReader(context, ref reader)); return result; }