Skip to content

Commit

Permalink
Add convenience methods to clients (#3700)
Browse files Browse the repository at this point in the history
  • Loading branch information
m-nash committed Jun 28, 2024
1 parent 434f058 commit 3a15bee
Show file tree
Hide file tree
Showing 13 changed files with 538 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ private MethodProvider BuildProcessMessage()
Throw(New.Instance(typeof(ClientResultException), _message.Response))
},
MethodBodyStatement.EmptyLine,
Declare(typeof(PipelineResponse), "response", new TernaryConditionalExpression(_message.BufferResponse, _message.Response, _message.ExtractResponse()), out var response),
Declare("response", typeof(PipelineResponse), new TernaryConditionalExpression(_message.BufferResponse, _message.Response, _message.ExtractResponse()), out var response),
Return(response)
}, this);
}
Expand Down Expand Up @@ -173,7 +173,7 @@ private MethodProvider BuildProcessMessageAsync()
Throw(new InvokeStaticMethodExpression(typeof(ClientResultException), nameof(ClientResultException.CreateAsync), [_message.Response], CallAsAsync: true))
},
MethodBodyStatement.EmptyLine,
Declare(typeof(PipelineResponse), "response", new TernaryConditionalExpression(_message.BufferResponse, _message.Response, _message.ExtractResponse()), out var response),
Declare("response", typeof(PipelineResponse), new TernaryConditionalExpression(_message.BufferResponse, _message.Response, _message.ExtractResponse()), out var response),
Return(response)
}, 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;
using System.ClientModel;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.IO;
Expand Down Expand Up @@ -159,7 +160,10 @@ protected override MethodProvider[] BuildMethods()
// Add PersistableModel serialization methods
BuildPersistableModelWriteMethod(),
BuildPersistableModelCreateMethod(),
BuildPersistableModelGetFormatFromOptionsMethod()
BuildPersistableModelGetFormatFromOptionsMethod(),
//cast operators
BuildImplicitToBinaryContent(),
BuildExplicitFromClientResult()
};

if (_isStruct)
Expand All @@ -170,6 +174,26 @@ protected override MethodProvider[] BuildMethods()
return [.. methods];
}

private MethodProvider BuildExplicitFromClientResult()
{
var result = new ParameterProvider("result", $"The {typeof(ClientResult):C} to deserialize the {Type:C} from.", typeof(ClientResult));
var modifiers = MethodSignatureModifiers.Public | MethodSignatureModifiers.Static | MethodSignatureModifiers.Explicit | MethodSignatureModifiers.Operator;
return new MethodProvider(
new MethodSignature(Type.Name, null, modifiers, null, null, [result]),
Throw(New.NotImplementedException(Literal("Not implemented"))), //TODO https://github.com/microsoft/typespec/issues/3696
this);
}

private MethodProvider BuildImplicitToBinaryContent()
{
var model = new ParameterProvider(Type.Name.ToVariableName(), $"The {Type:C} to serialize into {typeof(BinaryContent):C}", Type);
var modifiers = MethodSignatureModifiers.Public | MethodSignatureModifiers.Static | MethodSignatureModifiers.Implicit | MethodSignatureModifiers.Operator;
return new MethodProvider(
new MethodSignature(nameof(BinaryContent), null, modifiers, null, null, [model]),
Throw(New.NotImplementedException(Literal("Not implemented"))), //TODO https://github.com/microsoft/typespec/issues/3696
this);
}

/// <summary>
/// Builds the types that the model type serialization implements.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ internal class ScmMethodProviderCollection : MethodProviderCollection
{
private string _cleanOperationName;
private string _createRequestMethodName;
private ParameterProvider? _bodyParameter;

public ScmMethodProviderCollection(InputOperation operation, TypeProvider enclosingType)
: base(operation, enclosingType)
Expand All @@ -34,24 +35,66 @@ protected override IReadOnlyList<MethodProvider> BuildMethods()
// TO-DO: Add Protocol and Convenience methods https://github.com/Azure/autorest.csharp/issues/4585, https://github.com/Azure/autorest.csharp/issues/4586
BuildCreateMessageMethod(),
BuildProtocolMethod(false),
BuildProtocolMethod(true)
BuildProtocolMethod(true),
BuildConvenienceMethod(false),
BuildConvenienceMethod(true),
];
}

