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();
}