private string GenerateMethodForApiEndpoint()

in src/JetBrains.Space.Generator/CodeGeneration/CSharp/Generators/CSharpApiModelResourceGenerator.cs [134:349]


    private string GenerateMethodForApiEndpoint(ApiEndpoint apiEndpoint, string baseEndpointPath)
    {
        var indent = new Indent();
        var builder = new CSharpBuilder();
            
        var endpointPath = (baseEndpointPath + "/" + apiEndpoint.Path.Segments.ToPath()).TrimEnd('/');
        
        var apiCallMethod = apiEndpoint.Method.ToHttpMethod();
        var methodNameForEndpoint = apiEndpoint.ToCSharpMethodName();
            
        var isResponsePrimitiveOrArrayOfPrimitive = apiEndpoint.ResponseBody is ApiFieldType.Primitive 
            or ApiFieldType.Array { ElementType: ApiFieldType.Primitive };

        var isResponseSyncBatch = apiEndpoint.ResponseBody is
            ApiFieldType.Object { Kind: ApiFieldType.Object.ObjectKind.SYNC_BATCH };

        if (apiEndpoint.ResponseBody == null)
        {
            var methodParametersBuilder = new MethodParametersBuilder(_codeGenerationContext)
                .WithParametersForApiParameters(apiEndpoint.Parameters);
                
            if (apiEndpoint.RequestBody != null)
            {
                if (apiEndpoint.RequestBody is ApiFieldType.Object requestBody && FeatureFlags.DoNotExposeRequestObjects)
                {
                    methodParametersBuilder = methodParametersBuilder
                        .WithParametersForApiFields(requestBody.Fields);
                }
                else
                {
                    methodParametersBuilder = methodParametersBuilder
                        .WithParameter(
                            apiEndpoint.ToCSharpRequestBodyClassName(endpointPath)!,
                            "data");
                }
            }
                
            methodParametersBuilder = methodParametersBuilder
                .WithParameter(CSharpType.RequestHeaders.Value,
                    "requestHeaders",
                    CSharpExpression.NullLiteral)
                .WithParameter(CSharpType.CancellationToken.Value,
                    "cancellationToken",
                    CSharpExpression.DefaultLiteral);
                
            builder.Append(
                indent.Wrap(GenerateMethodDocumentationForEndpoint(apiEndpoint, methodParametersBuilder)));
            builder.Append($"{indent}public async Task {methodNameForEndpoint}Async(");
            builder.Append(methodParametersBuilder.BuildMethodParametersList());
            builder.AppendLine(")");
            builder.AppendLine($"{indent}{{");
                
            indent.Increment();
                
            // Generate query string
            var requestParametersBuilder = new QueryStringParameterConversionGenerator("queryParameters", _codeGenerationContext)
                .WithQueryStringParametersForEndpoint(apiEndpoint);
                
            if (apiEndpoint.ResponseBody != null && !isResponsePrimitiveOrArrayOfPrimitive)
            {
                var partialType = "Partial<" + apiEndpoint.ResponseBody.GetArrayElementTypeOrType().ToCSharpType(_codeGenerationContext) + ">";
                    
                requestParametersBuilder = requestParametersBuilder
                    .WithQueryStringParameter("$fields", $"(partial != null ? partial(new {partialType}()) : {partialType}.Default()).ToString()");
            }
                
            builder.AppendLine($"{indent}var {requestParametersBuilder.TargetNameValueCollectionName} = new NameValueCollection();");
            requestParametersBuilder.WriteTo(builder, indent);
            builder.AppendLine($"{indent}");
                
            // Generate HTTP request
            builder.Append($"{indent}await _connection.RequestResourceAsync");
            builder.Append("(\"" + apiCallMethod + "\", ");
            builder.Append("$\"api/http/" + endpointPath + "{" + requestParametersBuilder.TargetNameValueCollectionName + ".ToQueryString()}");
            builder.Append("\"");

            if (apiEndpoint.RequestBody != null)
            {
                if (apiEndpoint.RequestBody is ApiFieldType.Object requestBody && FeatureFlags.DoNotExposeRequestObjects)
                {
                    builder.Append(", " + ConstructNewRequestObject(indent, apiEndpoint, requestBody, endpointPath));
                }
                else
                {
                    builder.Append(", data");
                }
            }

            if (!isResponseSyncBatch)
            {
                builder.Append(", requestHeaders: null");
            }
            else
            {
                builder.Append($", requestHeaders: {nameof(EpochTrackerHeaders)}.{nameof(EpochTrackerHeaders.GenerateFrom)}(_connection.ServerUrl, {nameof(EpochTracker)}.{nameof(EpochTracker.Instance)})");
            }
            builder.Append($", functionName: \"{methodNameForEndpoint}\"");
            builder.Append(", cancellationToken: cancellationToken");
            builder.AppendLine(");");
            indent.Decrement();
            builder.AppendLine($"{indent}}}");
        }
        else if (apiEndpoint.ResponseBody != null)
        {
            var methodParametersBuilder = new MethodParametersBuilder(_codeGenerationContext)
                .WithParametersForApiParameters(apiEndpoint.Parameters);
                
            if (apiEndpoint.RequestBody != null)
            {
                if (apiEndpoint.RequestBody is ApiFieldType.Object requestBody && FeatureFlags.DoNotExposeRequestObjects)
                {
                    methodParametersBuilder = methodParametersBuilder
                        .WithParametersForApiFields(requestBody.Fields);
                }
                else
                {
                    methodParametersBuilder = methodParametersBuilder
                        .WithParameter(
                            apiEndpoint.ToCSharpRequestBodyClassName(endpointPath)!,
                            "data");
                }
            }
        
            if (apiEndpoint.ResponseBody != null && !isResponsePrimitiveOrArrayOfPrimitive)
            {
                var partialType = "Partial<" + apiEndpoint.ResponseBody.GetArrayElementTypeOrType().ToCSharpType(_codeGenerationContext) + ">";
                var funcType = $"Func<{partialType}, {partialType}>?";
                methodParametersBuilder = methodParametersBuilder
                    .WithParameter(
                        funcType,
                        "partial",
                        CSharpExpression.NullLiteral);
            }
                
            methodParametersBuilder = methodParametersBuilder
                .WithParameter(CSharpType.RequestHeaders.Value,
                    "requestHeaders",
                    CSharpExpression.NullLiteral)
                .WithParameter(CSharpType.CancellationToken.Value,
                    "cancellationToken",
                    CSharpExpression.DefaultLiteral);
        
            builder.Append(
                indent.Wrap(GenerateMethodDocumentationForEndpoint(apiEndpoint, methodParametersBuilder)));
            builder.Append($"{indent}public async Task<");
            builder.Append(apiEndpoint.ResponseBody!.ToCSharpType(_codeGenerationContext));
            builder.Append(">");
            builder.Append($" {methodNameForEndpoint}Async(");
            builder.Append(methodParametersBuilder.BuildMethodParametersList());
            builder.AppendLine(")");
            builder.AppendLine($"{indent}{{");
                
            indent.Increment();
                
            // Generate query string
            var requestParametersBuilder = new QueryStringParameterConversionGenerator("queryParameters", _codeGenerationContext)
                .WithQueryStringParametersForEndpoint(apiEndpoint);
                
            if (apiEndpoint.ResponseBody != null && !isResponsePrimitiveOrArrayOfPrimitive)
            {
                var partialType = "Partial<" + apiEndpoint.ResponseBody.GetArrayElementTypeOrType().ToCSharpType(_codeGenerationContext) + ">";
                    
                requestParametersBuilder = requestParametersBuilder
                    .WithQueryStringParameter("$fields", $"(partial != null ? partial(new {partialType}()) : {partialType}.Default()).ToString()");
            }
                
            builder.AppendLine($"{indent}var {requestParametersBuilder.TargetNameValueCollectionName} = new NameValueCollection();");
            requestParametersBuilder.WriteTo(builder, indent);
            builder.AppendLine($"{indent}");

            // Generate HTTP request
            builder.Append($"{indent}return await _connection.RequestResourceAsync<");
            if (apiEndpoint.RequestBody != null)
            {
                builder.Append(apiEndpoint.ToCSharpRequestBodyClassName(endpointPath)!);
                builder.Append(", ");
            }
            builder.Append(apiEndpoint.ResponseBody!.ToCSharpType(_codeGenerationContext));
            builder.Append(">");
            builder.Append("(\"" + apiCallMethod + "\", ");
            builder.Append("$\"api/http/" + endpointPath + "{" + requestParametersBuilder.TargetNameValueCollectionName + ".ToQueryString()}");
            builder.Append("\"");
                
            if (apiEndpoint.RequestBody != null)
            {
                if (apiEndpoint.RequestBody is ApiFieldType.Object requestBody && FeatureFlags.DoNotExposeRequestObjects)
                {
                    builder.Append(", " + ConstructNewRequestObject(indent, apiEndpoint, requestBody, endpointPath));
                }
                else
                {
                    builder.Append(", data");
                }
            }
                
            if (!isResponseSyncBatch)
            {
                builder.Append(", requestHeaders: null");
            }
            else
            {
                builder.Append($", requestHeaders: {nameof(EpochTrackerHeaders)}.{nameof(EpochTrackerHeaders.GenerateFrom)}(_connection.ServerUrl, {nameof(EpochTracker)}.{nameof(EpochTracker.Instance)})");
            }
            builder.Append($", functionName: \"{methodNameForEndpoint}\"");
            builder.Append(", cancellationToken: cancellationToken");
            builder.AppendLine(");");
            indent.Decrement();
            builder.AppendLine($"{indent}}}");
        }
        else
        {
            builder.AppendLine($"{indent}#warning UNSUPPORTED CASE - " + apiEndpoint.ToCSharpMethodName() + " - " + apiEndpoint.Method.ToHttpMethod() + " " + endpointPath);
        }
            
        return builder.ToString();
    }