private string GenerateDtoFieldDefinition()

in src/JetBrains.Space.Generator/CodeGeneration/CSharp/Generators/CSharpApiModelDtoGenerator.cs [202:329]


    private string GenerateDtoFieldDefinition(string dtoId, string typeNameForDto, ApiField apiField)
    {
        var indent = new Indent();
        var builder = new CSharpBuilder();

        var propertyNameForField = apiField.ToCSharpPropertyName(typeNameForDto);
        var backingFieldNameForField = apiField.ToCSharpBackingFieldName();

        // Backing field
        builder.Append($"{indent}private PropertyValue<");
        builder.Append(apiField.Type.ToCSharpType(_codeGenerationContext));
        if (apiField.Type.Nullable)
        {
            builder.Append('?');
        }
        
        if (!apiField.Type.Nullable && apiField.RequiresAddedNullability())
        {
            builder.Append('?');
        }

        builder.Append("> ");
        builder.Append($"{backingFieldNameForField} = new PropertyValue<");
        builder.Append(apiField.Type.ToCSharpType(_codeGenerationContext));
        if (apiField.Type.Nullable)
        {
            builder.Append('?');
        }
        
        if (!apiField.Type.Nullable && apiField.RequiresAddedNullability())
        {
            builder.Append('?');
        }
            
        // For non-nullable List<> and Dictionary<>, make sure the field is initialized.
        // We do this by setting a temporary default value for this pass.
        var overrideDefaultValue = !apiField.Type.Nullable && apiField.DefaultValue == null;
        if (overrideDefaultValue)
        {
            // REVIEW: This is a mutation, might be good to consider making this immutable.
            apiField.DefaultValue = apiField.Type switch
            {
                ApiFieldType.Array => new ApiDefaultValue.Collection(),
                ApiFieldType.Map => new ApiDefaultValue.Map(),
                _ => apiField.DefaultValue
            };
        }

        var initialValueForAssignment = apiField.ToCSharpDefaultValueForAssignment(_codeGenerationContext);
        if (initialValueForAssignment != null)
        {
            builder.AppendLine($">(nameof({typeNameForDto}), nameof({propertyNameForField}), \"{apiField.Name}\", {initialValueForAssignment});");
        }
        else
        {
            builder.AppendLine($">(nameof({typeNameForDto}), nameof({propertyNameForField}), \"{apiField.Name}\");");
        }
        builder.AppendLine($"{indent}");

        // Restore null default value
        if (overrideDefaultValue)
        {
            apiField.DefaultValue = null;
        }

        // Property
        ApiDocumentationUtilities.RenderCSharpDocumentation(apiField.Description, apiField.Experimental, output =>
        {
            builder.Append(indent.Wrap(output));
        });
        if (!apiField.Optional && !apiField.Type.Nullable)
        {
            builder.AppendLine($"{indent}[Required]");
        }
        if (apiField.Optional && (apiField.Type.Nullable || apiField.RequiresAddedNullability()) && _codeGenerationContext.IsRequestBodyDto(dtoId))
        {
            // REMARK: This only works well in .NET6+.
            // Since .NET3.1 will go out of support relatively soon (December 3, 2022 - https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core),
            // we decided to only add optional request body properties in supported .NET versions.
            builder.AppendLine($"#if NET6_0_OR_GREATER");
            builder.AppendLine($"{indent}[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]");
            builder.AppendLine($"#endif");
        }
        if (apiField.Deprecation != null)
        {
            builder.AppendLine($"{indent}{apiField.Deprecation.ToCSharpDeprecation()}");
        }
        else if (apiField.Experimental != null && FeatureFlags.GenerateExperimentalAnnotations)
        {
            builder.AppendLine($"{indent}{apiField.Experimental.ToCSharpExperimental()}");
        }
        builder.AppendLine($"{indent}[JsonPropertyName(\"{apiField.Name}\")]");

        if (apiField.Type is ApiFieldType.Primitive apiFieldTypePrimitive)
        {
            var csharpType = apiFieldTypePrimitive.ToCSharpPrimitiveType();
            if (csharpType.JsonConverter != null)
            {
                builder.AppendLine($"{indent}[JsonConverter(typeof({csharpType.JsonConverter.Name}))]");
            }
        }
            
        builder.Append($"{indent}public ");
        builder.Append(apiField.Type.ToCSharpType(_codeGenerationContext));
        if (apiField.Type.Nullable)
        {
            builder.Append('?');
        }
        
        if (!apiField.Type.Nullable && apiField.RequiresAddedNullability())
        {
            builder.Append('?');
        }
        
        builder.Append(" ");
        builder.AppendLine($"{indent}{propertyNameForField}");
            
        builder.AppendLine($"{indent}{{");
        indent.Increment();
            
        builder.AppendLine($"{indent}get => {backingFieldNameForField}.GetValue({nameof(IPropagatePropertyAccessPath.InlineErrors)});");
        builder.AppendLine($"{indent}set => {backingFieldNameForField}.SetValue(value);");

        indent.Decrement();
        builder.AppendLine($"{indent}}}");

        return builder.ToString();
    }