From 3f721a17c1b9ff5a34a7fcebbaab8ea4655b2e19 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 18 Apr 2021 14:33:39 +0200 Subject: [PATCH] Add support for System.Runtime.CompilerServices.SpecialNameAttribute --- .../TestCases/ILPretty/FSharpLoops_Debug.cs | 2 ++ .../TestCases/ILPretty/FSharpLoops_Release.cs | 2 ++ .../TypeSystem/TypeSystemLoaderTests.cs | 30 ++++++++++++++++++- .../TypeSystem/TypeSystemTestCase.cs | 24 +++++++++++++++ .../Implementation/KnownAttributes.cs | 2 ++ .../Implementation/MetadataEvent.cs | 7 +++++ .../Implementation/MetadataField.cs | 6 ++++ .../Implementation/MetadataMethod.cs | 7 +++++ .../Implementation/MetadataProperty.cs | 8 +++++ .../Implementation/MetadataTypeDefinition.cs | 6 ++++ 10 files changed, 93 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs index 9ba4da06a..c2a148c2a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs @@ -32,6 +32,7 @@ using Microsoft.FSharp.Core.CompilerServices; public static class Program { [Serializable] + [SpecialName] [CompilationMapping(SourceConstructFlags.Closure)] internal sealed class disposable_00403 : IDisposable { @@ -47,6 +48,7 @@ public static class Program } [Serializable] + [SpecialName] [CompilationMapping(SourceConstructFlags.Closure)] internal sealed class getSeq_00405 : GeneratedSequenceBase { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs index da54a4b4c..eb885b071 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs @@ -33,6 +33,7 @@ using Microsoft.FSharp.Core.CompilerServices; public static class Program { [Serializable] + [SpecialName] [CompilationMapping(SourceConstructFlags.Closure)] internal sealed class disposable_00403 : IDisposable { @@ -48,6 +49,7 @@ public static class Program } [Serializable] + [SpecialName] [CompilationMapping(SourceConstructFlags.Closure)] internal sealed class getSeq_00405 : GeneratedSequenceBase { diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs index a0e9fc773..84b4252bd 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs @@ -90,7 +90,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.IsFalse(c.IsAbstract); Assert.IsFalse(c.IsSealed); Assert.IsFalse(c.IsStatic); - //Assert.IsFalse(c.IsShadowing); + Assert.IsFalse(c.HasAttribute(KnownAttribute.SpecialName)); } [Test] @@ -109,6 +109,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.AreEqual(0, method.GetAttributes().Count()); Assert.IsTrue(method.HasBody); Assert.IsNull(method.AccessorOwner); + Assert.IsFalse(method.HasAttribute(KnownAttribute.SpecialName)); } [Test] @@ -127,6 +128,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.AreEqual(0, method.GetAttributes().Count()); Assert.IsTrue(method.HasBody); Assert.IsNull(method.AccessorOwner); + Assert.IsFalse(method.HasAttribute(KnownAttribute.SpecialName)); } [Test] @@ -145,6 +147,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.AreEqual(1, method.GetAttributes().Count()); Assert.IsTrue(method.HasBody); Assert.IsNull(method.AccessorOwner); + Assert.IsFalse(method.HasAttribute(KnownAttribute.SpecialName)); } [Test] @@ -403,6 +406,9 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); Assert.AreEqual(Accessibility.Private, p.Setter.Accessibility); Assert.IsTrue(p.Getter.HasBody); + Assert.IsFalse(p.HasAttribute(KnownAttribute.SpecialName)); + Assert.IsFalse(p.Getter.HasAttribute(KnownAttribute.SpecialName)); + Assert.IsFalse(p.Setter.HasAttribute(KnownAttribute.SpecialName)); } [Test] @@ -1958,5 +1964,27 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.AreEqual(TypeKind.Class, multicastDelegate); Assert.IsFalse(multicastDelegate.IsSealed); } + + [Test] + public void HasSpecialName() + { + var nonCustomAttributes = compilation.FindType(typeof(NonCustomAttributes)).GetDefinition(); + + var method = nonCustomAttributes.GetMethods(m => m.Name == "SpecialNameMethod").Single(); + var property = nonCustomAttributes.GetProperties(p => p.Name == "SpecialNameProperty").Single(); + var @event = nonCustomAttributes.GetEvents(e => e.Name == "SpecialNameEvent").Single(); + var field = nonCustomAttributes.GetFields(f => f.Name == "SpecialNameField").Single(); + + var @class = nonCustomAttributes.GetNestedTypes(t => t.Name == "SpecialNameClass").Single().GetDefinition(); + var @struct = nonCustomAttributes.GetNestedTypes(t => t.Name == "SpecialNameStruct").Single().GetDefinition(); + + Assert.IsTrue(method.HasAttribute(KnownAttribute.SpecialName)); + Assert.IsTrue(property.HasAttribute(KnownAttribute.SpecialName)); + Assert.IsTrue(@event.HasAttribute(KnownAttribute.SpecialName)); + Assert.IsTrue(field.HasAttribute(KnownAttribute.SpecialName)); + + Assert.IsTrue(@class.HasAttribute(KnownAttribute.SpecialName)); + Assert.IsTrue(@struct.HasAttribute(KnownAttribute.SpecialName)); + } } } diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs index d6f54d953..1a55b5cce 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs @@ -148,9 +148,28 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem [Serializable] public class NonCustomAttributes { + [SpecialName] + public class SpecialNameClass + { + } + + [SpecialName] + public struct SpecialNameStruct + { + } + [NonSerialized] public readonly int NonSerializedField; + [SpecialName] + public readonly int SpecialNameField; + + [SpecialName] + public event EventHandler SpecialNameEvent; + + [SpecialName] + public int SpecialNameProperty { get; set; } + [DllImport("unmanaged.dll", CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DllMethod([In, Out] ref int p); @@ -162,6 +181,11 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public static void PreserveSigAsAttribute() { } + + [SpecialName] + public static void SpecialNameMethod() + { + } } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8)] diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs index e73f0ec3d..aae66c064 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs @@ -45,6 +45,7 @@ namespace ICSharpCode.Decompiler.TypeSystem Conditional, Obsolete, IsReadOnly, + SpecialName, DebuggerHidden, DebuggerStepThrough, @@ -119,6 +120,7 @@ namespace ICSharpCode.Decompiler.TypeSystem new TopLevelTypeName("System.Diagnostics", nameof(ConditionalAttribute)), new TopLevelTypeName("System", nameof(ObsoleteAttribute)), new TopLevelTypeName("System.Runtime.CompilerServices", "IsReadOnlyAttribute"), + new TopLevelTypeName("System.Runtime.CompilerServices", nameof(SpecialNameAttribute)), new TopLevelTypeName("System.Diagnostics", nameof(DebuggerHiddenAttribute)), new TopLevelTypeName("System.Diagnostics", nameof(DebuggerStepThroughAttribute)), // Assembly attributes: diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs index 1ad755cd2..bd4815687 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs @@ -113,6 +113,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var b = new AttributeListBuilder(module); var metadata = module.metadata; var eventDef = metadata.GetEventDefinition(handle); + + // SpecialName + if ((eventDef.Attributes & (EventAttributes.SpecialName | EventAttributes.RTSpecialName)) == EventAttributes.SpecialName) + { + b.Add(KnownAttribute.SpecialName); + } + b.Add(eventDef.GetCustomAttributes(), SymbolKind.Event); return b.Build(); } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs index 16c44187d..1095f0469 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs @@ -152,6 +152,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation b.Add(KnownAttribute.NonSerialized); } + // SpecialName + if ((fieldDef.Attributes & (FieldAttributes.SpecialName | FieldAttributes.RTSpecialName)) == FieldAttributes.SpecialName) + { + b.Add(KnownAttribute.SpecialName); + } + b.AddMarshalInfo(fieldDef.GetMarshallingDescriptor()); b.Add(fieldDef.GetCustomAttributes(), SymbolKind.Field); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs index f153a094c..cccbbe26c 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs @@ -446,6 +446,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } #endregion + // SpecialName + if ((def.Attributes & (MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)) == MethodAttributes.SpecialName + && SymbolKind == SymbolKind.Method) + { + b.Add(KnownAttribute.SpecialName); + } + b.Add(def.GetCustomAttributes(), symbolKind); b.AddSecurityAttributes(def.GetDeclarativeSecurityAttributes()); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs index b0dd16219..f64af4a70 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -205,6 +206,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { b.Add(KnownAttribute.IndexerName, KnownTypeCode.String, Name); } + + // SpecialName + if ((propertyDef.Attributes & (PropertyAttributes.SpecialName | PropertyAttributes.RTSpecialName)) == PropertyAttributes.SpecialName) + { + b.Add(KnownAttribute.SpecialName); + } + b.Add(propertyDef.GetCustomAttributes(), symbolKind); return b.Build(); } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs index a6c41404e..b5e420f8c 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs @@ -370,6 +370,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation if ((typeDefinition.Attributes & TypeAttributes.Import) != 0) b.Add(KnownAttribute.ComImport); + // SpecialName + if ((typeDefinition.Attributes & (TypeAttributes.SpecialName | TypeAttributes.RTSpecialName)) == TypeAttributes.SpecialName) + { + b.Add(KnownAttribute.SpecialName); + } + #region StructLayoutAttribute LayoutKind layoutKind = LayoutKind.Auto; switch (typeDefinition.Attributes & TypeAttributes.LayoutMask)