private MethodProvider BuildConvenienceMethod(bool isAsync)
{
ClientProvider? client = _enclosingType as ClientProvider;
if (client is null)
{
throw new InvalidOperationException("Protocol methods can only be built for client types.");
}

var methodModifier = MethodSignatureModifiers.Public | MethodSignatureModifiers.Virtual;
if (isAsync)
{
methodModifier |= MethodSignatureModifiers.Async;
}
var methodSignature = new MethodSignature(
isAsync ? _cleanOperationName + "Async" : _cleanOperationName,
FormattableStringHelpers.FromString(_operation.Description),
methodModifier,
GetResponseType(_operation.Responses, true, isAsync),
null,
Parameters: ConvenienceMethodParameters);
var processMessageName = isAsync ? "ProcessMessageAsync" : "ProcessMessage";
MethodBodyStatement[] methodBody = _bodyParameter is null
? [Return(This.Invoke(methodSignature.Name, [.. ConvenienceMethodParameters, Null], null, isAsync, isAsync))]
: [
Declare("result", typeof(ClientResult), This.Invoke(methodSignature.Name, [.. ConvenienceMethodParameters, Null], null, isAsync, isAsync), out var result),
Return(new InvokeStaticMethodExpression(
typeof(ClientResult),
nameof(ClientResult.FromValue),
[result.CastTo(_bodyParameter.Type), result.Invoke("GetRawResponse")])),
];

var convenienceMethod = new MethodProvider(methodSignature, methodBody, _enclosingType);
convenienceMethod.XmlDocs!.Exceptions.Add(new(typeof(ClientResultException), "Service returned a non-success status code.", []));
return convenienceMethod;
}

private List<ParameterProvider>? _methodParameters;
private List<ParameterProvider> MethodParameters => _methodParameters ??= GetMethodParameters(_operation);
private List<ParameterProvider> MethodParameters => _methodParameters ??= GetMethodParameters(false);

private List<ParameterProvider>? _convenienceMethodParameters;
private List<ParameterProvider> ConvenienceMethodParameters => _convenienceMethodParameters ??= GetMethodParameters(true);

