From f26116ac781c0fa2b21673afc10f0625b01552b4 Mon Sep 17 00:00:00 2001 From: CptMoore <39010654+cptmoore@users.noreply.github.com> Date: Wed, 29 Jan 2025 20:18:07 +0100 Subject: [PATCH 1/6] Added OriginalAccessModifierAttribute. --- src/Publicizer/AssemblyEditor.cs | 152 ++++++++++++++++++-- src/Publicizer/PublicizeAssemblies.cs | 56 ++------ src/Publicizer/PublicizerAssemblyContext.cs | 1 + 3 files changed, 160 insertions(+), 49 deletions(-) diff --git a/src/Publicizer/AssemblyEditor.cs b/src/Publicizer/AssemblyEditor.cs index 4bbc802..54220a2 100644 --- a/src/Publicizer/AssemblyEditor.cs +++ b/src/Publicizer/AssemblyEditor.cs @@ -1,13 +1,32 @@ +using System; +using System.Linq; using dnlib.DotNet; +using FieldAttributes = dnlib.DotNet.FieldAttributes; +using MethodAttributes = dnlib.DotNet.MethodAttributes; +using TypeAttributes = dnlib.DotNet.TypeAttributes; namespace Publicizer; /// /// Class for making edits to assemblies and related types. /// -internal static class AssemblyEditor +internal class AssemblyEditor { - internal static bool PublicizeType(TypeDef type) + private readonly ModuleDef _module; + private readonly bool _addOriginalAccessModifierAttribute; + internal AssemblyEditor(ModuleDef module, bool addOriginalAccessModifierAttribute) + { + _module = module; + _addOriginalAccessModifierAttribute = addOriginalAccessModifierAttribute; + } + + internal bool publicizedAnyMemberInAssembly; + internal int publicizedTypesCount; + internal int publicizedPropertiesCount; + internal int publicizedMethodsCount; + internal int publicizedFieldsCount; + + internal bool PublicizeType(TypeDef type) { TypeAttributes oldAttributes = type.Attributes; type.Attributes &= ~TypeAttributes.VisibilityMask; @@ -20,10 +39,17 @@ internal static bool PublicizeType(TypeDef type) { type.Attributes |= TypeAttributes.Public; } - return type.Attributes != oldAttributes; + + if (type.Attributes != oldAttributes) + { + AddOriginalAccessModifierAttribute(type, ConvertAttributes(oldAttributes)); + publicizedTypesCount++; + return true; + } + return false; } - internal static bool PublicizeProperty(PropertyDef property, bool includeVirtual = true) + internal bool PublicizeProperty(PropertyDef property, bool includeVirtual = true) { bool publicized = false; @@ -37,26 +63,136 @@ internal static bool PublicizeProperty(PropertyDef property, bool includeVirtual publicized |= PublicizeMethod(setMethod, includeVirtual); } + if (publicized) + { + publicizedPropertiesCount++; + } return publicized; } - internal static bool PublicizeMethod(MethodDef method, bool includeVirtual = true) + internal bool PublicizeMethod(MethodDef method, bool includeVirtual = true) { if (includeVirtual || !method.IsVirtual) { MethodAttributes oldAttributes = method.Attributes; method.Attributes &= ~MethodAttributes.MemberAccessMask; method.Attributes |= MethodAttributes.Public; - return method.Attributes != oldAttributes; + if (method.Attributes != oldAttributes) + { + AddOriginalAccessModifierAttribute(method, ConvertAttributes(oldAttributes)); + publicizedAnyMemberInAssembly = true; + publicizedMethodsCount++; + return true; + } } return false; } - internal static bool PublicizeField(FieldDef field) + internal bool PublicizeField(FieldDef field) { FieldAttributes oldAttributes = field.Attributes; field.Attributes &= ~FieldAttributes.FieldAccessMask; field.Attributes |= FieldAttributes.Public; - return field.Attributes != oldAttributes; + if (field.Attributes != oldAttributes) + { + AddOriginalAccessModifierAttribute(field, ConvertAttributes(oldAttributes)); + publicizedAnyMemberInAssembly = true; + publicizedFieldsCount++; + return true; + } + return false; + } + + private MethodDef? _attributeConstructor; + private void AddOriginalAccessModifierAttribute(IHasCustomAttribute item, AccessModifier original) + { + if (!_addOriginalAccessModifierAttribute) + { + return; + } + if (_attributeConstructor == null) + { + string @namespace = new UTF8String(nameof(Publicizer)); + string name = new UTF8String("OriginalAccessModifierAttribute"); + TypeDef? attributeTypeDef = _module.Types.FirstOrDefault(t => t.Namespace == @namespace && t.Name == name); + if (attributeTypeDef == null) + { + ITypeDefOrRef attributeBaseTypeRef = _module.Import(typeof(Attribute))!; + attributeTypeDef = new TypeDefUser(@namespace, name, attributeBaseTypeRef); + attributeTypeDef.Attributes = TypeAttributes.NotPublic | TypeAttributes.Sealed; + + var methodSig = MethodSig.CreateInstance( + _module.CorLibTypes.Void, + _module.CorLibTypes.String + ); + var methodDef = new MethodDefUser(".ctor", methodSig); + + attributeTypeDef.Methods.Add(methodDef); + } + _attributeConstructor = attributeTypeDef.FindConstructors().First(); + } + var attribute = new CustomAttribute(_attributeConstructor); + var caArgument = new CAArgument(_module.CorLibTypes.String, AccessModifierToString(original)); + attribute.ConstructorArguments.Add(caArgument); + item.CustomAttributes.Add(attribute); + } + + private static AccessModifier ConvertAttributes(TypeAttributes attributes) + { + attributes &= ~TypeAttributes.VisibilityMask; + return attributes switch + { + TypeAttributes.NotPublic => AccessModifier.Private, + TypeAttributes.Public => AccessModifier.Public, + TypeAttributes.NestedPublic => AccessModifier.Public, + TypeAttributes.NestedPrivate => AccessModifier.Private, + TypeAttributes.NestedFamily => AccessModifier.Protected, + TypeAttributes.NestedAssembly => AccessModifier.Internal, + TypeAttributes.NestedFamANDAssem => AccessModifier.PrivateProtected, + TypeAttributes.NestedFamORAssem => AccessModifier.ProtectedInternal, + _ => AccessModifier.File + }; + } + private static AccessModifier ConvertAttributes(MethodAttributes attributes) + { + // methods and fields share the same visibility mask order and values + return ConvertAttributes((FieldAttributes)attributes); + } + private static AccessModifier ConvertAttributes(FieldAttributes attributes) + { + attributes &= ~FieldAttributes.FieldAccessMask; + return attributes switch + { + FieldAttributes.PrivateScope => AccessModifier.CompilerControlled, + FieldAttributes.Private => AccessModifier.Private, + FieldAttributes.FamANDAssem => AccessModifier.PrivateProtected, + FieldAttributes.Assembly => AccessModifier.Internal, + FieldAttributes.Family => AccessModifier.Protected, + FieldAttributes.FamORAssem => AccessModifier.ProtectedInternal, + FieldAttributes.Public => AccessModifier.Public, + _ => AccessModifier.File + }; + } + // makes it more readable + // corresponds to official documentation + // https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers + private enum AccessModifier + { + Public, Private, Protected, Internal, ProtectedInternal, PrivateProtected, File, CompilerControlled + } + private static string AccessModifierToString(AccessModifier modifier) + { + return modifier switch + { + AccessModifier.Public => "public", + AccessModifier.Private => "private", + AccessModifier.Protected => "protected", + AccessModifier.Internal => "internal", + AccessModifier.ProtectedInternal => "protected internal", + AccessModifier.PrivateProtected => "private protected", + AccessModifier.File => "file", + AccessModifier.CompilerControlled => "[CompilerControlled|PrivateScope]", + _ => throw new ArgumentOutOfRangeException(nameof(modifier), modifier, null) + }; } } diff --git a/src/Publicizer/PublicizeAssemblies.cs b/src/Publicizer/PublicizeAssemblies.cs index 06a58dc..b2d5649 100644 --- a/src/Publicizer/PublicizeAssemblies.cs +++ b/src/Publicizer/PublicizeAssemblies.cs @@ -221,13 +221,9 @@ private static Dictionary GetPublicizerAssemb private static bool PublicizeAssembly(ModuleDef module, PublicizerAssemblyContext assemblyContext, ITaskLogger logger) { - bool publicizedAnyMemberInAssembly = false; var doNotPublicizePropertyMethods = new HashSet(); - int publicizedTypesCount = 0; - int publicizedPropertiesCount = 0; - int publicizedMethodsCount = 0; - int publicizedFieldsCount = 0; + var assemblyEditor = new AssemblyEditor(module, assemblyContext.AddOriginalAccessModifierAttribute); // TYPES foreach (TypeDef? typeDef in module.GetTypes()) @@ -262,11 +258,9 @@ private static bool PublicizeAssembly(ModuleDef module, PublicizerAssemblyContex bool explicitlyPublicizeProperty = assemblyContext.PublicizeMemberPatterns.Contains(propertyName); if (explicitlyPublicizeProperty) { - if (AssemblyEditor.PublicizeProperty(propertyDef)) + if (assemblyEditor.PublicizeProperty(propertyDef)) { publicizedAnyMemberInType = true; - publicizedAnyMemberInAssembly = true; - publicizedPropertiesCount++; logger.Verbose($"Explicitly publicizing property: {propertyName}"); } continue; @@ -296,11 +290,9 @@ private static bool PublicizeAssembly(ModuleDef module, PublicizerAssemblyContex continue; } - if (AssemblyEditor.PublicizeProperty(propertyDef, assemblyContext.IncludeVirtualMembers)) + if (assemblyEditor.PublicizeProperty(propertyDef, assemblyContext.IncludeVirtualMembers)) { publicizedAnyMemberInType = true; - publicizedAnyMemberInAssembly = true; - publicizedPropertiesCount++; } } } @@ -326,11 +318,9 @@ private static bool PublicizeAssembly(ModuleDef module, PublicizerAssemblyContex bool explicitlyPublicizeMethod = assemblyContext.PublicizeMemberPatterns.Contains(methodName); if (explicitlyPublicizeMethod) { - if (AssemblyEditor.PublicizeMethod(methodDef)) + if (assemblyEditor.PublicizeMethod(methodDef)) { publicizedAnyMemberInType = true; - publicizedAnyMemberInAssembly = true; - publicizedMethodsCount++; logger.Verbose($"Explicitly publicizing method: {methodName}"); } continue; @@ -360,11 +350,9 @@ private static bool PublicizeAssembly(ModuleDef module, PublicizerAssemblyContex continue; } - if (AssemblyEditor.PublicizeMethod(methodDef, assemblyContext.IncludeVirtualMembers)) + if (assemblyEditor.PublicizeMethod(methodDef, assemblyContext.IncludeVirtualMembers)) { publicizedAnyMemberInType = true; - publicizedAnyMemberInAssembly = true; - publicizedMethodsCount++; } } } @@ -384,11 +372,9 @@ private static bool PublicizeAssembly(ModuleDef module, PublicizerAssemblyContex bool explicitlyPublicizeField = assemblyContext.PublicizeMemberPatterns.Contains(fieldName); if (explicitlyPublicizeField) { - if (AssemblyEditor.PublicizeField(fieldDef)) + if (assemblyEditor.PublicizeField(fieldDef)) { publicizedAnyMemberInType = true; - publicizedAnyMemberInAssembly = true; - publicizedFieldsCount++; logger.Verbose($"Explicitly publicizing field: {fieldName}"); } continue; @@ -418,22 +404,16 @@ private static bool PublicizeAssembly(ModuleDef module, PublicizerAssemblyContex continue; } - if (AssemblyEditor.PublicizeField(fieldDef)) + if (assemblyEditor.PublicizeField(fieldDef)) { publicizedAnyMemberInType = true; - publicizedAnyMemberInAssembly = true; - publicizedFieldsCount++; } } } if (publicizedAnyMemberInType) { - if (AssemblyEditor.PublicizeType(typeDef)) - { - publicizedAnyMemberInAssembly = true; - publicizedTypesCount++; - } + assemblyEditor.PublicizeType(typeDef); continue; } @@ -446,10 +426,8 @@ private static bool PublicizeAssembly(ModuleDef module, PublicizerAssemblyContex bool explicitlyPublicizeType = assemblyContext.PublicizeMemberPatterns.Contains(typeName); if (explicitlyPublicizeType) { - if (AssemblyEditor.PublicizeType(typeDef)) + if (assemblyEditor.PublicizeType(typeDef)) { - publicizedAnyMemberInAssembly = true; - publicizedTypesCount++; logger.Verbose($"Explicitly publicizing type: {typeName}"); } continue; @@ -474,20 +452,16 @@ private static bool PublicizeAssembly(ModuleDef module, PublicizerAssemblyContex continue; } - if (AssemblyEditor.PublicizeType(typeDef)) - { - publicizedAnyMemberInAssembly = true; - publicizedTypesCount++; - } + assemblyEditor.PublicizeType(typeDef); } } - logger.Info("Publicized types: " + publicizedTypesCount); - logger.Info("Publicized properties: " + publicizedPropertiesCount); - logger.Info("Publicized methods: " + publicizedMethodsCount); - logger.Info("Publicized fields: " + publicizedFieldsCount); + logger.Info("Publicized types: " + assemblyEditor.publicizedTypesCount); + logger.Info("Publicized properties: " + assemblyEditor.publicizedPropertiesCount); + logger.Info("Publicized methods: " + assemblyEditor.publicizedMethodsCount); + logger.Info("Publicized fields: " + assemblyEditor.publicizedFieldsCount); - return publicizedAnyMemberInAssembly; + return assemblyEditor.publicizedAnyMemberInAssembly; } private static bool IsCompilerGenerated(IHasCustomAttribute memberDef) diff --git a/src/Publicizer/PublicizerAssemblyContext.cs b/src/Publicizer/PublicizerAssemblyContext.cs index 948ff4e..ae8c371 100644 --- a/src/Publicizer/PublicizerAssemblyContext.cs +++ b/src/Publicizer/PublicizerAssemblyContext.cs @@ -14,6 +14,7 @@ internal PublicizerAssemblyContext(string assemblyName) internal bool ExplicitlyPublicizeAssembly { get; set; } = false; internal bool IncludeCompilerGeneratedMembers { get; set; } = true; internal bool IncludeVirtualMembers { get; set; } = true; + internal bool AddOriginalAccessModifierAttribute { get; set; } = true; internal bool ExplicitlyDoNotPublicizeAssembly { get; set; } = false; internal HashSet PublicizeMemberPatterns { get; } = new HashSet(); internal Regex? PublicizeMemberRegexPattern { get; set; } From bc7aa2be4997bcf4e760b228a68b7fdaf4d47a7b Mon Sep 17 00:00:00 2001 From: CptMoore <39010654+cptmoore@users.noreply.github.com> Date: Tue, 11 Feb 2025 18:13:57 +0100 Subject: [PATCH 2/6] Reduce test failure to 1/10. --- src/Publicizer/AssemblyEditor.cs | 58 ++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/src/Publicizer/AssemblyEditor.cs b/src/Publicizer/AssemblyEditor.cs index 54220a2..8343339 100644 --- a/src/Publicizer/AssemblyEditor.cs +++ b/src/Publicizer/AssemblyEditor.cs @@ -13,11 +13,14 @@ namespace Publicizer; internal class AssemblyEditor { private readonly ModuleDef _module; - private readonly bool _addOriginalAccessModifierAttribute; + private readonly MethodDef? _attributeConstructor; internal AssemblyEditor(ModuleDef module, bool addOriginalAccessModifierAttribute) { _module = module; - _addOriginalAccessModifierAttribute = addOriginalAccessModifierAttribute; + if (addOriginalAccessModifierAttribute) + { + _attributeConstructor = CreateAccessModifierAttributeType(module).FindConstructors().First(); + } } internal bool publicizedAnyMemberInAssembly; @@ -103,33 +106,11 @@ internal bool PublicizeField(FieldDef field) return false; } - private MethodDef? _attributeConstructor; private void AddOriginalAccessModifierAttribute(IHasCustomAttribute item, AccessModifier original) { - if (!_addOriginalAccessModifierAttribute) - { - return; - } if (_attributeConstructor == null) { - string @namespace = new UTF8String(nameof(Publicizer)); - string name = new UTF8String("OriginalAccessModifierAttribute"); - TypeDef? attributeTypeDef = _module.Types.FirstOrDefault(t => t.Namespace == @namespace && t.Name == name); - if (attributeTypeDef == null) - { - ITypeDefOrRef attributeBaseTypeRef = _module.Import(typeof(Attribute))!; - attributeTypeDef = new TypeDefUser(@namespace, name, attributeBaseTypeRef); - attributeTypeDef.Attributes = TypeAttributes.NotPublic | TypeAttributes.Sealed; - - var methodSig = MethodSig.CreateInstance( - _module.CorLibTypes.Void, - _module.CorLibTypes.String - ); - var methodDef = new MethodDefUser(".ctor", methodSig); - - attributeTypeDef.Methods.Add(methodDef); - } - _attributeConstructor = attributeTypeDef.FindConstructors().First(); + return; } var attribute = new CustomAttribute(_attributeConstructor); var caArgument = new CAArgument(_module.CorLibTypes.String, AccessModifierToString(original)); @@ -137,6 +118,33 @@ private void AddOriginalAccessModifierAttribute(IHasCustomAttribute item, Access item.CustomAttributes.Add(attribute); } + private static TypeDef CreateAccessModifierAttributeType(ModuleDef module) + { + string @namespace = new UTF8String(nameof(Publicizer)); + string name = new UTF8String("OriginalAccessModifierAttribute"); + TypeDef? attributeTypeDef = module.Types.FirstOrDefault(t => t.Namespace == @namespace && t.Name == name); + if (attributeTypeDef == null) + { + ITypeDefOrRef attributeBaseTypeRef = module.Import(typeof(Attribute))!; + attributeTypeDef = new TypeDefUser(@namespace, name, attributeBaseTypeRef); + attributeTypeDef.Attributes = TypeAttributes.NestedAssembly | TypeAttributes.Sealed; + + var methodSig = MethodSig.CreateInstance( + module.CorLibTypes.Void, + module.CorLibTypes.String + ); + var methodDef = new MethodDefUser( + ".ctor", + methodSig, + MethodAttributes.Assembly | MethodAttributes.RTSpecialName + ); + attributeTypeDef.Methods.Add(methodDef); + + module.Types.Add(attributeTypeDef); + } + return attributeTypeDef; + } + private static AccessModifier ConvertAttributes(TypeAttributes attributes) { attributes &= ~TypeAttributes.VisibilityMask; From 02f362702e548a595b6ef9c834c931a22cb36936 Mon Sep 17 00:00:00 2001 From: CptMoore <39010654+cptmoore@users.noreply.github.com> Date: Tue, 11 Feb 2025 19:09:01 +0100 Subject: [PATCH 3/6] Use proper System.Attribute type. --- src/Publicizer/AssemblyEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Publicizer/AssemblyEditor.cs b/src/Publicizer/AssemblyEditor.cs index 8343339..0bb7cab 100644 --- a/src/Publicizer/AssemblyEditor.cs +++ b/src/Publicizer/AssemblyEditor.cs @@ -125,7 +125,7 @@ private static TypeDef CreateAccessModifierAttributeType(ModuleDef module) TypeDef? attributeTypeDef = module.Types.FirstOrDefault(t => t.Namespace == @namespace && t.Name == name); if (attributeTypeDef == null) { - ITypeDefOrRef attributeBaseTypeRef = module.Import(typeof(Attribute))!; + ITypeDefOrRef attributeBaseTypeRef = module.CorLibTypes.GetTypeRef("System", "Attribute"); attributeTypeDef = new TypeDefUser(@namespace, name, attributeBaseTypeRef); attributeTypeDef.Attributes = TypeAttributes.NestedAssembly | TypeAttributes.Sealed; From 29db3f3d9f4c7b0f55eb79a500a04c3989b2ef86 Mon Sep 17 00:00:00 2001 From: CptMoore <39010654+cptmoore@users.noreply.github.com> Date: Wed, 12 Feb 2025 07:23:54 +0100 Subject: [PATCH 4/6] Ignore rider folder and user files. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d2845b1..9fbf6b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .vs bin/ obj/ -*.csproj.user \ No newline at end of file +*.user +.idea/ \ No newline at end of file From 225f2f98dd4518b25fa180dbabb9920939c43ebe Mon Sep 17 00:00:00 2001 From: CptMoore <39010654+cptmoore@users.noreply.github.com> Date: Wed, 12 Feb 2025 07:24:31 +0100 Subject: [PATCH 5/6] Do not add access modifier attributes to core libs. --- src/Publicizer/AssemblyEditor.cs | 32 ++++++++++++++++++--------- src/Publicizer/PublicizeAssemblies.cs | 9 +++++++- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/Publicizer/AssemblyEditor.cs b/src/Publicizer/AssemblyEditor.cs index 0bb7cab..cb7c225 100644 --- a/src/Publicizer/AssemblyEditor.cs +++ b/src/Publicizer/AssemblyEditor.cs @@ -13,16 +13,26 @@ namespace Publicizer; internal class AssemblyEditor { private readonly ModuleDef _module; - private readonly MethodDef? _attributeConstructor; + private readonly TypeDef? _accessAttributeType; + private readonly MethodDef? _accessAttributeConstructor; internal AssemblyEditor(ModuleDef module, bool addOriginalAccessModifierAttribute) { _module = module; - if (addOriginalAccessModifierAttribute) + + // workaround for custom attributes not being supported in, at least some, core libs + bool isCoreLib = module.IsCoreLibraryModule ?? false; + if (!isCoreLib && addOriginalAccessModifierAttribute) { - _attributeConstructor = CreateAccessModifierAttributeType(module).FindConstructors().First(); + _accessAttributeType = GetOrCreateAccessAttributeType(module); + _accessAttributeConstructor = _accessAttributeType.FindConstructors().First(); } } + internal bool IsAccessAttribute(ITypeDefOrRef typeRef) + { + return typeRef == _accessAttributeType; + } + internal bool publicizedAnyMemberInAssembly; internal int publicizedTypesCount; internal int publicizedPropertiesCount; @@ -108,25 +118,25 @@ internal bool PublicizeField(FieldDef field) private void AddOriginalAccessModifierAttribute(IHasCustomAttribute item, AccessModifier original) { - if (_attributeConstructor == null) + if (_accessAttributeConstructor == null) { return; } - var attribute = new CustomAttribute(_attributeConstructor); + var attribute = new CustomAttribute(_accessAttributeConstructor); var caArgument = new CAArgument(_module.CorLibTypes.String, AccessModifierToString(original)); attribute.ConstructorArguments.Add(caArgument); item.CustomAttributes.Add(attribute); } - private static TypeDef CreateAccessModifierAttributeType(ModuleDef module) + private static readonly string s_accessAttributeNamespace = new UTF8String(nameof(Publicizer)); + private static readonly string s_accessAttributeName = new UTF8String("OriginalAccessModifierAttribute"); + private static TypeDef GetOrCreateAccessAttributeType(ModuleDef module) { - string @namespace = new UTF8String(nameof(Publicizer)); - string name = new UTF8String("OriginalAccessModifierAttribute"); - TypeDef? attributeTypeDef = module.Types.FirstOrDefault(t => t.Namespace == @namespace && t.Name == name); + TypeDef? attributeTypeDef = module.Types.FirstOrDefault(t => t.Namespace == s_accessAttributeNamespace && t.Name == s_accessAttributeName); if (attributeTypeDef == null) { ITypeDefOrRef attributeBaseTypeRef = module.CorLibTypes.GetTypeRef("System", "Attribute"); - attributeTypeDef = new TypeDefUser(@namespace, name, attributeBaseTypeRef); + attributeTypeDef = new TypeDefUser(s_accessAttributeNamespace, s_accessAttributeName, attributeBaseTypeRef); attributeTypeDef.Attributes = TypeAttributes.NestedAssembly | TypeAttributes.Sealed; var methodSig = MethodSig.CreateInstance( @@ -136,7 +146,7 @@ private static TypeDef CreateAccessModifierAttributeType(ModuleDef module) var methodDef = new MethodDefUser( ".ctor", methodSig, - MethodAttributes.Assembly | MethodAttributes.RTSpecialName + MethodAttributes.Assembly | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig ); attributeTypeDef.Methods.Add(methodDef); diff --git a/src/Publicizer/PublicizeAssemblies.cs b/src/Publicizer/PublicizeAssemblies.cs index b2d5649..8bc7f72 100644 --- a/src/Publicizer/PublicizeAssemblies.cs +++ b/src/Publicizer/PublicizeAssemblies.cs @@ -226,8 +226,15 @@ private static bool PublicizeAssembly(ModuleDef module, PublicizerAssemblyContex var assemblyEditor = new AssemblyEditor(module, assemblyContext.AddOriginalAccessModifierAttribute); // TYPES - foreach (TypeDef? typeDef in module.GetTypes()) + foreach (TypeDef typeDef in module.GetTypes()) { + if (assemblyEditor.IsAccessAttribute(typeDef)) + { + // do not publicize the access attribute itself, keep it internal + // also avoids the attribute attributing itself + continue; + } + doNotPublicizePropertyMethods.Clear(); bool publicizedAnyMemberInType = false; From 8860d448d9ff71b68f15a49f6c48cbf6e4a3e086 Mon Sep 17 00:00:00 2001 From: CptMoore <39010654+cptmoore@users.noreply.github.com> Date: Fri, 14 Feb 2025 16:57:41 +0100 Subject: [PATCH 6/6] Calling base attribute constructor explicitly. --- src/Publicizer/AssemblyEditor.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Publicizer/AssemblyEditor.cs b/src/Publicizer/AssemblyEditor.cs index cb7c225..8d9eba9 100644 --- a/src/Publicizer/AssemblyEditor.cs +++ b/src/Publicizer/AssemblyEditor.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using dnlib.DotNet; +using dnlib.DotNet.Emit; using FieldAttributes = dnlib.DotNet.FieldAttributes; using MethodAttributes = dnlib.DotNet.MethodAttributes; using TypeAttributes = dnlib.DotNet.TypeAttributes; @@ -135,7 +136,13 @@ private static TypeDef GetOrCreateAccessAttributeType(ModuleDef module) TypeDef? attributeTypeDef = module.Types.FirstOrDefault(t => t.Namespace == s_accessAttributeNamespace && t.Name == s_accessAttributeName); if (attributeTypeDef == null) { - ITypeDefOrRef attributeBaseTypeRef = module.CorLibTypes.GetTypeRef("System", "Attribute"); + TypeRef attributeBaseTypeRef = module.CorLibTypes.GetTypeRef("System", "Attribute"); + MemberRef attributeBaseConstructorMethodRef = new MemberRefUser( + module, + ".ctor", + MethodSig.CreateInstance(module.CorLibTypes.Void), + attributeBaseTypeRef + ); attributeTypeDef = new TypeDefUser(s_accessAttributeNamespace, s_accessAttributeName, attributeBaseTypeRef); attributeTypeDef.Attributes = TypeAttributes.NestedAssembly | TypeAttributes.Sealed; @@ -148,6 +155,12 @@ private static TypeDef GetOrCreateAccessAttributeType(ModuleDef module) methodSig, MethodAttributes.Assembly | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig ); + + CilBody body = methodDef.Body = new CilBody(); + body.Instructions.Add(new Instruction(OpCodes.Ldarg_0)); + body.Instructions.Add(new Instruction(OpCodes.Call, attributeBaseConstructorMethodRef)); + body.Instructions.Add(new Instruction(OpCodes.Ret)); + attributeTypeDef.Methods.Add(methodDef); module.Types.Add(attributeTypeDef);