Skip to content

Commit

Permalink
Update ClientPipelineApi, HttpMessageApi abstraction (microsoft#4816)
Browse files Browse the repository at this point in the history
- Remove unused `ClientPipelineApi.CreateMessage`
- Add `HttpRequestOptionsApi` to `ClientPipelineApi.Send(Async)`
- Replace `HttpMessageApi.ResponseClassifier` with
`HttpMessageApi.ApplyResponseClassifier`
- Make abstraction more generic

This fix is needed for below issues of Azure plugin:
Azure/azure-sdk-for-net#46899
Azure/azure-sdk-for-net#46900
Azure/azure-sdk-for-net#46901
Azure/azure-sdk-for-net#46902
  • Loading branch information
live1206 authored and swatikumar committed Nov 5, 2024
1 parent fa8a67d commit 84992c3
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
using System;
using Microsoft.Generator.CSharp.Expressions;
using Microsoft.Generator.CSharp.Primitives;
using Microsoft.Generator.CSharp.Providers;
using Microsoft.Generator.CSharp.Snippets;
using Microsoft.Generator.CSharp.Statements;

namespace Microsoft.Generator.CSharp.ClientModel.Providers
{
Expand All @@ -18,13 +20,11 @@ protected ClientPipelineApi(Type type, ValueExpression original) : base(type, or
{
}

public abstract HttpMessageApi CreateMessage();

public abstract ValueExpression CreateMessage(HttpRequestOptionsApi requestOptions, ValueExpression responseClassifier);

public abstract InvokeMethodExpression Send(HttpMessageApi message);
public abstract MethodBodyStatement Send(HttpMessageApi message, HttpRequestOptionsApi options);

public abstract InvokeMethodExpression SendAsync(HttpMessageApi message);
public abstract MethodBodyStatement SendAsync(HttpMessageApi message, HttpRequestOptionsApi options);

public abstract ValueExpression Create(ValueExpression options, ValueExpression perRetryPolicies);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ protected HttpMessageApi(Type type, ValueExpression original) : base(type, origi

public abstract ValueExpression BufferResponse();

public abstract ValueExpression ResponseClassifier();
public abstract MethodBodyStatement ApplyResponseClassifier(StatusCodeClassifierApi statusCodeClassifier);

public abstract MethodBodyStatement Apply(ValueExpression options);
public abstract MethodBodyStatement ApplyRequestOptions(HttpRequestOptionsApi options);

public abstract MethodBodyStatement[] ExtractResponse();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.Generator.CSharp.Expressions;
using Microsoft.Generator.CSharp.Primitives;
using Microsoft.Generator.CSharp.Snippets;
using Microsoft.Generator.CSharp.Statements;

namespace Microsoft.Generator.CSharp.ClientModel.Providers
{
Expand All @@ -15,11 +16,11 @@ protected HttpRequestApi(CSharpType type, ValueExpression original) : base(type,
{
}

public abstract AssignmentExpression SetMethod(string httpMethod);
public abstract MethodBodyStatement SetMethod(string httpMethod);

public abstract AssignmentExpression SetUri(ValueExpression uri);
public abstract MethodBodyStatement SetUri(ValueExpression uri);

public abstract InvokeMethodExpression SetHeaders(IReadOnlyList<ValueExpression> arguments);
public abstract MethodBodyStatement SetHeaders(IReadOnlyList<ValueExpression> arguments);

public abstract ValueExpression Content();
public abstract HttpRequestApi FromExpression(ValueExpression original);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using Microsoft.Generator.CSharp.Expressions;
using Microsoft.Generator.CSharp.Providers;
using Microsoft.Generator.CSharp.Snippets;

namespace Microsoft.Generator.CSharp.ClientModel.Providers
Expand Down Expand Up @@ -33,5 +34,55 @@ public static T ToApi<T>(this ValueExpression valueExpression) where T : ScopedA
throw new InvalidOperationException($"Invalid type {typeof(T)}");
}
}

public static T ToApi<T>(this ParameterProvider valueExpression) where T : ScopedApi
{
switch (typeof(T).Name)
{
case nameof(ClientResponseApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.FromExpression(valueExpression);
case nameof(HttpResponseApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.FromExpression(valueExpression);
case nameof(HttpRequestOptionsApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.HttpRequestOptionsApi.FromExpression(valueExpression);
case nameof(HttpMessageApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.HttpMessageApi.FromExpression(valueExpression);
case nameof(HttpRequestApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.HttpRequestApi.FromExpression(valueExpression);
case nameof(ClientPipelineApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.ClientPipelineApi.FromExpression(valueExpression);
case nameof(StatusCodeClassifierApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.StatusCodeClassifierApi.FromExpression(valueExpression);
case nameof(RequestContentApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.RequestContentApi.FromExpression(valueExpression);
default:
throw new InvalidOperationException($"Invalid type {typeof(T)}");
}
}

public static T ToApi<T>(this PropertyProvider valueExpression) where T : ScopedApi
{
switch (typeof(T).Name)
{
case nameof(ClientResponseApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.FromExpression(valueExpression);
case nameof(HttpResponseApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.FromExpression(valueExpression);
case nameof(HttpRequestOptionsApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.HttpRequestOptionsApi.FromExpression(valueExpression);
case nameof(HttpMessageApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.HttpMessageApi.FromExpression(valueExpression);
case nameof(HttpRequestApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.HttpRequestApi.FromExpression(valueExpression);
case nameof(ClientPipelineApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.ClientPipelineApi.FromExpression(valueExpression);
case nameof(StatusCodeClassifierApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.StatusCodeClassifierApi.FromExpression(valueExpression);
case nameof(RequestContentApi):
return (T)(object)ClientModelPlugin.Instance.TypeFactory.RequestContentApi.FromExpression(valueExpression);
default:
throw new InvalidOperationException($"Invalid type {typeof(T)}");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ public ClientPipelineExtensionsDefinition()
{
_pipelineParam = new ParameterProvider("pipeline", FormattableStringHelpers.Empty, ClientModelPlugin.Instance.TypeFactory.ClientPipelineApi.ClientPipelineType);
_messageParam = new ParameterProvider("message", FormattableStringHelpers.Empty, ClientModelPlugin.Instance.TypeFactory.HttpMessageApi.HttpMessageType);
_requestOptionsParam = new ParameterProvider("options", FormattableStringHelpers.Empty, ClientModelPlugin.Instance.TypeFactory.HttpRequestOptionsApi.HttpRequestOptionsType);
_pipeline = _pipelineParam.AsExpression.ToApi<ClientPipelineApi>();
_message = _messageParam.AsExpression.ToApi<HttpMessageApi>();
_options = _requestOptionsParam.AsExpression.ToApi<HttpRequestOptionsApi>();
_requestOptionsParam = new ParameterProvider(ClientModelPlugin.Instance.TypeFactory.HttpRequestOptionsApi.ParameterName, FormattableStringHelpers.Empty, ClientModelPlugin.Instance.TypeFactory.HttpRequestOptionsApi.HttpRequestOptionsType);
_pipeline = _pipelineParam.ToApi<ClientPipelineApi>();
_message = _messageParam.ToApi<HttpMessageApi>();
_options = _requestOptionsParam.ToApi<HttpRequestOptionsApi>();
}

protected override TypeSignatureModifiers GetDeclarationModifiers()
Expand Down Expand Up @@ -124,7 +124,7 @@ private MethodProvider BuildProcessMessage()
var clientErrorNoThrow = _options.NoThrow();
return new MethodProvider(signature, new MethodBodyStatement[]
{
_pipeline.Send(_message).Terminate(),
_pipeline.Send(_message, _options),
MethodBodyStatement.EmptyLine,
new IfStatement(_message.Response().IsError().And(new BinaryOperatorExpression("&", _options.NullConditional().Property("ErrorOptions"), clientErrorNoThrow).NotEqual(clientErrorNoThrow)))
{
Expand Down Expand Up @@ -167,7 +167,7 @@ private MethodProvider BuildProcessMessageAsync()
var clientErrorNoThrow = _options.NoThrow();
return new MethodProvider(signature, new MethodBodyStatement[]
{
_pipeline.SendAsync(_message).Terminate(),
_pipeline.SendAsync(_message, _options),
MethodBodyStatement.EmptyLine,
new IfStatement(_message.Response().IsError().And(new BinaryOperatorExpression("&", _options.NullConditional().Property("ErrorOptions"), clientErrorNoThrow).NotEqual(clientErrorNoThrow)))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.ClientModel.Primitives;
using Microsoft.Generator.CSharp.Expressions;
using Microsoft.Generator.CSharp.Primitives;
using Microsoft.Generator.CSharp.Statements;
using static Microsoft.Generator.CSharp.Snippets.Snippet;

namespace Microsoft.Generator.CSharp.ClientModel.Providers
Expand All @@ -26,23 +27,20 @@ public ClientPipelineProvider(ValueExpression original) : base(typeof(ClientPipe
public override ValueExpression Create(ValueExpression options, ValueExpression perRetryPolicies)
=> Static<ClientPipeline>().Invoke(nameof(ClientPipeline.Create), [options, New.Array(ClientModelPlugin.Instance.TypeFactory.ClientPipelineApi.PipelinePolicyType), perRetryPolicies, New.Array(ClientModelPlugin.Instance.TypeFactory.ClientPipelineApi.PipelinePolicyType)]).As<ClientPipeline>();

public override HttpMessageApi CreateMessage()
=> new PipelineMessageProvider(Original.Invoke(nameof(ClientPipeline.CreateMessage)));

public override ValueExpression CreateMessage(HttpRequestOptionsApi requestOptions, ValueExpression responseClassifier)
=> Original.Invoke(nameof(ClientPipeline.CreateMessage), requestOptions, responseClassifier).As<PipelineMessage>();
=> new PipelineMessageProvider(Original.Invoke(nameof(ClientPipeline.CreateMessage)));

public override ClientPipelineApi FromExpression(ValueExpression expression)
=> new ClientPipelineProvider(expression);

public override ValueExpression PerRetryPolicy(params ValueExpression[] arguments)
=> Static<ApiKeyAuthenticationPolicy>().Invoke(nameof(ApiKeyAuthenticationPolicy.CreateHeaderApiKeyPolicy), arguments).As<ApiKeyAuthenticationPolicy>();

public override InvokeMethodExpression Send(HttpMessageApi message)
=> Original.Invoke(nameof(ClientPipeline.Send), [message]);
public override MethodBodyStatement Send(HttpMessageApi message, HttpRequestOptionsApi options)
=> Original.Invoke(nameof(ClientPipeline.Send), [message]).Terminate();

public override InvokeMethodExpression SendAsync(HttpMessageApi message)
=> Original.Invoke(nameof(ClientPipeline.SendAsync), [message], true);
public override MethodBodyStatement SendAsync(HttpMessageApi message, HttpRequestOptionsApi options)
=> Original.Invoke(nameof(ClientPipeline.SendAsync), [message], true).Terminate();

public override ClientPipelineApi ToExpression() => this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System.ClientModel.Primitives;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.Generator.CSharp.Expressions;
using Microsoft.Generator.CSharp.Primitives;
using Microsoft.Generator.CSharp.Statements;
Expand All @@ -27,10 +28,10 @@ public override ValueExpression BufferResponse()
public override HttpResponseApi Response()
=> new PipelineResponseProvider(Original.Property(nameof(PipelineMessage.Response)));

public override ValueExpression ResponseClassifier()
=> Original.Property(nameof(PipelineMessage.ResponseClassifier));
public override MethodBodyStatement ApplyResponseClassifier(StatusCodeClassifierApi statusCodeClassifier)
=> Original.Property(nameof(PipelineMessage.ResponseClassifier)).Assign(statusCodeClassifier).Terminate();

public override MethodBodyStatement Apply(ValueExpression options)
public override MethodBodyStatement ApplyRequestOptions(HttpRequestOptionsApi options)
=> Original.Invoke(nameof(PipelineMessage.Apply), options).Terminate();

public override MethodBodyStatement[] ExtractResponse()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.Generator.CSharp.Expressions;
using Microsoft.Generator.CSharp.ClientModel.Snippets;
using static Microsoft.Generator.CSharp.Snippets.Snippet;
using Microsoft.Generator.CSharp.Statements;

namespace Microsoft.Generator.CSharp.ClientModel.Providers
{
Expand All @@ -24,14 +25,14 @@ public override ValueExpression Content()
public override HttpRequestApi FromExpression(ValueExpression original)
=> new PipelineRequestProvider(original);

public override InvokeMethodExpression SetHeaders(IReadOnlyList<ValueExpression> arguments)
=> Original.Property(nameof(PipelineRequest.Headers)).Invoke(nameof(PipelineRequestHeaders.Set), arguments);
public override MethodBodyStatement SetHeaders(IReadOnlyList<ValueExpression> arguments)
=> Original.Property(nameof(PipelineRequest.Headers)).Invoke(nameof(PipelineRequestHeaders.Set), arguments).Terminate();

public override AssignmentExpression SetMethod(string httpMethod)
=> Original.Property(nameof(PipelineRequest.Method)).Assign(Literal(httpMethod));
public override MethodBodyStatement SetMethod(string httpMethod)
=> Original.Property(nameof(PipelineRequest.Method)).Assign(Literal(httpMethod)).Terminate();

public override AssignmentExpression SetUri(ValueExpression value)
=> Original.Property("Uri").Assign(value.As<ClientUriBuilderDefinition>().ToUri());
public override MethodBodyStatement SetUri(ValueExpression value)
=> Original.Property("Uri").Assign(value.As<ClientUriBuilderDefinition>().ToUri()).Terminate();

public override HttpRequestApi ToExpression() => this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ private bool IsCreateRequest(MethodProvider method)

private MethodProvider BuildCreateRequestMethod(InputOperation operation)
{
var pipelineField = ((MemberExpression)ClientProvider.PipelineProperty).ToApi<ClientPipelineApi>();
var pipelineField = ClientProvider.PipelineProperty.ToApi<ClientPipelineApi>();

var options = ScmKnownParameters.RequestOptions;
var signature = new MethodSignature(
Expand Down Expand Up @@ -165,18 +165,18 @@ private MethodProvider BuildCreateRequestMethod(InputOperation operation)
signature,
new MethodBodyStatements(
[
Declare("message", pipelineField.CreateMessage().ToApi<HttpMessageApi>(), out HttpMessageApi message),
message.ResponseClassifier().Assign(classifier).Terminate(),
Declare("request", message.Request().ToApi<HttpRequestApi>(), out HttpRequestApi request), // ScopedApi<PipelineRequest>
request.SetMethod(operation.HttpMethod).Terminate(),
Declare("message", pipelineField.CreateMessage(options.ToApi<HttpRequestOptionsApi>(), classifier).ToApi<HttpMessageApi>(), out HttpMessageApi message),
message.ApplyResponseClassifier(classifier.ToApi<StatusCodeClassifierApi>()),
Declare("request", message.Request().ToApi<HttpRequestApi>(), out HttpRequestApi request),
request.SetMethod(operation.HttpMethod),
Declare("uri", New.Instance<ClientUriBuilderDefinition>(), out ScopedApi<ClientUriBuilderDefinition> uri),
uri.Reset(ClientProvider.EndpointField).Terminate(),
.. AppendPathParameters(uri, operation, paramMap),
.. AppendQueryParameters(uri, operation, paramMap),
request.SetUri(uri).Terminate(),
request.SetUri(uri),
.. AppendHeaderParameters(request, operation, paramMap),
.. GetSetContent(request, signature.Parameters),
message.Apply(options),
message.ApplyRequestOptions(options.ToApi<HttpRequestOptionsApi>()),
Return(message)
]),
this);
Expand Down Expand Up @@ -231,7 +231,7 @@ private IEnumerable<MethodBodyStatement> AppendHeaderParameters(HttpRequestApi r
}
else
{
statement = request.SetHeaders([Literal(inputParameter.NameInRequest), toStringExpression.As<string>()]).Terminate();
statement = request.SetHeaders([Literal(inputParameter.NameInRequest), toStringExpression.As<string>()]);
}
statements.Add(statement);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.Generator.CSharp.ClientModel.Providers;
using Microsoft.Generator.CSharp.Expressions;
using Microsoft.Generator.CSharp.Primitives;
using Microsoft.Generator.CSharp.Statements;
using Microsoft.Generator.CSharp.Tests.Common;
using NUnit.Framework;

Expand All @@ -28,7 +29,6 @@ public void ValidateBodyOfRestClientOperationIsOverridden()

Assert.NotNull(method);
Assert.NotNull(method!.BodyStatements);
var test = method?.BodyStatements?.ToDisplayString();
Assert.AreEqual(Helpers.GetExpectedFromFile(), method!.BodyStatements!.ToDisplayString());
}

Expand Down Expand Up @@ -58,9 +58,6 @@ public TestClientPipelineApi(ValueExpression original) : base(typeof(string), or
public override ValueExpression Create(ValueExpression options, ValueExpression perRetryPolicies)
=> Original.Invoke("GetFakeCreate", [options, perRetryPolicies]);

public override HttpMessageApi CreateMessage()
=> Original.Invoke("GetFakeCreateMessage").ToApi<HttpMessageApi>();

public override ValueExpression CreateMessage(HttpRequestOptionsApi requestOptions, ValueExpression responseClassifier)
=> Original.Invoke("GetFakeCreateMessage", [requestOptions, responseClassifier]);

Expand All @@ -70,11 +67,11 @@ public override ClientPipelineApi FromExpression(ValueExpression expression)
public override ValueExpression PerRetryPolicy(params ValueExpression[] arguments)
=> Original.Invoke("GetFakePerRetryPolicy", arguments);

public override InvokeMethodExpression Send(HttpMessageApi message)
=> Original.Invoke("GetFakeSend", message);
public override MethodBodyStatement Send(HttpMessageApi message, HttpRequestOptionsApi options)
=> Original.Invoke("GetFakeSend", [message, options]).Terminate();

public override InvokeMethodExpression SendAsync(HttpMessageApi message)
=> Original.Invoke("GetFakeSendAsync", message);
public override MethodBodyStatement SendAsync(HttpMessageApi message, HttpRequestOptionsApi options)
=> Original.Invoke("GetFakeSendAsync", [message, options]).Terminate();

public override ClientPipelineApi ToExpression() => this;
}
Expand Down
Loading

0 comments on commit 84992c3

Please sign in to comment.