Beispiel #1
0
        private void CreateFieldProperty(int index, AbideTagField field)
        {
            if (field == null)
            {
                throw new ArgumentNullException(nameof(field));
            }
            if (string.IsNullOrEmpty(field.Name))
            {
                return;
            }

            Type returnType = null;

            switch (field.FieldType)
            {
            case FieldType.FieldString:
            case FieldType.FieldLongString:
            case FieldType.FieldStringId:
                returnType = typeof(string);
                break;

            case FieldType.FieldCharInteger:
                returnType = typeof(byte);
                break;

            case FieldType.FieldShortInteger:
                returnType = typeof(short);
                break;

            case FieldType.FieldLongInteger:
                returnType = typeof(int);
                break;

            case FieldType.FieldAngle:
                returnType = typeof(float);
                break;

            case FieldType.FieldTag:
                returnType = typeof(TagFourCc);
                break;

            case FieldType.FieldCharEnum:
                returnType = typeof(byte);
                break;

            case FieldType.FieldEnum:
                returnType = typeof(short);
                break;

            case FieldType.FieldLongEnum:
                returnType = typeof(int);
                break;

            case FieldType.FieldLongFlags:
                returnType = typeof(int);
                break;

            case FieldType.FieldWordFlags:
                returnType = typeof(short);
                break;

            case FieldType.FieldByteFlags:
                returnType = typeof(byte);
                break;

            case FieldType.FieldPoint2D:
                returnType = typeof(Point2);
                break;

            case FieldType.FieldRectangle2D:
                returnType = typeof(Rectangle2);
                break;

            case FieldType.FieldRgbColor:
                returnType = typeof(ColorRgb);
                break;

            case FieldType.FieldArgbColor:
                returnType = typeof(ColorArgb);
                break;

            case FieldType.FieldReal:
            case FieldType.FieldRealFraction:
                returnType = typeof(float);
                break;

            case FieldType.FieldRealPoint2D:
                returnType = typeof(Point2F);
                break;

            case FieldType.FieldRealPoint3D:
                returnType = typeof(Point3F);
                break;

            case FieldType.FieldRealVector2D:
                returnType = typeof(Vector2);
                break;

            case FieldType.FieldRealVector3D:
                returnType = typeof(Vector3);
                break;

            case FieldType.FieldQuaternion:
                returnType = typeof(Quaternion);
                break;

            case FieldType.FieldEulerAngles2D:
                returnType = typeof(Vector2);
                break;

            case FieldType.FieldEulerAngles3D:
                returnType = typeof(Vector3);
                break;
            }

            //Format name
            string originalName = AbideCodeDomGlobals.GeneratePascalCasedName(field.Name);

            if (string.IsNullOrEmpty(originalName))
            {
                return;
            }

            int    nameCount     = 0;
            string formattedName = originalName;

            while (fieldNames.Contains(formattedName))
            {
                formattedName = $"{originalName}{++nameCount}";
            }

            //Add to list
            fieldNames.Add(formattedName);

            //Create field indexer
            CodeIndexerExpression fieldsIndexerExpression = new CodeIndexerExpression(
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), nameof(Block.Fields)));

            fieldsIndexerExpression.Indices.Add(new CodePrimitiveExpression(index));

            //Create field value property expression
            CodePropertyReferenceExpression valuePropRef = new CodePropertyReferenceExpression(
                fieldsIndexerExpression, "Value");

            CodeAssignStatement       setStatement        = new CodeAssignStatement(valuePropRef, new CodePropertySetValueReferenceExpression());
            CodeMethodReturnStatement returnStatement     = null;
            CodeTypeReference         returnTypeReference = null;

            if (returnType != null)
            {
                returnTypeReference = new CodeTypeReference(returnType.Name);
                returnStatement     = new CodeMethodReturnStatement(new CodeCastExpression(
                                                                        new CodeTypeReference(returnType.Name), valuePropRef));
            }
            else
            {
                switch (field.FieldType)
                {
                case FieldType.FieldBlock:
                    returnTypeReference = new CodeTypeReference($"BlockField<{AbideCodeDomGlobals.GetMemberName(field.ReferencedBlock)}>");
                    returnStatement     = new CodeMethodReturnStatement(new CodeCastExpression(
                                                                            returnTypeReference, fieldsIndexerExpression));
                    setStatement = null;
                    break;
                }
            }

            //Check
            if (returnStatement == null | returnTypeReference == null)
            {
                return;
            }

            //Create field property
            CodeMemberProperty fieldMemberProperty = new CodeMemberProperty()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Final,
                Name       = formattedName,
                Type       = returnTypeReference
            };

            fieldMemberProperty.GetStatements.Add(returnStatement);
            if (setStatement != null)
            {
                fieldMemberProperty.SetStatements.Add(setStatement);
            }
            fieldMemberProperty.Comments.Add(new CodeCommentStatement("<summary>", true));
            fieldMemberProperty.Comments.Add(new CodeCommentStatement($"Gets or sets the value of the {field.Name} field.", true));
            fieldMemberProperty.Comments.Add(new CodeCommentStatement("</summary>", true));
            tagGroupCodeTypeDeclaration.Members.Add(fieldMemberProperty);
        }