private static List<ParameterProvider> GetMethodParameters(InputOperation operation)
private List<ParameterProvider> GetMethodParameters(bool isConvenience)
{
List<ParameterProvider> methodParameters = new();
foreach (InputParameter inputParam in operation.Parameters)
foreach (InputParameter inputParam in _operation.Parameters)
{
if (inputParam.Kind != InputOperationParameterKind.Method)
continue;
if (inputParam.Location == RequestLocation.Body)
{
// TODO: add concrete body with https://github.com/Azure/autorest.csharp/issues/4586
methodParameters.Add(ScmKnownParameters.BinaryContent);
var parameter = isConvenience ? ClientModelPlugin.Instance.TypeFactory.CreateCSharpParam(inputParam) : ScmKnownParameters.BinaryContent;
_bodyParameter = parameter;
methodParameters.Add(parameter);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void TestDefaultCSharpMethodCollection(InputOperation inputOperation)
{
var methodCollection = new ScmMethodProviderCollection(inputOperation, new MockClientTypeProvider());
Assert.IsNotNull(methodCollection);
Assert.AreEqual(3, methodCollection.Count);
Assert.AreEqual(5, methodCollection.Count);

var method = methodCollection![0];
var signature = method.Signature;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static MethodBodyStatement UsingDeclare(string name, StreamSnippet value,
public static MethodBodyStatement UsingDeclare(VariableExpression variable, ValueExpression value)
=> new DeclarationExpression(variable, false, true).Assign(value).Terminate();

public static MethodBodyStatement Declare(CSharpType variableType, string name, ValueExpression value, out VariableExpression variable)
public static MethodBodyStatement Declare(string name, CSharpType variableType, ValueExpression value, out VariableExpression variable)
{
var variableRef = new VariableExpression(variableType, name);
variable = variableRef;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ public IDisposable WriteMethodDeclarationNoScope(MethodSignatureBase methodBase,

if (isImplicitOrExplicit)
{
Append($"{method.ReturnType}");
AppendIf($"{method.ReturnType}", method.ReturnType is not null);
}

if (method.ExplicitInterface is not null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#nullable disable

using System;
using System.ClientModel;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Text.Json;
Expand Down Expand Up @@ -75,5 +76,17 @@ Friend IPersistableModel<Friend>.Create(BinaryData data, ModelReaderWriterOption
}

string IPersistableModel<Friend>.GetFormatFromOptions(ModelReaderWriterOptions options) => "J";

/// <param name="friend"> The <see cref="Friend"/> to serialize into <see cref="BinaryContent"/>. </param>
public static implicit operator BinaryContent(Friend friend)
{
throw new NotImplementedException("Not implemented");
}

/// <param name="result"> The <see cref="ClientResult"/> to deserialize the <see cref="Friend"/> from. </param>
public static explicit operator Friend(ClientResult result)
{
throw new NotImplementedException("Not implemented");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#nullable disable

using System;
using System.ClientModel;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Text.Json;
Expand Down Expand Up @@ -102,5 +103,17 @@ ModelWithRequiredNullableProperties IPersistableModel<ModelWithRequiredNullableP
}

string IPersistableModel<ModelWithRequiredNullableProperties>.GetFormatFromOptions(ModelReaderWriterOptions options) => "J";

/// <param name="modelWithRequiredNullableProperties"> The <see cref="ModelWithRequiredNullableProperties"/> to serialize into <see cref="BinaryContent"/>. </param>
public static implicit operator BinaryContent(ModelWithRequiredNullableProperties modelWithRequiredNullableProperties)
{
throw new NotImplementedException("Not implemented");
}

/// <param name="result"> The <see cref="ClientResult"/> to deserialize the <see cref="ModelWithRequiredNullableProperties"/> from. </param>
public static explicit operator ModelWithRequiredNullableProperties(ClientResult result)
{
throw new NotImplementedException("Not implemented");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#nullable disable

using System;
using System.ClientModel;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Text.Json;
Expand Down Expand Up @@ -75,5 +76,17 @@ ProjectedModel IPersistableModel<ProjectedModel>.Create(BinaryData data, ModelRe
}

string IPersistableModel<ProjectedModel>.GetFormatFromOptions(ModelReaderWriterOptions options) => "J";

/// <param name="projectedModel"> The <see cref="ProjectedModel"/> to serialize into <see cref="BinaryContent"/>. </param>
public static implicit operator BinaryContent(ProjectedModel projectedModel)
{
throw new NotImplementedException("Not implemented");
}

/// <param name="result"> The <see cref="ClientResult"/> to deserialize the <see cref="ProjectedModel"/> from. </param>
public static explicit operator ProjectedModel(ClientResult result)
{
throw new NotImplementedException("Not implemented");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#nullable disable

using System;
using System.ClientModel;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Text.Json;
Expand Down Expand Up @@ -68,5 +69,17 @@ ReturnsAnonymousModelResponse IPersistableModel<ReturnsAnonymousModelResponse>.C
}

string IPersistableModel<ReturnsAnonymousModelResponse>.GetFormatFromOptions(ModelReaderWriterOptions options) => "J";

/// <param name="returnsAnonymousModelResponse"> The <see cref="ReturnsAnonymousModelResponse"/> to serialize into <see cref="BinaryContent"/>. </param>
public static implicit operator BinaryContent(ReturnsAnonymousModelResponse returnsAnonymousModelResponse)
{
throw new NotImplementedException("Not implemented");
}

/// <param name="result"> The <see cref="ClientResult"/> to deserialize the <see cref="ReturnsAnonymousModelResponse"/> from. </param>
public static explicit operator ReturnsAnonymousModelResponse(ClientResult result)
{
throw new NotImplementedException("Not implemented");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#nullable disable

using System;
using System.ClientModel;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Text.Json;
Expand Down Expand Up @@ -286,5 +287,17 @@ RoundTripModel IPersistableModel<RoundTripModel>.Create(BinaryData data, ModelRe
}

string IPersistableModel<RoundTripModel>.GetFormatFromOptions(ModelReaderWriterOptions options) => "J";

/// <param name="roundTripModel"> The <see cref="RoundTripModel"/> to serialize into <see cref="BinaryContent"/>. </param>
public static implicit operator BinaryContent(RoundTripModel roundTripModel)
{
throw new NotImplementedException("Not implemented");
}

/// <param name="result"> The <see cref="ClientResult"/> to deserialize the <see cref="RoundTripModel"/> from. </param>
public static explicit operator RoundTripModel(ClientResult result)
{
throw new NotImplementedException("Not implemented");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#nullable disable

using System;
using System.ClientModel;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Text.Json;
Expand Down Expand Up @@ -146,5 +147,17 @@ Thing IPersistableModel<Thing>.Create(BinaryData data, ModelReaderWriterOptions
}

string IPersistableModel<Thing>.GetFormatFromOptions(ModelReaderWriterOptions options) => "J";

/// <param name="thing"> The <see cref="Thing"/> to serialize into <see cref="BinaryContent"/>. </param>
public static implicit operator BinaryContent(Thing thing)
{
throw new NotImplementedException("Not implemented");
}

/// <param name="result"> The <see cref="ClientResult"/> to deserialize the <see cref="Thing"/> from. </param>
public static explicit operator Thing(ClientResult result)
{
throw new NotImplementedException("Not implemented");
}
}
}
Loading

0 comments on commit 3a15bee

Please sign in to comment.