From 55f3d411b3ca83b23091ee3ce963ff072539b8a5 Mon Sep 17 00:00:00 2001 From: Samuele Lorefice Date: Wed, 26 Feb 2025 18:58:29 +0100 Subject: [PATCH] Added documentation to Attribute builder. Added Inheritance methods. Added a base DNA attribute to GenerateTypeDeclarations method. --- CodeGenerator/AttributeBuilder.cs | 96 ++++++++++++++++++++++++++++++- CodeGenerator/Program.cs | 21 ++++++- 2 files changed, 115 insertions(+), 2 deletions(-) diff --git a/CodeGenerator/AttributeBuilder.cs b/CodeGenerator/AttributeBuilder.cs index 2ba97bc..c97007f 100644 --- a/CodeGenerator/AttributeBuilder.cs +++ b/CodeGenerator/AttributeBuilder.cs @@ -3,23 +3,49 @@ using System.CodeDom; using System.Collections.Generic; namespace CodeGenerator { + // ReSharper disable always BitwiseOperatorOnEnumWithoutFlags public class AttributeBuilder { private CodeTypeDeclaration _attrDecl = new(); private List<(Type, string)> _fields = new(); + + /// + /// List of fields registered for the attribute currently being built. + /// + /// Each tuple contains the type of the field and the name of the field + public List<(Type, string)> Fields => _fields; + private List<(Type, string, string)> _properties = new(); + /// + /// List of properties registered for the attribute currently being built. + /// + /// Each tuple contains the type of the property, the name of the property and the name of the backing field + public List<(Type, string, string)> Properties => _properties; + + /// + /// Creates a new instance of the class. + /// public AttributeBuilder() { _attrDecl.IsClass = true; _attrDecl.Attributes = MemberAttributes.Public; _attrDecl.BaseTypes.Add(typeof(Attribute)); } + /// + /// Creates a new instance of the class with the specified name for the Attribute. + /// + /// Name the built attribute will have. + /// The set name can be always overridden by using method. public AttributeBuilder(string name) : this() { _attrDecl.Name = name; } + /// + /// Clears the current state of the builder and prepares it for a new attribute declaration. + /// + /// clears the internal metadata for fields and properties, also reinstantiates the internal instance public AttributeBuilder New() { _attrDecl = new CodeTypeDeclaration(); _fields.Clear(); @@ -27,11 +53,37 @@ namespace CodeGenerator { return this; } + /// + /// Sets the base type of the attribute. + /// + /// Fully qualified name from which this is going to be derived + public AttributeBuilder DeriveFromClass(string baseType) { + _attrDecl.BaseTypes[0] = new(baseType); + return this; + } + + /// + /// Adds another base type to the . To be used only with interfaces. + /// + /// Fully qualfied name of the type to add to the BaseTypes list. + public AttributeBuilder Implements(string interfaceName) { + _attrDecl.BaseTypes.Add(interfaceName); + return this; + } + + /// + /// Sets the name of the attribute that will be generated. + /// + /// Name the attribute will have. public AttributeBuilder SetName(string name) { _attrDecl.Name = name; return this; } + /// + /// Sets the for the attribute being generated. + /// + /// List of arguments for public AttributeBuilder SetAttributeUsage(CodeAttributeArgument usageArgs) { var attrUsage = new CodeAttributeDeclaration() { Name = nameof(AttributeUsageAttribute), @@ -41,15 +93,32 @@ namespace CodeGenerator { return this; } - // ReSharper disable always BitwiseOperatorOnEnumWithoutFlags + /// + /// Adds a field to the attribute being generated. + /// + /// Name of the field to be added. + /// Visibility parameters, OR'd sequence of + /// type of the attribute public AttributeBuilder AddField(string name, MemberAttributes attributes = MemberAttributes.Private | MemberAttributes.Final) => AddField(typeof(T), name, attributes); + /// + /// Adds a field to the attribute being generated. + /// + /// Type of the attribute. Must be a base type or a fully qualified name + /// Name of the field to be added. + /// Visibility parameters, OR'd sequence of public AttributeBuilder AddField(string type, string name, MemberAttributes attributes = MemberAttributes.Private | MemberAttributes.Final) => AddField(Type.GetType(type), name, attributes); + /// + /// Adds a field to the attribute being generated. + /// + /// Type of the attribute. Must be a base type or a fully qualified name + /// Name of the field to be added. + /// Visibility parameters, OR'd sequence of public AttributeBuilder AddField(Type type, string name, MemberAttributes attributes = MemberAttributes.Private | MemberAttributes.Final) { var field = new CodeMemberField(type, name); @@ -59,11 +128,29 @@ namespace CodeGenerator { return this; } + /// + /// Adds an auto-property to the attribute being generated. + /// + /// Type of the attribute. Must be a base type or a fully qualified name + /// Name of the property to be added. + /// Visibility parameters, OR'd sequence of + /// Whether the property should have a getter + /// Whether the property should have a setter + /// This method is a composite call to and public AttributeBuilder AddAutoProperty(Type type, string name, MemberAttributes attributes = MemberAttributes.Public, bool get = true, bool set = true) { AddField(type, $"_{name}", MemberAttributes.Private); return AddProperty(type, name, $"_{name}", attributes, get, set); } + /// + /// Adds a property to the attribute being generated. + /// + /// Type of the attribute. Must be a base type or a fully qualified name + /// Name of the property to be added. + /// Name of the backing field for the property + /// Visibility parameters, OR'd sequence of + /// Whether the property should have a getter + /// Whether the property should have a setter public AttributeBuilder AddProperty(Type type, string name, string backingPropertyName, MemberAttributes attributes = MemberAttributes.Public, bool get = true, bool set = true) { var prop = new CodeMemberProperty { @@ -94,6 +181,9 @@ namespace CodeGenerator { return this; } + /// + /// Adds a constructor to all the properties inside the attribute being generated. + /// public AttributeBuilder AddPropertiesConstructor() { var ctor = new CodeConstructor { Attributes = MemberAttributes.Public }; _attrDecl.Members.Add(ctor); @@ -107,6 +197,10 @@ namespace CodeGenerator { return this; } + /// + /// Builds the instance. + /// + /// Instance of the built by the builder. public CodeTypeDeclaration Build() => _attrDecl; } } \ No newline at end of file diff --git a/CodeGenerator/Program.cs b/CodeGenerator/Program.cs index 58be9cf..3ff5d04 100644 --- a/CodeGenerator/Program.cs +++ b/CodeGenerator/Program.cs @@ -21,6 +21,7 @@ namespace CodeGenerator { private const string OutPath = @"GeneratedOutput"; private const string Namespace = "BlendFile"; private static HashSet _customTypes; + private static readonly string[] ListLenghtStr = {"count", "length", "size"}; private static void Log(string message) { @@ -142,12 +143,18 @@ namespace CodeGenerator { var attributeBuilder = new AttributeBuilder(); var typeDeclarations = new CodeTypeDeclaration[] { + attributeBuilder.New().SetName("DNAAttribute") + .SetAttributeUsage(new (new CodeSnippetExpression("AttributeTargets.All"))) + .AddAutoProperty(typeof(int), "OriginalIndex") + .AddAutoProperty(typeof(string), "OriginalName") + .AddPropertiesConstructor() + .Build(), attributeBuilder.New().SetName("DNAFieldAttribute") .SetAttributeUsage(new (new CodeSnippetExpression("AttributeTargets.Field"))) .AddAutoProperty(typeof(int), "Size") .AddAutoProperty(typeof(string), "OriginalType") - .AddAutoProperty(typeof(string), "OriginalName") .AddAutoProperty(typeof(int), "OriginalIndex") + .AddAutoProperty(typeof(string), "OriginalName") .AddAutoProperty(typeof(string), "UnderlyingType") .AddAutoProperty(typeof(bool), "IsPointer") .AddAutoProperty(typeof(int), "MemoryOffset") @@ -155,9 +162,21 @@ namespace CodeGenerator { .Build(), attributeBuilder.New().SetName("DNAClassAttribute") .SetAttributeUsage(new (new CodeSnippetExpression("AttributeTargets.Class | AttributeTargets.Struct"))) + .AddAutoProperty(typeof(int), "Size") .AddAutoProperty(typeof(int), "OriginalIndex") .AddAutoProperty(typeof(string), "OriginalName") + .AddPropertiesConstructor() + .Build(), + attributeBuilder.New().SetName("DNAListAttribute") + .SetAttributeUsage(new (new CodeSnippetExpression("AttributeTargets.Property | AttributeTargets.Field"))) .AddAutoProperty(typeof(int), "Size") + .AddAutoProperty(typeof(string), "OriginalType") + .AddAutoProperty(typeof(string), "OriginalName") + .AddAutoProperty(typeof(int), "OriginalIndex") + .AddAutoProperty(typeof(string), "UnderlyingType") + .AddAutoProperty(typeof(string), "CountFieldName") + .AddAutoProperty(typeof(int), "CountFieldIndex") + .AddAutoProperty(typeof(int), "MemoryOffset") .AddPropertiesConstructor() .Build() };