Beispiel #2
0
        private CodeExpression CreateFieldCreateExpression(AbideTagField tagField)
        {
            //Prepare
            CodeExpression[] optionExpressions     = null;
            CodeExpression   nameExpression        = new CodePrimitiveExpression(tagField.NameObject.ToString());
            CodeExpression   explanationExpression = new CodePrimitiveExpression(tagField.Explanation ?? string.Empty);
            CodeExpression   groupTagExpression    = new CodePrimitiveExpression(tagField.GroupTag);

            //Check
            switch (tagField.FieldType)
            {
            case FieldType.FieldString:
                return(new CodeObjectCreateExpression(new CodeTypeReference("StringField"), nameExpression));

            case FieldType.FieldLongString:
                return(new CodeObjectCreateExpression(new CodeTypeReference("LongStringField"), nameExpression));

            case FieldType.FieldStringId:
                return(new CodeObjectCreateExpression(new CodeTypeReference("StringIdField"), nameExpression));

            case FieldType.FieldOldStringId:
                return(new CodeObjectCreateExpression(new CodeTypeReference("OldStringIdField"), nameExpression));

            case FieldType.FieldCharInteger:
                return(new CodeObjectCreateExpression(new CodeTypeReference("CharIntegerField"), nameExpression));

            case FieldType.FieldShortInteger:
                return(new CodeObjectCreateExpression(new CodeTypeReference("ShortIntegerField"), nameExpression));

            case FieldType.FieldLongInteger:
                return(new CodeObjectCreateExpression(new CodeTypeReference("LongIntegerField"), nameExpression));

            case FieldType.FieldAngle:
                return(new CodeObjectCreateExpression(new CodeTypeReference("AngleField"), nameExpression));

            case FieldType.FieldTag:
                return(new CodeObjectCreateExpression(new CodeTypeReference("TagField"), nameExpression));

            case FieldType.FieldCharEnum:
                optionExpressions    = new CodeExpression[tagField.Options.Count + 1];
                optionExpressions[0] = nameExpression;
                for (int i = 0; i < tagField.Options.Count; i++)
                {
                    optionExpressions[i + 1] = new CodePrimitiveExpression(tagField.Options[i].ToString());
                }
                return(new CodeObjectCreateExpression(new CodeTypeReference("CharEnumField"), optionExpressions));

            case FieldType.FieldEnum:
                optionExpressions    = new CodeExpression[tagField.Options.Count + 1];
                optionExpressions[0] = nameExpression;
                for (int i = 0; i < tagField.Options.Count; i++)
                {
                    optionExpressions[i + 1] = new CodePrimitiveExpression(tagField.Options[i].ToString());
                }
                return(new CodeObjectCreateExpression(new CodeTypeReference("EnumField"), optionExpressions));

            case FieldType.FieldLongEnum:
                optionExpressions    = new CodeExpression[tagField.Options.Count + 1];
                optionExpressions[0] = nameExpression;
                for (int i = 0; i < tagField.Options.Count; i++)
                {
                    optionExpressions[i + 1] = new CodePrimitiveExpression(tagField.Options[i].ToString());
                }
                return(new CodeObjectCreateExpression(new CodeTypeReference("LongEnumField"), optionExpressions));

            case FieldType.FieldLongFlags:
                optionExpressions    = new CodeExpression[tagField.Options.Count + 1];
                optionExpressions[0] = nameExpression;
                for (int i = 0; i < tagField.Options.Count; i++)
                {
                    optionExpressions[i + 1] = new CodePrimitiveExpression(tagField.Options[i].ToString());
                }
                return(new CodeObjectCreateExpression(new CodeTypeReference("LongFlagsField"), optionExpressions));

            case FieldType.FieldWordFlags:
                optionExpressions    = new CodeExpression[tagField.Options.Count + 1];
                optionExpressions[0] = nameExpression;
                for (int i = 0; i < tagField.Options.Count; i++)
                {
                    optionExpressions[i + 1] = new CodePrimitiveExpression(tagField.Options[i].ToString());
                }
                return(new CodeObjectCreateExpression(new CodeTypeReference("WordFlagsField"), optionExpressions));

            case FieldType.FieldByteFlags:
                optionExpressions    = new CodeExpression[tagField.Options.Count + 1];
                optionExpressions[0] = nameExpression;
                for (int i = 0; i < tagField.Options.Count; i++)
                {
                    optionExpressions[i + 1] = new CodePrimitiveExpression(tagField.Options[i].ToString());
                }
                return(new CodeObjectCreateExpression(new CodeTypeReference("ByteFlagsField"), optionExpressions));

            case FieldType.FieldPoint2D:
                return(new CodeObjectCreateExpression(new CodeTypeReference("Point2dField"), nameExpression));

            case FieldType.FieldRectangle2D:
                return(new CodeObjectCreateExpression(new CodeTypeReference("Rectangle2dField"), nameExpression));

            case FieldType.FieldRgbColor:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RgbColorField"), nameExpression));

            case FieldType.FieldArgbColor:
                return(new CodeObjectCreateExpression(new CodeTypeReference("ArgbColorField"), nameExpression));

            case FieldType.FieldReal:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealField"), nameExpression));

            case FieldType.FieldRealFraction:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealFractionField"), nameExpression));

            case FieldType.FieldRealPoint2D:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealPoint2dField"), nameExpression));

            case FieldType.FieldRealPoint3D:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealPoint3dField"), nameExpression));

            case FieldType.FieldRealVector2D:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealVector2dField"), nameExpression));

            case FieldType.FieldRealVector3D:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealVector3dField"), nameExpression));

            case FieldType.FieldQuaternion:
                return(new CodeObjectCreateExpression(new CodeTypeReference("QuaternionField"), nameExpression));

            case FieldType.FieldEulerAngles2D:
                return(new CodeObjectCreateExpression(new CodeTypeReference("EulerAngles2dField"), nameExpression));

            case FieldType.FieldEulerAngles3D:
                return(new CodeObjectCreateExpression(new CodeTypeReference("EulerAngles3dField"), nameExpression));

            case FieldType.FieldRealPlane2D:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealPlane2dField"), nameExpression));

            case FieldType.FieldRealPlane3D:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealPlane3dField"), nameExpression));

            case FieldType.FieldRealRgbColor:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealRgbColorField"), nameExpression));

            case FieldType.FieldRealArgbColor:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealArgbColorField"), nameExpression));

            case FieldType.FieldRealHsvColor:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealHsvColorField"), nameExpression));

            case FieldType.FieldRealAhsvColor:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealAhsvColorField"), nameExpression));

            case FieldType.FieldShortBounds:
                return(new CodeObjectCreateExpression(new CodeTypeReference("ShortBoundsField"), nameExpression));

            case FieldType.FieldAngleBounds:
                return(new CodeObjectCreateExpression(new CodeTypeReference("AngleBoundsField"), nameExpression));

            case FieldType.FieldRealBounds:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealBoundsField"), nameExpression));

            case FieldType.FieldRealFractionBounds:
                return(new CodeObjectCreateExpression(new CodeTypeReference("RealFractionBoundsField"), nameExpression));

            case FieldType.FieldTagReference:
                return(new CodeObjectCreateExpression(new CodeTypeReference("TagReferenceField"), nameExpression, groupTagExpression));

            case FieldType.FieldBlock:
                return(new CodeObjectCreateExpression(new CodeTypeReference($"BlockField<{AbideCodeDomGlobals.GetMemberName(tagField.ReferencedBlock)}>"), nameExpression, new CodePrimitiveExpression(tagField.ReferencedBlock.MaximumElementCount)));

            case FieldType.FieldLongBlockFlags:
                return(new CodeObjectCreateExpression(new CodeTypeReference("LongFlagsField"), nameExpression));

            case FieldType.FieldWordBlockFlags:
                return(new CodeObjectCreateExpression(new CodeTypeReference("WordFlagsField"), nameExpression));

            case FieldType.FieldByteBlockFlags:
                return(new CodeObjectCreateExpression(new CodeTypeReference("ByteFlagsField"), nameExpression));

            case FieldType.FieldCharBlockIndex1:
                return(new CodeObjectCreateExpression(new CodeTypeReference("CharBlockIndexField"), nameExpression));

            case FieldType.FieldCharBlockIndex2:
                return(new CodeObjectCreateExpression(new CodeTypeReference("CharBlockIndexField"), nameExpression));

            case FieldType.FieldShortBlockIndex1:
                return(new CodeObjectCreateExpression(new CodeTypeReference("ShortBlockIndexField"), nameExpression));

            case FieldType.FieldShortBlockIndex2:
                return(new CodeObjectCreateExpression(new CodeTypeReference("ShortBlockIndexField"), nameExpression));

            case FieldType.FieldLongBlockIndex1:
                return(new CodeObjectCreateExpression(new CodeTypeReference("LongBlockIndexField"), nameExpression));

            case FieldType.FieldLongBlockIndex2:
                return(new CodeObjectCreateExpression(new CodeTypeReference("LongBlockIndexField"), nameExpression));

            case FieldType.FieldData:
                return(new CodeObjectCreateExpression(new CodeTypeReference("DataField"), nameExpression, new CodePrimitiveExpression(tagField.ElementSize), new CodePrimitiveExpression(tagField.Alignment)));

            case FieldType.FieldVertexBuffer:
                return(new CodeObjectCreateExpression(new CodeTypeReference("VertexBufferField"), nameExpression));

            case FieldType.FieldPad:
                return(new CodeObjectCreateExpression(new CodeTypeReference("PadField"), nameExpression, new CodePrimitiveExpression(tagField.Length)));

            case FieldType.FieldSkip:
                return(new CodeObjectCreateExpression(new CodeTypeReference("SkipField"), nameExpression, new CodePrimitiveExpression(tagField.Length)));

            case FieldType.FieldExplanation:
                return(new CodeObjectCreateExpression(new CodeTypeReference("ExplanationField"), nameExpression, explanationExpression));

            case FieldType.FieldStruct:
                return(new CodeObjectCreateExpression(new CodeTypeReference($"StructField<{AbideCodeDomGlobals.GetMemberName(tagField.ReferencedBlock)}>"), nameExpression));

            case FieldType.FieldTagIndex:
                return(new CodeObjectCreateExpression(new CodeTypeReference("TagIndexField"), nameExpression));
            }

            //Return
            return(null);
        }
