private void WriteClassConstructor(IJsonClassGeneratorConfig config, StringBuilder sw, JsonType type, string indentMembers, string indentBodies)
        {
            // Write an empty constructor on a single-line:
            if (type.Fields.Count == 0)
            {
                sw.AppendFormat(indentMembers + "public {0}() {{}}{1}", type.AssignedName, Environment.NewLine);
                return;
            }

            // Constructor signature:
            {
                if (config.UseJsonAttributes)
                {
                    sw.AppendLine(indentMembers + "[JsonConstructor]");
                }

                sw.AppendFormat(indentMembers + "public {0}({1}", type.AssignedName, Environment.NewLine);

                FieldInfo lastField = type.Fields[type.Fields.Count - 1];

                foreach (FieldInfo field in type.Fields)
                {
                    // Writes something like: `[JsonProperty("foobar")] string foobar,`

                    string ctorParameterName = this.GetCSharpCamelCaseName(field.MemberName);

                    bool   isLast = Object.ReferenceEquals(field, lastField);
                    string comma  = isLast ? "" : ",";

                    //

                    sw.Append(indentBodies);

                    string attribute = config.GetCSharpJsonAttributeCode(field);
                    if (attribute.Length > 0)
                    {
                        sw.Append(attribute);
                        sw.Append(' ');
                    }

                    sw.AppendFormat("{0} {1}{2}{3}", /*0:*/ field.Type.GetTypeName(), /*1:*/ ctorParameterName, /*2:*/ comma, /*3:*/ Environment.NewLine);
                }
            }

            sw.AppendLine(indentMembers + ")");

            // Constructor body:
            sw.AppendLine(indentMembers + "{");

            foreach (FieldInfo field in type.Fields)
            {
                string ctorParameterName = this.GetCSharpCamelCaseName(field.MemberName);
                string classPropertyName = this.GetCSharpPascalCaseName(field.MemberName);

                sw.AppendFormat(indentBodies + "this.{0} = {1};{2}", /*0:*/ classPropertyName, /*1:*/ ctorParameterName, /*2:*/ Environment.NewLine);
            }

            sw.AppendLine(indentMembers + "}");
            sw.AppendLine();
        }
        public void WriteClassMembers(IJsonClassGeneratorConfig config, StringBuilder sw, JsonType type, string indentMembers)
        {
            bool first = true;

            foreach (FieldInfo field in type.Fields)
            {
                string classPropertyName = this.GetCSharpPascalCaseName(field.MemberName);
                string propertyAttribute = config.GetCSharpJsonAttributeCode(field);

                if (!first && (propertyAttribute.Length > 0 || config.ExamplesInDocumentation))
                {
                    // If rendering examples/XML comments - or property attributes - then add a newline before the property for readability's sake (except if it's the first property in the class)
                    sw.AppendLine();
                }

                if (config.ExamplesInDocumentation)
                {
                    sw.AppendFormat(indentMembers + "/// <summary>");
                    sw.AppendFormat(indentMembers + "/// Examples: " + field.GetExamplesText());
                    sw.AppendFormat(indentMembers + "/// </summary>");
                    sw.AppendLine();
                }

                if (propertyAttribute.Length > 0)
                {
                    sw.Append(indentMembers);
                    sw.AppendLine(propertyAttribute);
                }

                if (config.UseFields)
                {
                    sw.AppendFormat(indentMembers + "public {0}{1} {2};{3}", config.ImmutableClasses ? "readonly " : "", field.Type.GetTypeName(), classPropertyName, Environment.NewLine);
                }
                else if (config.ImmutableClasses)
                {
                    if (field.Type.Type == JsonTypeEnum.Array)
                    {
                        sw.AppendFormat(indentMembers + "public IReadOnlyList<{0}> {1} {{ get; }}{2}", this.GetTypeName(field.Type.InternalType, config), classPropertyName, Environment.NewLine);
                    }
                    else
                    {
                        sw.AppendFormat(indentMembers + "public {0} {1} {{ get; }}{2}", field.Type.GetTypeName(), classPropertyName, Environment.NewLine);
                    }
                }
                else
                {
                    var getterSetterPart = "{ get; set; }";
                    if (config.NoSettersForCollections &&
                        (field.Type.IsCollectionType() &&
                         (config.ArrayAsList() && field.Type.Type == JsonTypeEnum.Array)))
                    {
                        getterSetterPart = "{ get; } = new " + field.Type.GetTypeName() + "();";
                    }
                    sw.AppendFormat(indentMembers + "public {0} {1} {2}{3}", field.Type.GetTypeName(), classPropertyName, getterSetterPart, Environment.NewLine);
                }

                first = false;
            }
        }
