private static void WriteArray_(
            ICurlyBracketStringBuilder cbsb,
            ITypeSymbol sourceSymbol,
            ISchemaMember member)
        {
            var arrayType = member.MemberType as ISequenceMemberType;

            if (arrayType.LengthSourceType != SequenceLengthSourceType.CONST)
            {
                var isImmediate =
                    arrayType.LengthSourceType ==
                    SequenceLengthSourceType.IMMEDIATE_VALUE;

                if (isImmediate)
                {
                    var writeType = SchemaGeneratorUtil.GetIntLabel(
                        arrayType.ImmediateLengthType);

                    var castType = SchemaGeneratorUtil.GetTypeName(
                        SchemaPrimitiveTypesUtil.ConvertIntToNumber(
                            arrayType.ImmediateLengthType));

                    var arrayLengthName = arrayType.SequenceType == SequenceType.ARRAY
                                    ? "Length"
                                    : "Count";
                    var arrayLengthAccessor = $"this.{member.Name}.{arrayLengthName}";

                    cbsb.WriteLine(
                        $"ew.Write{writeType}(({castType}) {arrayLengthAccessor});");
                }
            }

            SchemaWriterGenerator.WriteIntoArray_(cbsb, sourceSymbol, member);
        }
예제 #2
0
        private void AssertGenerated_(string src, string expectedGenerated)
        {
            var structure = SchemaTestUtil.Parse(src);

            Assert.IsEmpty(structure.Diagnostics);

            var actualGenerated = new SchemaWriterGenerator().Generate(structure);

            Assert.AreEqual(expectedGenerated, actualGenerated.ReplaceLineEndings());
        }
        public string Generate(ISchemaStructure structure)
        {
            var typeSymbol = structure.TypeSymbol;

            var typeNamespace = SymbolTypeUtil.MergeContainingNamespaces(typeSymbol);

            var declaringTypes =
                SymbolTypeUtil.GetDeclaringTypesDownward(typeSymbol);

            var cbsb = new CurlyBracketStringBuilder();

            cbsb.WriteLine("using System;")
            .WriteLine("using System.IO;");

            // TODO: Handle fancier cases here
            cbsb.EnterBlock($"namespace {typeNamespace}");
            foreach (var declaringType in declaringTypes)
            {
                cbsb.EnterBlock(SymbolTypeUtil.GetQualifiersAndNameFor(declaringType));
            }
            cbsb.EnterBlock(SymbolTypeUtil.GetQualifiersAndNameFor(typeSymbol));

            cbsb.EnterBlock("public void Write(EndianBinaryWriter ew)");
            foreach (var member in structure.Members)
            {
                SchemaWriterGenerator.WriteMember_(cbsb, typeSymbol, member);
            }
            cbsb.ExitBlock();

            // TODO: Handle fancier cases here

            // type
            cbsb.ExitBlock();

            // parent types
            foreach (var declaringType in declaringTypes)
            {
                cbsb.ExitBlock();
            }

            // namespace
            cbsb.ExitBlock();

            var generatedCode = cbsb.ToString();

            return(generatedCode);
        }
        private static void WritePrimitive_(
            ICurlyBracketStringBuilder cbsb,
            ISchemaMember member)
        {
            var primitiveType = member.MemberType as IPrimitiveMemberType;

            if (primitiveType.PrimitiveType == SchemaPrimitiveType.BOOLEAN)
            {
                SchemaWriterGenerator.WriteBoolean_(cbsb, member);
                return;
            }

            var readType = SchemaGeneratorUtil.GetPrimitiveLabel(
                primitiveType.UseAltFormat
              ? SchemaPrimitiveTypesUtil.ConvertNumberToPrimitive(
                    primitiveType.AltFormat)
              : primitiveType.PrimitiveType);

            var needToCast = primitiveType.UseAltFormat &&
                             primitiveType.PrimitiveType !=
                             SchemaPrimitiveTypesUtil.GetUnderlyingPrimitiveType(
                SchemaPrimitiveTypesUtil.ConvertNumberToPrimitive(
                    primitiveType.AltFormat));

            var castText = "";

            if (needToCast)
            {
                var castType =
                    SchemaGeneratorUtil.GetTypeName(primitiveType.AltFormat);
                castText = $"({castType}) ";
            }

            cbsb.WriteLine(
                $"ew.Write{readType}({castText}this.{member.Name});");
        }
        private static void WriteMember_(
            ICurlyBracketStringBuilder cbsb,
            ITypeSymbol sourceSymbol,
            ISchemaMember member)
        {
            if (member.IsPosition)
            {
                return;
            }

            if (member.Offset != null)
            {
                cbsb.WriteLine("throw new NotImplementedException();");
                return;
            }

            SchemaWriterGenerator.Align_(cbsb, member);

            var ifBoolean = member.IfBoolean;

            if (ifBoolean != null)
            {
                if (ifBoolean.SourceType == IfBooleanSourceType.IMMEDIATE_VALUE)
                {
                    var booleanNumberType =
                        SchemaPrimitiveTypesUtil.ConvertIntToNumber(
                            ifBoolean.ImmediateBooleanType);
                    var booleanPrimitiveType =
                        SchemaPrimitiveTypesUtil.ConvertNumberToPrimitive(
                            booleanNumberType);
                    var booleanNumberLabel =
                        SchemaGeneratorUtil.GetTypeName(booleanNumberType);
                    var booleanPrimitiveLabel =
                        SchemaGeneratorUtil.GetPrimitiveLabel(booleanPrimitiveType);
                    cbsb.WriteLine(
                        $"ew.Write{booleanPrimitiveLabel}(({booleanNumberLabel}) (this.{member.Name} != null ? 1 : 0));")
                    .EnterBlock($"if (this.{member.Name} != null)");
                }
                else
                {
                    cbsb.EnterBlock($"if (this.{ifBoolean.BooleanMember.Name})");
                }
            }

            var memberType = member.MemberType;

            if (memberType is IGenericMemberType genericMemberType)
            {
                memberType = genericMemberType.ConstraintType;
            }

            switch (memberType)
            {
            case IPrimitiveMemberType: {
                SchemaWriterGenerator.WritePrimitive_(cbsb, member);
                break;
            }

            case IStringType: {
                SchemaWriterGenerator.WriteString_(cbsb, member);
                break;
            }

            case IStructureMemberType structureMemberType: {
                SchemaWriterGenerator.WriteStructure_(cbsb, member);
                break;
            }

            case ISequenceMemberType: {
                SchemaWriterGenerator.WriteArray_(cbsb, sourceSymbol, member);
                break;
            }

            default:
                // Anything that makes it down here probably isn't meant to be read.
                throw new NotImplementedException();
            }

            if (ifBoolean != null)
            {
                cbsb.ExitBlock();
            }
        }