public string GenerateDtoDefinition()

in src/JetBrains.Space.Generator/CodeGeneration/CSharp/Generators/CSharpApiModelDtoGenerator.cs [16:171]


    public string GenerateDtoDefinition(ApiDto apiDto)
    {
        var indent = new Indent();
        var builder = new CSharpBuilder();
            
        var typeNameForDto = apiDto.ToCSharpClassName();
            
        if (apiDto.Deprecation != null)
        {
            builder.AppendLine($"{indent}{apiDto.Deprecation.ToCSharpDeprecation()}");
        }
        else if (apiDto.FeatureFlag != null && _codeGenerationContext.TryGetFeatureFlag(apiDto.FeatureFlag, out var featureFlag))
        {
            builder.AppendLine($"{indent}{featureFlag.ToCSharpFeatureFlag()}");
        }
        else if (apiDto.Experimental != null && FeatureFlags.GenerateExperimentalAnnotations)
        {
            builder.AppendLine($"{indent}{apiDto.Experimental.ToCSharpExperimental()}");
        }
                
        if (apiDto.HierarchyRole2 != HierarchyRole2.INTERFACE && apiDto.HierarchyRole2 != HierarchyRole2.SEALED_INTERFACE && apiDto.Extends == null && apiDto.Inheritors.Count > 0)
        {
            // When extending another DTO, make sure to apply a converter
            builder.AppendLine($"{indent}[JsonConverter(typeof(ClassNameDtoTypeConverter))]");
        }

        var modifierForDto = apiDto.HierarchyRole2 switch
        {
            HierarchyRole2.INTERFACE => "interface",
            HierarchyRole2.SEALED_INTERFACE => "interface",
            HierarchyRole2.ABSTRACT_CLASS => "abstract class",
            HierarchyRole2.FINAL_CLASS => "sealed class",
            _ => "class"
        };
        
        var dtoHierarchy = new List<string>();
        if (apiDto.Extends != null && _codeGenerationContext.TryGetDto(apiDto.Extends.Id, out var apiDtoExtends))
        {
            dtoHierarchy.Add(apiDtoExtends!.ToCSharpClassName());
        }

        foreach (var dtoImplements in apiDto.Implements)
        {
            if (_codeGenerationContext.TryGetDto(dtoImplements.Id, out var apiDtoImplements))
            {
                dtoHierarchy.Add(apiDtoImplements!.ToCSharpClassName());
            }
        }
        if (dtoHierarchy.Count > 0 || apiDto.Inheritors.Count > 0)
        {
            dtoHierarchy.Add(nameof(IClassNameConvertible));
        }
            
        dtoHierarchy.Add(nameof(IPropagatePropertyAccessPath));

        var visibilityModifier = "public";
        if (FeatureFlags.DoNotExposeRequestObjects && _codeGenerationContext.IsRequestBodyDto(apiDto.Id))
        {
            visibilityModifier = "internal";
        }
            
        builder.AppendLine($"{indent}{visibilityModifier} {modifierForDto} {typeNameForDto}");
        indent.Increment();
        builder.AppendLine($"{indent} : " + string.Join(", ", dtoHierarchy));
        indent.Decrement();
            
        builder.AppendLine($"{indent}{{");
        indent.Increment();
            
        // When in a hierarchy with IClassNameConvertible, make sure we can capture the class name.
        if (dtoHierarchy.Contains(nameof(IClassNameConvertible)) && apiDto.HierarchyRole2 != HierarchyRole2.INTERFACE && apiDto.HierarchyRole2 != HierarchyRole2.SEALED_INTERFACE)
        {
            var modifierForClassNameProperty = apiDto.Extends == null
                ? apiDto.HierarchyRole2 != HierarchyRole2.FINAL_CLASS
                    ? "virtual" // Parent
                    : ""
                : "override";   // Inheritor
                
            builder.AppendLine($"{indent}[JsonPropertyName(\"className\")]");
            builder.AppendLine($"{indent}public {modifierForClassNameProperty} string? ClassName => \"{apiDto.Name}\";");
            builder.AppendLine($"{indent}");
        }
            
        // Determine list of fields
        var apiDtoFields = DetermineFieldsToGenerateFor(apiDto);
            
        // Generate factories for inheritors
        foreach (var apiDtoInheritorReference in apiDto.Inheritors)
        {
            if (_codeGenerationContext.TryGetDto(apiDtoInheritorReference.Id, out var apiDtoInheritor)
                && apiDtoInheritor!.HierarchyRole2 != HierarchyRole2.INTERFACE && apiDtoInheritor.HierarchyRole2 != HierarchyRole2.SEALED_INTERFACE && apiDtoInheritor.HierarchyRole2 != HierarchyRole2.ABSTRACT_CLASS)
            {
                var inheritorTypeName = apiDtoInheritor.ToCSharpClassName();
                var inheritorFactoryMethodName = apiDtoInheritor.ToCSharpFactoryMethodName(apiDto);
                    
                var methodParametersBuilder = new MethodParametersBuilder(_codeGenerationContext)
                    .WithParametersForApiDtoFields(DetermineFieldsToGenerateFor(apiDtoInheritor));
                    
                builder.AppendLine($"{indent}public static {inheritorTypeName} {inheritorFactoryMethodName}({methodParametersBuilder.BuildMethodParametersList()})");
                indent.Increment();
                builder.AppendLine($"{indent}=> new {inheritorTypeName}({methodParametersBuilder.WithDefaultValueForAllParameters(null).BuildMethodCallParameters()});");
                indent.Decrement();
                builder.AppendLine($"{indent}");
            }
        }
            
        // Generate constructor
        // ReSharper disable once RedundantLogicalConditionalExpressionOperand
        if (apiDto.HierarchyRole2 != HierarchyRole2.INTERFACE && apiDto.HierarchyRole2 != HierarchyRole2.SEALED_INTERFACE && apiDto.HierarchyRole2 != HierarchyRole2.ABSTRACT_CLASS)
        {
            var methodParametersBuilder = new MethodParametersBuilder(_codeGenerationContext)
                .WithParametersForApiDtoFields(apiDtoFields);
                        
            // Empty constructor
            builder.AppendLine($"{indent}public {typeNameForDto}() {{ }}");
            builder.AppendLine($"{indent}");
                
            // Parameterized constructor
            if (apiDtoFields.Count > 0)
            {
                builder.AppendLine($"{indent}public {typeNameForDto}({methodParametersBuilder.BuildMethodParametersList()})");
                builder.AppendLine($"{indent}{{");
                indent.Increment();
                foreach (var apiDtoField in apiDtoFields)
                {
                    if (apiDtoField.Field.Type.IsCSharpReferenceType())
                    {
                        builder.AppendLine($"{indent}{apiDtoField.Field.ToCSharpPropertyName(typeNameForDto)} = {apiDtoField.Field.ToCSharpVariableInstanceOrDefaultValue(_codeGenerationContext)};");
                    }
                    else
                    {
                        builder.AppendLine($"{indent}{apiDtoField.Field.ToCSharpPropertyName(typeNameForDto)} = {apiDtoField.Field.ToCSharpVariableName()};");
                    }
                }
                indent.Decrement();
                builder.AppendLine($"{indent}}}");
                builder.AppendLine($"{indent}");
            }
        }
            
        // Generate properties for fields
        foreach (var apiDtoField in apiDtoFields)
        {
            builder.AppendLine(indent.Wrap(GenerateDtoFieldDefinition(apiDto.Id, typeNameForDto, apiDtoField.Field)));
        }
            
        // Implement IPropagatePropertyAccessPath?
        if (dtoHierarchy.Contains(nameof(IPropagatePropertyAccessPath)) && apiDto.HierarchyRole2 != HierarchyRole2.INTERFACE && apiDto.HierarchyRole2 != HierarchyRole2.SEALED_INTERFACE)
        {
            builder.AppendLine(indent.Wrap(GenerateDtoPropagatePropertyAccessPath(apiDto, apiDtoFields)));
        }
        
        indent.Decrement();
        builder.AppendLine($"{indent}}}");
        return builder.ToString();
    }