diff --git a/CodeGenerator/AttributeBuilder.cs b/CodeGenerator/AttributeBuilder.cs new file mode 100644 index 0000000..278a9d8 --- /dev/null +++ b/CodeGenerator/AttributeBuilder.cs @@ -0,0 +1,106 @@ +using System; +using System.CodeDom; +using System.Collections.Generic; + +namespace CodeGenerator { + public class AttributeBuilder { + + private static AttributeBuilder _instance; + public static AttributeBuilder Instance => _instance ??= new(); + + private CodeTypeDeclaration _attrDecl = new(); + + private List<(Type, string)> _fields = new(); + private List<(Type, string, string)> _properties = new(); + + public AttributeBuilder New() { + _attrDecl.IsClass = true; + _attrDecl.Attributes = MemberAttributes.Public; + _attrDecl.BaseTypes.Add(typeof(Attribute)); + return this; + } + + public AttributeBuilder New(string name) { + New(); + _attrDecl.Name = name; + return this; + } + + public AttributeBuilder SetAttributeUsage(CodeAttributeArgument usageArgs) { + var attrUsage = new CodeAttributeDeclaration() { + Name = nameof(AttributeUsageAttribute), + Arguments = { usageArgs } + }; + _attrDecl.CustomAttributes.Add(attrUsage); + return this; + } + + // ReSharper disable always BitwiseOperatorOnEnumWithoutFlags + public AttributeBuilder AddField(string name, + MemberAttributes attributes = MemberAttributes.Private | MemberAttributes.Final) => + AddField(typeof(T), name, attributes); + + public AttributeBuilder AddField(string type, string name, + MemberAttributes attributes = MemberAttributes.Private | MemberAttributes.Final) => + AddField(Type.GetType(type), name, attributes); + + public AttributeBuilder AddField(Type type, string name, + MemberAttributes attributes = MemberAttributes.Private | MemberAttributes.Final) { + var field = new CodeMemberField(type, name); + field.Attributes = attributes; + _attrDecl.Members.Add(field); + _fields.Add((type, name)); + return this; + } + + 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); + } + + public AttributeBuilder AddProperty(Type type, string name, string backingPropertyName, + MemberAttributes attributes = MemberAttributes.Public, bool get = true, bool set = true) { + var prop = new CodeMemberProperty { + Name = name, + Type = new (type), + Attributes = attributes, + HasGet = get, + HasSet = set + }; + + if (get) { + prop.GetStatements.Add( + new CodeMethodReturnStatement( + new CodeFieldReferenceExpression( + new CodeThisReferenceExpression(), backingPropertyName))); + } + + if (set) { + prop.SetStatements.Add( + new CodeAssignStatement( + new CodeFieldReferenceExpression( + new CodeThisReferenceExpression(), backingPropertyName), + new CodePropertySetValueReferenceExpression())); + } + + _properties.Add((type, name, backingPropertyName)); + _attrDecl.Members.Add(prop); + return this; + } + + public AttributeBuilder AddPropertiesConstructor() { + var ctor = new CodeConstructor { Attributes = MemberAttributes.Public }; + _attrDecl.Members.Add(ctor); + _properties.ForEach(property => { + ctor.Parameters.Add(new (property.Item1, property.Item2)); + ctor.Statements.Add( + new CodeAssignStatement( + new CodeFieldReferenceExpression( + new CodeThisReferenceExpression(), property.Item3), new CodeVariableReferenceExpression(property.Item2))); + }); + return this; + } + + public CodeTypeDeclaration Build() => _attrDecl; + } +} \ No newline at end of file diff --git a/CodeGenerator/Program.cs b/CodeGenerator/Program.cs index 82fe5f2..43ab25b 100644 --- a/CodeGenerator/Program.cs +++ b/CodeGenerator/Program.cs @@ -4,7 +4,6 @@ using System.CodeDom.Compiler; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices.ComTypes; using System.Text; using Kaitai; using Microsoft.CSharp; @@ -139,265 +138,31 @@ namespace CodeGenerator { } private static CodeTypeDeclaration GenerateDNAFieldAttributeType() { - var ctd = new CodeTypeDeclaration("DNAFieldAttribute") { - IsClass = true, - Attributes = MemberAttributes.Public - }; - ctd.BaseTypes.Add(new CodeTypeReference(typeof(Attribute))); - ctd.CustomAttributes.Add(new("AttributeUsage", - new CodeAttributeArgument(new CodeSnippetExpression("AttributeTargets.Field")))); - - var cmf = new CodeMemberField(typeof(int), "_size") { - Attributes = MemberAttributes.Private - }; - ctd.Members.Add(cmf); - - var cmp = new CodeMemberProperty() { - Name = "Size", - Type = new CodeTypeReference(typeof(int)), - Attributes = MemberAttributes.Public, - HasSet = true, - SetStatements = { - new CodeAssignStatement(new CFieldRefExp(new CThisRefExp(), "_size"), new CArgRefExp("value")) - }, - HasGet = true, - GetStatements = { - new CodeMethodReturnStatement(new CFieldRefExp(new CThisRefExp(), "_size")) - } - }; - ctd.Members.Add(cmp); - - cmf = new CodeMemberField(typeof(string), "_originalType") { - Attributes = MemberAttributes.Private - }; - ctd.Members.Add(cmf); - - cmp = new CodeMemberProperty() { - Name = "OriginalType", - Type = new CodeTypeReference(typeof(string)), - Attributes = MemberAttributes.Public, - HasSet = true, - SetStatements = { - new CodeAssignStatement(new CFieldRefExp(new CThisRefExp(), "_originalType"), new CArgRefExp("value")) - }, - HasGet = true, - GetStatements = { - new CodeMethodReturnStatement(new CFieldRefExp(new CThisRefExp(), "_originalType")) - } - }; - ctd.Members.Add(cmp); - - cmf = new CodeMemberField(typeof(string), "_originalName") { - Attributes = MemberAttributes.Private - }; - ctd.Members.Add(cmf); - - cmp = new CodeMemberProperty() { - Name = "OriginalName", - Type = new CodeTypeReference(typeof(string)), - Attributes = MemberAttributes.Public, - HasSet = true, - SetStatements = { - new CodeAssignStatement( - new CFieldRefExp(new CThisRefExp(), "_originalName"), new CArgRefExp("value")) - }, - HasGet = true, - GetStatements = { - new CodeMethodReturnStatement(new CFieldRefExp(new CThisRefExp(), "_originalName")) - } - }; - ctd.Members.Add(cmp); - - cmf = new CodeMemberField(typeof(int), "_originalIndex") { - Attributes = MemberAttributes.Private - }; - ctd.Members.Add(cmf); - - cmp = new CodeMemberProperty() { - Name = "OriginalIndex", - Type = new CodeTypeReference(typeof(int)), - Attributes = MemberAttributes.Public, - HasSet = true, - SetStatements = { - new CodeAssignStatement(new CFieldRefExp(new CThisRefExp(), "_originalIndex"), new CArgRefExp("value")) - }, - HasGet = true, - GetStatements = { - new CodeMethodReturnStatement(new CFieldRefExp(new CThisRefExp(), "_originalIndex")) - } - }; - ctd.Members.Add(cmp); - - cmp = new CodeMemberProperty() { - Name = "UnderlyingType", - Type = new CodeTypeReference(typeof(string)), - Attributes = MemberAttributes.Public, - HasGet = true, - GetStatements = { - new CodeMethodReturnStatement(new CodeSnippetExpression("_originalType")) - }, - HasSet = true, - SetStatements = { - new CodeAssignStatement(new CFieldRefExp(new CThisRefExp(), "_originalType"), new CArgRefExp("value")) - } - }; - ctd.Members.Add(cmp); + var attributeBuilder = AttributeBuilder.Instance; - cmf = new CodeMemberField(typeof(bool), "_isPointer") { - Attributes = MemberAttributes.Private - }; - - ctd.Members.Add(cmf); - - cmp = new CodeMemberProperty() { - Name = "IsPointer", - Type = new CodeTypeReference(typeof(bool)), - Attributes = MemberAttributes.Public, - HasGet = true, - GetStatements = { - new CodeMethodReturnStatement(new CodeSnippetExpression("_isPointer")) - }, - HasSet = true, - SetStatements = { - new CodeAssignStatement(new CFieldRefExp(new CThisRefExp(), "_isPointer"), new CArgRefExp("value")) - } - }; - - ctd.Members.Add(cmp); - - cmf = new CodeMemberField(typeof(int), "_memoryOffset") { - Attributes = MemberAttributes.Private - }; - - cmp = new CodeMemberProperty() { - Name = "MemoryOffset", - Type = new CodeTypeReference(typeof(int)), - Attributes = MemberAttributes.Public, - HasGet = true, - GetStatements = { - new CodeMethodReturnStatement(new CodeSnippetExpression("0")) - }, - HasSet = true, - SetStatements = { - new CodeAssignStatement(new CFieldRefExp(new CThisRefExp(), "_memoryOffset"), new CArgRefExp("value")) - } - }; - - ctd.Members.Add(cmp); - var cc = new CodeConstructor() { Attributes = MemberAttributes.Public }; - - cc.Parameters.AddRange(new CParamDeclExp[] { - new(typeof(int), "originalIndex"), - new(typeof(string), "originalType"), - new(typeof(string), "originalName"), - new(typeof(string), "underlyingType"), - new(typeof(int), "size"), - new(typeof(bool), "isPointer"), - new(typeof(int), "memoryOffset") - }); - - cc.Statements.AddRange(new CodeAssignStatement[] { - new(new CFieldRefExp(new CThisRefExp(), "OriginalIndex"), new CArgRefExp("originalIndex")), - new(new CFieldRefExp(new CThisRefExp(), "OriginalType"), new CArgRefExp("originalType")), - new(new CFieldRefExp(new CThisRefExp(), "OriginalName"), new CArgRefExp("originalName")), - new(new CFieldRefExp(new CThisRefExp(), "OriginalType"), new CArgRefExp("underlyingType")), - new(new CFieldRefExp(new CThisRefExp(), "Size"), new CArgRefExp("size")), - new(new CFieldRefExp(new CThisRefExp(), "IsPointer"), new CArgRefExp("isPointer")), - new(new CFieldRefExp(new CThisRefExp(), "MemoryOffset"), new CArgRefExp("memoryOffset")) - }); - - ctd.Members.Add(cc); - return ctd; + return attributeBuilder.New("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), "UnderlyingType") + .AddAutoProperty(typeof(bool), "IsPointer") + .AddAutoProperty(typeof(int), "MemoryOffset") + .AddPropertiesConstructor() + .Build(); } private static CodeTypeDeclaration GenerateDNAClassAttributeType() { - var ctd = new CodeTypeDeclaration("DNAClassAttribute") { - IsClass = true, - Attributes = MemberAttributes.Public - }; - ctd.BaseTypes.Add(new CodeTypeReference(typeof(Attribute))); - ctd.CustomAttributes.Add(new("AttributeUsage", - new CodeAttributeArgument(new CodeSnippetExpression("AttributeTargets.Class | AttributeTargets.Struct")))); + var attributeBuilder = AttributeBuilder.Instance; - - var cmf = new CodeMemberField(typeof(int), "_originalIndex") { - Attributes = MemberAttributes.Private - }; - ctd.Members.Add(cmf); - - var cmp = new CodeMemberProperty() { - Name = "OriginalIndex", - Type = new CodeTypeReference(typeof(int)), - Attributes = MemberAttributes.Public, - HasSet = true, - SetStatements = { - new CodeAssignStatement(new CFieldRefExp(new CThisRefExp(), "_originalIndex"), new CArgRefExp("value")) - }, - HasGet = true, - GetStatements = { - new CodeMethodReturnStatement(new CFieldRefExp(new CThisRefExp(), "_originalIndex")) - } - }; - ctd.Members.Add(cmp); - - cmf = new CodeMemberField(typeof(string), "_originalName") { - Attributes = MemberAttributes.Private - }; - ctd.Members.Add(cmf); - - cmp = new CodeMemberProperty() { - Name = "OriginalName", - Type = new CodeTypeReference(typeof(string)), - Attributes = MemberAttributes.Public, - HasSet = true, - SetStatements = { - new CodeAssignStatement(new CFieldRefExp(new CThisRefExp(), "_originalName"), new CArgRefExp("value")) - }, - HasGet = true, - GetStatements = { - new CodeMethodReturnStatement(new CFieldRefExp(new CThisRefExp(), "_originalName")) - } - }; - ctd.Members.Add(cmp); - - cmf = new CodeMemberField(typeof(int), "_size") { - Attributes = MemberAttributes.Private - }; - - ctd.Members.Add(cmf); - - cmp = new CodeMemberProperty() { - Name = "Size", - Type = new CodeTypeReference(typeof(int)), - Attributes = MemberAttributes.Public, - HasGet = true, - GetStatements = { - new CodeMethodReturnStatement(new CodeSnippetExpression("_size")) - }, - HasSet = true, - SetStatements = { - new CodeAssignStatement(new CFieldRefExp(new CThisRefExp(), "_size"), new CArgRefExp("value")) - } - }; - - ctd.Members.Add(cmp); - - var cc = new CodeConstructor() { Attributes = MemberAttributes.Public }; - - cc.Parameters.AddRange(new CParamDeclExp[] { - new(typeof(int), "originalIndex"), - new(typeof(string), "originalName"), - new(typeof(int), "size") - }); - - cc.Statements.AddRange(new CodeAssignStatement[] { - new(new CFieldRefExp(new CThisRefExp(), "OriginalIndex"), new CArgRefExp("originalIndex")), - new(new CFieldRefExp(new CThisRefExp(), "OriginalName"), new CArgRefExp("originalName")), - new(new CFieldRefExp(new CThisRefExp(), "Size"), new CArgRefExp("size")) - }); - - ctd.Members.Add(cc); - return ctd; + return attributeBuilder.New("DNAClassAttribute") + .SetAttributeUsage(new (new CodeSnippetExpression("AttributeTargets.Class | AttributeTargets.Struct"))) + .AddAutoProperty(typeof(int), "OriginalIndex") + .AddAutoProperty(typeof(string), "OriginalName") + .AddAutoProperty(typeof(int), "Size") + .AddPropertiesConstructor() + .Build(); } private static CodeAttributeDeclaration GenerateDNAFieldAttribute(int index, BlendFile.DnaField field,