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);