Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dpg): support logicalPath of lro #3839

Merged
merged 14 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/AutoRest.CSharp/Common/Input/CodeModelConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ public List<InputParameter> CreateOperationParameters(IReadOnlyCollection<Reques

return new OperationLongRunning(
FinalStateVia: operation.LongRunningFinalStateVia,
FinalResponse: CreateOperationResponse(operation.LongRunningFinalResponse)
FinalResponse: CreateOperationResponse(operation.LongRunningFinalResponse),
ResultPath: null
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@
// Licensed under the MIT License.

using Azure.Core;
using System.Linq;
using AutoRest.CSharp.Utilities;

namespace AutoRest.CSharp.Common.Input;

internal record OperationLongRunning(OperationFinalStateVia FinalStateVia, OperationResponse FinalResponse)
internal record OperationLongRunning(OperationFinalStateVia FinalStateVia, OperationResponse FinalResponse, string? ResultPath)
{
public OperationLongRunning() : this(FinalStateVia: OperationFinalStateVia.Location, FinalResponse: new OperationResponse()) { }
public OperationLongRunning() : this(FinalStateVia: OperationFinalStateVia.Location, FinalResponse: new OperationResponse(), null) { }

/// <summary>
/// Meaninngful return type of the long running operation.
archerzz marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
public InputType? ReturnType
{
get
{
if (FinalResponse.BodyType is null)
return null;

if (ResultPath is null)
return FinalResponse.BodyType;

var rawResponseType = (InputModelType)FinalResponse.BodyType;
return rawResponseType.Properties.FirstOrDefault(p => p.SerializedName == ResultPath)!.Type;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ protected LongRunningOperation(InputOperation operation, BuildContext context, L
FinalStateVia = operation.LongRunning.FinalStateVia;

var finalResponse = operation.LongRunning.FinalResponse;
var finalResponseType = finalResponse.BodyType;
var returnType = operation.LongRunning.ReturnType;

if (finalResponseType != null)
if (returnType != null)
{
ResultType = TypeFactory.GetOutputType(context.TypeFactory.CreateType(finalResponseType with {IsNullable = false}));
ResultSerialization = SerializationBuilder.Build(finalResponse.BodyMediaType, finalResponseType, ResultType, null);
ResultType = TypeFactory.GetOutputType(context.TypeFactory.CreateType(returnType with {IsNullable = false}));
ResultSerialization = SerializationBuilder.Build(finalResponse.BodyMediaType, returnType, ResultType, null);

var paging = operation.Paging;
if (paging != null)
Expand Down
16 changes: 15 additions & 1 deletion src/AutoRest.CSharp/LowLevel/Generation/DpgClientWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using AutoRest.CSharp.Common.Generation.Writers;
using AutoRest.CSharp.Common.Input;
Expand Down Expand Up @@ -357,12 +358,25 @@ private void WriteConvenienceLroMethod(LowLevelClientMethod clientMethod, Conven
.LineRaw(";");
// return ProtocolOperationHelpers.Convert(response, r => responseType.FromResponse(r), ClientDiagnostics, scopeName);
var diagnostic = convenienceMethod.Diagnostic ?? clientMethod.ProtocolMethodDiagnostic;
_writer.Line($"return {typeof(ProtocolOperationHelpers)}.{nameof(ProtocolOperationHelpers.Convert)}({responseVariable:I}, {responseType}.FromResponse, {fields.ClientDiagnosticsProperty.Name}, {diagnostic.ScopeName:L});");
_writer.Line($"return {typeof(ProtocolOperationHelpers)}.{nameof(ProtocolOperationHelpers.Convert)}({responseVariable:I}, {GetConvertMethodStatement(clientMethod.LongRunning!, responseType)}, {fields.ClientDiagnosticsProperty.Name}, {diagnostic.ScopeName:L});");
}
}
_writer.Line();
}

private string GetConvertMethodStatement(OperationLongRunning longRunning, CSharpType responseType)
archerzz marked this conversation as resolved.
Show resolved Hide resolved
{
if (longRunning.ResultPath.IsNullOrEmpty())
{
return $"{responseType.Name}.FromResponse";
}

return @$"r => {{
var resultJsonElement = {typeof(JsonDocument)}.{nameof(JsonDocument.Parse)}(r.{nameof(Response.Content)}).{nameof(JsonDocument.RootElement)}.{nameof(JsonElement.GetProperty)}(""{longRunning.ResultPath}"");
return {longRunning.ReturnType!.Name}.Deserialize{longRunning.ReturnType.Name}(resultJsonElement);
}}";
}

private void WriteConveniencePageableMethod(LowLevelClientMethod clientMethod, ConvenienceMethod convenienceMethod, ProtocolMethodPaging pagingInfo, ClientFields fields, bool async)
{
_writer.WritePageable(convenienceMethod, clientMethod.RequestMethod, pagingInfo.NextPageMethod, fields.ClientDiagnosticsProperty, fields.PipelineField, clientMethod.ProtocolMethodDiagnostic.ScopeName, pagingInfo.ItemName, pagingInfo.NextLinkName, async);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ private ReturnTypeChain BuildReturnTypes()
{
if (Operation.LongRunning != null)
{
return Operation.LongRunning.FinalResponse.BodyType;
return Operation.LongRunning.ReturnType;
}

var operationBodyTypes = Operation.Responses.Where(r => !r.IsErrorResponse).Select(r => r.BodyType).Distinct();
Expand Down
15 changes: 13 additions & 2 deletions src/TypeSpec.Extension/Emitter.Csharp/src/lib/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,11 @@ export function loadOperation(
if (op.verb !== "delete") {
const formattedType = getFormattedType(
program,
metadata.logicalResult
// TODO: we should check `logicalPath` or other ways to determine body type,
// after https://github.com/Azure/typespec-azure/issues/3725 is fixed
op.verb === "post"
archerzz marked this conversation as resolved.
Show resolved Hide resolved
? metadata.envelopeResult
: metadata.logicalResult
);
bodyType = getInputType(context, formattedType, models, enums);
}
Expand All @@ -401,7 +405,14 @@ export function loadOperation(
StatusCodes: op.verb === "delete" ? [204] : [200],
BodyType: bodyType,
BodyMediaType: BodyMediaType.Json
} as OperationResponse
} as OperationResponse,
ResultPath:
metadata.logicalPath ??
// https://github.com/Azure/typespec-azure/issues/3725
archerzz marked this conversation as resolved.
Show resolved Hide resolved
(metadata.envelopeResult != metadata.logicalResult &&
op.verb === "post"
? "result" // actually `result` is the only allowed path for now
: undefined)
} as OperationLongRunning;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ import { OperationResponse } from "./operationResponse.js";
export interface OperationLongRunning {
FinalStateVia: OperationFinalStateVia;
FinalResponse: OperationResponse;
ResultPath?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ model Pet {

interface Projects {
@doc("Creates a new pet or updates an existing one.")
createOrUpdate is LongRunningResourceCreateOrUpdate<Pet>;
createOrUpdate is LongRunningResourceCreateOrReplace<Pet>;
archerzz marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"Name": "Pet",
"Namespace": "LroOperation",
"IsNullable": false,
"Usage": "None",
"Usage": "RoundTrip",
"Properties": [
{
"$id": "3",
Expand Down Expand Up @@ -143,62 +143,55 @@
},
{
"$id": "19",
"Name": "contentType",
"NameInRequest": "Content-Type",
"Description": "This request has a JSON Merge Patch body.",
"Name": "resource",
"NameInRequest": "resource",
"Description": "The resource instance.",
"Type": {
"$id": "20",
"Name": "Literal",
"LiteralValueType": {
"$id": "21",
"Name": "String",
"Kind": "String",
"IsNullable": false
},
"Value": "application/merge-patch+json",
"IsNullable": false
},
"Location": "Header",
"DefaultValue": {
"$id": "22",
"Type": {
"$ref": "20"
},
"Value": "application/merge-patch+json"
"$ref": "2"
},
"Location": "Body",
"IsRequired": true,
"IsApiVersion": false,
"IsResourceParameter": false,
"IsContentType": true,
"IsContentType": false,
"IsEndpoint": false,
"SkipUrlEncoding": false,
"Explode": false,
"Kind": "Constant"
"Kind": "Method"
},
{
"$id": "23",
"Name": "resource",
"NameInRequest": "resource",
"Description": "The resource instance.",
"$id": "20",
"Name": "contentType",
"NameInRequest": "Content-Type",
"Type": {
"$ref": "2"
"$id": "21",
"Name": "String",
"Kind": "String",
"IsNullable": false
},
"Location": "Body",
"IsRequired": true,
"Location": "Header",
"IsApiVersion": false,
"IsResourceParameter": false,
"IsContentType": false,
"IsContentType": true,
"IsRequired": true,
"IsEndpoint": false,
"SkipUrlEncoding": false,
"Explode": false,
"Kind": "Method"
"Kind": "Constant",
"DefaultValue": {
"$id": "22",
"Type": {
"$ref": "21"
},
"Value": "application/json"
}
},
{
"$id": "24",
"$id": "23",
"Name": "accept",
"NameInRequest": "Accept",
"Type": {
"$id": "25",
"$id": "24",
"Name": "String",
"Kind": "String",
"IsNullable": false
Expand All @@ -213,17 +206,17 @@
"Explode": false,
"Kind": "Constant",
"DefaultValue": {
"$id": "26",
"$id": "25",
"Type": {
"$ref": "25"
"$ref": "24"
},
"Value": "application/json"
}
}
],
"Responses": [
{
"$id": "27",
"$id": "26",
"StatusCodes": [
201
],
Expand All @@ -233,12 +226,12 @@
"BodyMediaType": "Json",
"Headers": [
{
"$id": "28",
"$id": "27",
"Name": "Operation-Location",
"NameInResponse": "operationLocation",
"Description": "The location for monitoring the operation state.",
"Type": {
"$id": "29",
"$id": "28",
"Name": "ResourceLocation",
"Kind": "Uri",
"IsNullable": false
Expand All @@ -248,7 +241,7 @@
"IsErrorResponse": false
},
{
"$id": "30",
"$id": "29",
"StatusCodes": [
200
],
Expand All @@ -258,12 +251,12 @@
"BodyMediaType": "Json",
"Headers": [
{
"$id": "31",
"$id": "30",
"Name": "Operation-Location",
"NameInResponse": "operationLocation",
"Description": "The location for monitoring the operation state.",
"Type": {
"$id": "32",
"$id": "31",
"Name": "ResourceLocation",
"Kind": "Uri",
"IsNullable": false
Expand All @@ -273,19 +266,19 @@
"IsErrorResponse": false
}
],
"HttpMethod": "PATCH",
"HttpMethod": "PUT",
"RequestBodyMediaType": "Json",
"Uri": "{Endpoint}/language",
"Path": "/authoring/analyze-text/Pet/{name}",
"RequestMediaTypes": [
"application/merge-patch+json"
"application/json"
],
"BufferResponse": true,
"LongRunning": {
"$id": "33",
"$id": "32",
"FinalStateVia": 3,
"FinalResponse": {
"$id": "34",
"$id": "33",
"StatusCodes": [
200
],
Expand All @@ -296,11 +289,11 @@
}
},
"GenerateProtocolMethod": true,
"GenerateConvenienceMethod": false
"GenerateConvenienceMethod": true
}
],
"Protocol": {
"$id": "35"
"$id": "34"
},
"Creatable": true
}
Expand Down
5 changes: 4 additions & 1 deletion test/CadlRanchProjects.Tests/lro/standard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ public Task Action() => Test(async (host) =>
{
var operation = await new StandardClient(host, null).ExportAsync(WaitUntil.Completed, "madge", "json");
Assert.IsTrue(operation.HasCompleted);
// TODO: support model properties

var exportedUser = operation.Value;
Assert.AreEqual("madge", exportedUser.Name);
Assert.AreEqual("/users/madge", exportedUser.ResourceUri);
});
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -797,10 +797,11 @@
200
],
"BodyType": {
"$ref": "34"
"$ref": "14"
},
"BodyMediaType": "Json"
}
},
"ResultPath": "result"
},
"GenerateProtocolMethod": true,
"GenerateConvenienceMethod": true
Expand Down
Loading
Loading