Esempio n. 3
0
        public void WriteClassMembers(IJsonClassGeneratorConfig config, StringBuilder sw, JsonType type, string indentMembers)
        {
            bool first = true;

            foreach (FieldInfo field in type.Fields)
            {
                string classPropertyName = this.GetCSharpPascalCaseName(field.MemberName);
                string propertyAttribute = config.GetCSharpJsonAttributeCode(field);

                // If we are using record types and this is not the first iteration, add a comma and newline to the previous line
                // this is required because every line except the last should end with a comma
                if (config.OutputType == OutputTypes.ImmutableRecord && !first)
                {
                    sw.AppendLine(",");
                }

                if (!first && ((propertyAttribute.Length > 0 && config.OutputType != OutputTypes.ImmutableRecord) || config.ExamplesInDocumentation))
                {
                    // If rendering examples/XML comments - or property attributes - then add a newline before the property for readability's sake (except if it's the first property in the class)
                    // For record types, we want all members to be next to each other, unless when using examples
                    sw.AppendLine();
                }

                if (config.ExamplesInDocumentation)
                {
                    sw.AppendFormat(indentMembers + "/// <summary>");
                    sw.AppendFormat(indentMembers + "/// Examples: " + field.GetExamplesText());
                    sw.AppendFormat(indentMembers + "/// </summary>");
                    sw.AppendLine();
                }

                if (propertyAttribute.Length > 0)
                {
                    sw.Append(indentMembers);
                    sw.Append(propertyAttribute);

                    if (config.OutputType != OutputTypes.ImmutableRecord)
                    {
                        sw.AppendLine();
                    }
                }

                // record types is not compatible with UseFields, so it comes first
                if (config.OutputType == OutputTypes.ImmutableRecord)
                {
                    // NOTE: not adding newlines here, that happens at the start of the loop. We need this so we can lazily add commas at the end.
                    if (field.Type.Type == JsonTypeEnum.Array)
                    {
                        // TODO: Respect config.CollectionType
                        sw.AppendFormat(" IReadOnlyList<{0}> {1}", this.GetTypeName(field.Type.InternalType, config), classPropertyName);
                    }
                    else
                    {
                        sw.AppendFormat(" {0} {1}", field.Type.GetTypeName(), classPropertyName);
                    }
                }
                else if (config.OutputType == OutputTypes.MutableClass)
                {
                    if (config.MutableClasses.Members == OutputMembers.AsPublicFields)
                    {
                        // Render a field like `public int Foobar;`:

                        bool useReadonlyModifier = config.OutputType == OutputTypes.ImmutableClass;

                        sw.AppendFormat(indentMembers + "public {0}{1} {2};{3}", useReadonlyModifier ? "readonly " : "", field.Type.GetTypeName(), classPropertyName, Environment.NewLine);
                    }
                    else if (config.MutableClasses.Members == OutputMembers.AsProperties)
                    {
                        var getterSetterPart = "{ get; set; }";

                        bool addCollectionPropertyInitializer =
                            config.MutableClasses.ReadOnlyCollectionProperties &&
                            field.Type.IsCollectionType() &&
                            config.CollectionType == OutputCollectionType.MutableList;

                        if (addCollectionPropertyInitializer && field.Type.Type == JsonTypeEnum.Array)
                        {
                            getterSetterPart = "{ get; } = new " + field.Type.GetTypeName() + "();";
                        }

                        sw.AppendFormat(indentMembers + "public {0} {1} {2}{3}", field.Type.GetTypeName(), classPropertyName, getterSetterPart, Environment.NewLine);
                    }
                    else
                    {
                        const String PATH    = nameof(config) + "." + nameof(config.MutableClasses) + "." + nameof(config.MutableClasses.Members);
                        const String MSG_FMT = "Invalid " + nameof(OutputMembers) + " enum value for " + PATH + ": {0}";
                        throw new InvalidOperationException(MSG_FMT);
                    }
                }
                else if (config.OutputType == OutputTypes.ImmutableClass)
                {
                    if (field.Type.Type == JsonTypeEnum.Array)
                    {
                        // TODO: Respect config.CollectionType
                        sw.AppendFormat(indentMembers + "public IReadOnlyList<{0}> {1} {{ get; }}{2}", this.GetTypeName(field.Type.InternalType, config), classPropertyName, Environment.NewLine);
                    }
                    else
                    {
                        sw.AppendFormat(indentMembers + "public {0} {1} {{ get; }}{2}", field.Type.GetTypeName(), classPropertyName, Environment.NewLine);
                    }
                }
                else
                {
                    throw new InvalidOperationException("Invalid " + nameof(OutputTypes) + " value: " + config.OutputType);
                }

                first = false;
            }

            // emit a final newline if we're dealing with record types
            if (config.OutputType == OutputTypes.ImmutableRecord)
            {
                sw.AppendLine();
            }
        }