Beispiel #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AbideTagLookupCodeCompileUnit"/> class.
        /// </summary>
        /// <param name="namespaceString">The optional namespace string. This defaults to "Abide.Tag.Cache."</param>
        /// <param name="tagNamespace"></param>
        public AbideTagLookupCodeCompileUnit(string namespaceString = "Abide.Tag.Cache", string tagNamespace = "Abide.Tag", TypeAttributes typeAttributes = TypeAttributes.Public)
        {
            //Create namespace
            CodeNamespace generatedCodeNamespace = new CodeNamespace($"{namespaceString}.Generated");

            //Add imports
            generatedCodeNamespace.Imports.Add(new CodeNamespaceImport(AbideCodeDomGlobals.SystemNamespace));
            generatedCodeNamespace.Imports.Add(new CodeNamespaceImport(AbideCodeDomGlobals.HaloLibraryNamespace));
            generatedCodeNamespace.Imports.Add(new CodeNamespaceImport(tagNamespace));

            //Create type
            tagLookupCodeTypeDeclaration = new CodeTypeDeclaration("TagLookup")
            {
                TypeAttributes = typeAttributes,
                IsClass        = true
            };
            tagLookupCodeTypeDeclaration.Comments.Add(new CodeCommentStatement("<summary>", true));
            tagLookupCodeTypeDeclaration.Comments.Add(new CodeCommentStatement($"Represents the global tag lookup class.", true));
            tagLookupCodeTypeDeclaration.Comments.Add(new CodeCommentStatement("</summary>", true));

            //Create Method
            CodeMemberMethod createTagGroupMethod1 = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "CreateTagGroup",
                ReturnType = new CodeTypeReference(nameof(Group)),
            };

            createTagGroupMethod1.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(nameof(TagFourCc)), "groupTag"));
            createTagGroupMethod1.Comments.Add(new CodeCommentStatement("<summary>", true));
            createTagGroupMethod1.Comments.Add(new CodeCommentStatement($"Returns a <see cref=\"Group\"/> instance based on the supplied tag.", true));
            createTagGroupMethod1.Comments.Add(new CodeCommentStatement("</summary>", true));
            createTagGroupMethod1.Comments.Add(new CodeCommentStatement("<param name=\"groupTag\">The group tag.</param>", true));
            tagLookupCodeTypeDeclaration.Members.Add(createTagGroupMethod1);

            //Generate if statements
            foreach (var tagGroup in AbideCodeDomGlobals.GetTagGroups())
            {
                createTagGroupMethod1.Statements.Add(new CodeCommentStatement($" {tagGroup.Name}"));
                createTagGroupMethod1.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression("groupTag"), CodeBinaryOperatorType.ValueEquality,
                                                                                                                 new CodePrimitiveExpression(tagGroup.GroupTag.FourCc)), new CodeMethodReturnStatement(
                                                                                    new CodeObjectCreateExpression(new CodeTypeReference(AbideCodeDomGlobals.GetMemberName(tagGroup))))));
            }
            createTagGroupMethod1.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression()));

            //Create Method
            CodeMemberMethod createTagGroupMethod2 = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "CreateTagGroup",
                ReturnType = new CodeTypeReference(nameof(Group)),
            };

            createTagGroupMethod2.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(string)), "tagGroupName"));
            createTagGroupMethod2.Comments.Add(new CodeCommentStatement("<summary>", true));
            createTagGroupMethod2.Comments.Add(new CodeCommentStatement($"Returns a <see cref=\"Group\"/> instance based on the supplied tag group name.", true));
            createTagGroupMethod2.Comments.Add(new CodeCommentStatement("</summary>", true));
            createTagGroupMethod2.Comments.Add(new CodeCommentStatement("<param name=\"tagGroupName\">The name of the tag group.</param>", true));
            tagLookupCodeTypeDeclaration.Members.Add(createTagGroupMethod2);

            //Generate if statements
            foreach (var tagGroup in AbideCodeDomGlobals.GetTagGroups())
            {
                createTagGroupMethod2.Statements.Add(new CodeCommentStatement($" {tagGroup.Name}"));
                createTagGroupMethod2.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression("tagGroupName"), CodeBinaryOperatorType.ValueEquality,
                                                                                                                 new CodePrimitiveExpression(tagGroup.Name)), new CodeMethodReturnStatement(
                                                                                    new CodeObjectCreateExpression(new CodeTypeReference(AbideCodeDomGlobals.GetMemberName(tagGroup))))));
            }
            createTagGroupMethod2.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression()));

            //Create method
            CodeMemberMethod createTagBlockMethod = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "CreateTagBlock",
                ReturnType = new CodeTypeReference(nameof(Block)),
            };

            createTagBlockMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(string)), "tagBlockName"));
            createTagBlockMethod.Comments.Add(new CodeCommentStatement("<summary>", true));
            createTagBlockMethod.Comments.Add(new CodeCommentStatement($"Returns a <see cref=\"Block\"/> instance based on the supplied tag block name.", true));
            createTagBlockMethod.Comments.Add(new CodeCommentStatement("</summary>", true));
            createTagBlockMethod.Comments.Add(new CodeCommentStatement("<param name=\"tagBlockName\">The name of the tag block.</param>", true));
            tagLookupCodeTypeDeclaration.Members.Add(createTagBlockMethod);

            //Generate if statements
            foreach (var tagBlock in AbideCodeDomGlobals.GetTagBlocks())
            {
                createTagBlockMethod.Statements.Add(new CodeCommentStatement($" {tagBlock.Name}"));
                createTagBlockMethod.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression("tagBlockName"), CodeBinaryOperatorType.ValueEquality,
                                                                                                                new CodePrimitiveExpression(tagBlock.Name)), new CodeMethodReturnStatement(
                                                                                   new CodeObjectCreateExpression(new CodeTypeReference(AbideCodeDomGlobals.GetMemberName(tagBlock))))));
            }
            createTagBlockMethod.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression()));

            //Add type to namespace
            generatedCodeNamespace.Types.Add(tagLookupCodeTypeDeclaration);

            //Add namespace
            Namespaces.Add(generatedCodeNamespace);
        }
Beispiel #4
0
        // private int currentFieldIndex = -1;

        /// <summary>
        /// Initializes a new instance of the <see cref="AbideTagBlockCodeCompileUnit"/> class.
        /// </summary>
        /// <param name="tagBlock">The tag block definition.</param>
        /// <param name="namespaceString">The optional namespace string. This defaults to "Cache."</param>
        /// <param name="tagNamespace"></param>
        public AbideTagBlockCodeCompileUnit(AbideTagBlock tagBlock, string namespaceString = "Cache", string tagNamespace = "Abide.Tag", TypeAttributes typeAttributes = TypeAttributes.Public)
        {
            //Prepare
            string blockTypeName = AbideCodeDomGlobals.GetMemberName(tagBlock);
            string baseTypeName  = nameof(Block);

            //Create namespace
            CodeNamespace generatedCodeNamespace = new CodeNamespace($"{namespaceString}.Generated");

            //Add imports
            generatedCodeNamespace.Imports.Add(new CodeNamespaceImport(AbideCodeDomGlobals.SystemNamespace));
            generatedCodeNamespace.Imports.Add(new CodeNamespaceImport(AbideCodeDomGlobals.HaloLibraryNamespace));
            generatedCodeNamespace.Imports.Add(new CodeNamespaceImport(tagNamespace));

            //Create type
            tagGroupCodeTypeDeclaration = new CodeTypeDeclaration(blockTypeName)
            {
                TypeAttributes = typeAttributes | TypeAttributes.Sealed,
                IsClass        = true
            };
            tagGroupCodeTypeDeclaration.BaseTypes.Add(baseTypeName);
            tagGroupCodeTypeDeclaration.Comments.Add(new CodeCommentStatement("<summary>", true));
            tagGroupCodeTypeDeclaration.Comments.Add(new CodeCommentStatement($"Represents the generated {tagBlock.Name} tag block.", true));
            tagGroupCodeTypeDeclaration.Comments.Add(new CodeCommentStatement("</summary>", true));

            //BlockName property
            CodeMemberProperty nameMemberProperty = new CodeMemberProperty()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Override,
                Name       = nameof(Block.Name),
                Type       = new CodeTypeReference(typeof(string))
            };

            nameMemberProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(tagBlock.Name)));
            nameMemberProperty.Comments.Add(new CodeCommentStatement("<summary>", true));
            nameMemberProperty.Comments.Add(new CodeCommentStatement($"Gets and returns the name of the {tagBlock.Name} tag block.", true));
            nameMemberProperty.Comments.Add(new CodeCommentStatement("</summary>", true));
            tagGroupCodeTypeDeclaration.Members.Add(nameMemberProperty);

            //DisplayName property
            CodeMemberProperty displayNameMemberProperty = new CodeMemberProperty()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Override,
                Name       = nameof(Block.DisplayName),
                Type       = new CodeTypeReference(typeof(string))
            };

            displayNameMemberProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(tagBlock.DisplayName)));
            displayNameMemberProperty.Comments.Add(new CodeCommentStatement("<summary>", true));
            displayNameMemberProperty.Comments.Add(new CodeCommentStatement($"Gets and returns the display name of the {tagBlock.Name} tag block.", true));
            displayNameMemberProperty.Comments.Add(new CodeCommentStatement("</summary>", true));
            tagGroupCodeTypeDeclaration.Members.Add(displayNameMemberProperty);

            //MaximumElementCount property
            CodeMemberProperty groupTagMemberProperty = new CodeMemberProperty()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Override,
                Name       = nameof(Block.MaximumElementCount),
                Type       = new CodeTypeReference(typeof(int))
            };

            groupTagMemberProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(tagBlock.MaximumElementCount)));
            groupTagMemberProperty.Comments.Add(new CodeCommentStatement("<summary>", true));
            groupTagMemberProperty.Comments.Add(new CodeCommentStatement($"Gets and returns the maximum number of elements allowed of the {tagBlock.Name} tag block.", true));
            groupTagMemberProperty.Comments.Add(new CodeCommentStatement("</summary>", true));
            tagGroupCodeTypeDeclaration.Members.Add(groupTagMemberProperty);

            //Alignment property
            CodeMemberProperty alignmentMemberProperty = new CodeMemberProperty()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Override,
                Name       = nameof(Block.Alignment),
                Type       = new CodeTypeReference(typeof(int))
            };

            alignmentMemberProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(tagBlock.FieldSet.Alignment)));
            alignmentMemberProperty.Comments.Add(new CodeCommentStatement("<summary>", true));
            alignmentMemberProperty.Comments.Add(new CodeCommentStatement($"Gets and returns the alignment of the {tagBlock.Name} tag block.", true));
            alignmentMemberProperty.Comments.Add(new CodeCommentStatement("</summary>", true));
            tagGroupCodeTypeDeclaration.Members.Add(alignmentMemberProperty);

            //Constructor
            CodeConstructor constructor = new CodeConstructor()
            {
                Attributes = MemberAttributes.Public,
            };

            constructor.Comments.Add(new CodeCommentStatement("<summary>", true));
            constructor.Comments.Add(new CodeCommentStatement($"Initializes a new instance of the <see cref=\"{blockTypeName}\"/> class.", true));
            constructor.Comments.Add(new CodeCommentStatement("</summary>", true));
            tagGroupCodeTypeDeclaration.Members.Add(constructor);

            //Process fields
            List <AbideTagField> processedFields = ProcessTagFields(tagBlock.FieldSet);

            //Add fields to fields list
            CodeExpression fieldCreateExpression = null;

            foreach (AbideTagField field in processedFields)
            {
                //Check
                if (field.FieldType == FieldType.FieldArrayStart)
                {
                    //Create
                    foreach (CodeExpression fieldExpression in CreateArrayFieldExpression(field))
                    {
                        //Add statement
                        constructor.Statements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodePropertyReferenceExpression(
                                                                                                                        new CodeThisReferenceExpression(), nameof(Block.Fields)), nameof(List <Field> .Add)), fieldExpression));

                        // CreateFieldProperty(++currentFieldIndex, field);
                    }
                }
                else
                {
                    //Create
                    fieldCreateExpression = CreateFieldCreateExpression(field);

                    //Add?
                    if (fieldCreateExpression != null)
                    {
                        //Add statement
                        constructor.Statements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodePropertyReferenceExpression(
                                                                                                                        new CodeThisReferenceExpression(), nameof(Block.Fields)), nameof(List <Field> .Add)), fieldCreateExpression));

                        // CreateFieldProperty(++currentFieldIndex, field);
                    }
                }
            }

            //Add type to namespace
            generatedCodeNamespace.Types.Add(tagGroupCodeTypeDeclaration);

            //Add namespace
            Namespaces.Add(generatedCodeNamespace);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AbideTagGroupCodeCompileUnit"/> class.
        /// </summary>
        /// <param name="tagGroup">The tag group definition.</param>
        /// <param name="namespaceString">The optional namespace string. This defaults to "Cache".</param>
        /// <param name="tagNamespace"></param>
        public AbideTagGroupCodeCompileUnit(AbideTagGroup tagGroup, string namespaceString = "Cache", string tagNamespace = "Abide.Tag", TypeAttributes typeAttributes = TypeAttributes.Public)
        {
            //Prepare
            string blockTypeName = AbideCodeDomGlobals.GetMemberName(AbideCodeDomGlobals.GetTagBlock(tagGroup.BlockName));
            string groupTypeName = AbideCodeDomGlobals.GetMemberName(tagGroup);

            //Create namespace
            CodeNamespace generatedCodeNamespace = new CodeNamespace($"{namespaceString}.Generated");

            //Add imports
            generatedCodeNamespace.Imports.Add(new CodeNamespaceImport(AbideCodeDomGlobals.SystemNamespace));
            generatedCodeNamespace.Imports.Add(new CodeNamespaceImport(AbideCodeDomGlobals.HaloLibraryNamespace));
            generatedCodeNamespace.Imports.Add(new CodeNamespaceImport(tagNamespace));

            //Create type
            tagGroupCodeTypeDeclaration = new CodeTypeDeclaration(groupTypeName)
            {
                TypeAttributes = typeAttributes,
                IsClass        = true
            };
            tagGroupCodeTypeDeclaration.BaseTypes.Add(nameof(Group));
            tagGroupCodeTypeDeclaration.Comments.Add(new CodeCommentStatement("<summary>", true));
            tagGroupCodeTypeDeclaration.Comments.Add(new CodeCommentStatement($"Represents the generated {tagGroup.Name} " +
                                                                              $"({tagGroup.GroupTag.FourCc.Replace("<", "&lt;").Replace(">", "&gt;")}) tag group.", true));
            tagGroupCodeTypeDeclaration.Comments.Add(new CodeCommentStatement("</summary>", true));

            //Name property
            CodeMemberProperty nameMemberProperty = new CodeMemberProperty()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Override,
                Name       = nameof(Group.Name),
                Type       = new CodeTypeReference(typeof(string))
            };

            nameMemberProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(tagGroup.Name)));
            nameMemberProperty.Comments.Add(new CodeCommentStatement("<summary>", true));
            nameMemberProperty.Comments.Add(new CodeCommentStatement($"Gets and returns the name of the {tagGroup.Name} tag group.", true));
            nameMemberProperty.Comments.Add(new CodeCommentStatement("</summary>", true));
            tagGroupCodeTypeDeclaration.Members.Add(nameMemberProperty);

            //GroupTag property
            CodeMemberProperty groupTagMemberProperty = new CodeMemberProperty()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Override,
                Name       = nameof(Group.Tag),
                Type       = new CodeTypeReference(nameof(TagFourCc))
            };

            groupTagMemberProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(tagGroup.GroupTag.FourCc)));
            groupTagMemberProperty.Comments.Add(new CodeCommentStatement("<summary>", true));
            groupTagMemberProperty.Comments.Add(new CodeCommentStatement($"Gets and returns the group tag of the {tagGroup.Name} tag group.", true));
            groupTagMemberProperty.Comments.Add(new CodeCommentStatement("</summary>", true));
            tagGroupCodeTypeDeclaration.Members.Add(groupTagMemberProperty);

            //Constructor
            CodeConstructor constructor = new CodeConstructor()
            {
                Attributes = MemberAttributes.Public,
            };

            constructor.Comments.Add(new CodeCommentStatement("<summary>", true));
            constructor.Comments.Add(new CodeCommentStatement($"Initializes a new instance of the <see cref=\"{groupTypeName}\"/> class.", true));
            constructor.Comments.Add(new CodeCommentStatement("</summary>", true));
            tagGroupCodeTypeDeclaration.Members.Add(constructor);

            //Initialize Blocks
            int       index  = 0;
            TagFourCc parent = tagGroup.ParentGroupTag;

            while (parent.Dword != 0)
            {
                //Get Parent
                var parentGroup = AbideCodeDomGlobals.GetTagGroup(parent);

                //Add Block
                constructor.Statements.Insert(0, new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodePropertyReferenceExpression(
                                                                                                                                                  new CodeThisReferenceExpression(), nameof(Group.TagBlocks)), nameof(List <Block> .Add)), new CodeObjectCreateExpression(
                                                                                                                new CodeTypeReference(AbideCodeDomGlobals.GetMemberName(AbideCodeDomGlobals.GetTagBlock(parentGroup.BlockName)))))));
                constructor.Statements.Insert(0, new CodeCommentStatement($"Add parent {parentGroup.Name} tag block to list."));

                CreateBlockProperty(index++, AbideCodeDomGlobals.GetTagBlock(parentGroup.BlockName));

                //Get parent's parent group
                parent = parentGroup.ParentGroupTag;
            }

            //Add Block
            constructor.Statements.Add(new CodeCommentStatement($"Add tag block to list."));
            constructor.Statements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodePropertyReferenceExpression(
                                                                                                            new CodeThisReferenceExpression(), nameof(Group.TagBlocks)), nameof(List <ITagBlock> .Add)), new CodeObjectCreateExpression(
                                                                          new CodeTypeReference(AbideCodeDomGlobals.GetMemberName(AbideCodeDomGlobals.GetTagBlock(tagGroup.BlockName))))));


            //Add type to namespace
            generatedCodeNamespace.Types.Add(tagGroupCodeTypeDeclaration);

            //Add namespace
            Namespaces.Add(generatedCodeNamespace);
        }