diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Primitives/ScmKnownParameters.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Primitives/ScmKnownParameters.cs index b9ee53e3b9..8c81414b0f 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Primitives/ScmKnownParameters.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Primitives/ScmKnownParameters.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.ClientModel; using System.ClientModel.Primitives; using System.Text.Json; using System.Xml; @@ -32,8 +31,8 @@ public static ParameterProvider ClientOptions(CSharpType clientOptionsType) => new("options", $"The options for configuring the client.", clientOptionsType.WithNullable(true), initializationValue: New.Instance(clientOptionsType.WithNullable(true))); public static readonly ParameterProvider KeyAuth = new("keyCredential", $"The token credential to copy", ClientModelPlugin.Instance.TypeFactory.KeyCredentialType); public static readonly ParameterProvider MatchConditionsParameter = new("matchConditions", $"The content to send as the request conditions of the request.", ClientModelPlugin.Instance.TypeFactory.MatchConditionsType, DefaultOf(ClientModelPlugin.Instance.TypeFactory.MatchConditionsType)); - public static readonly ParameterProvider RequestOptions = new("options", $"The request options, which can override default behaviors of the client pipeline on a per-call basis.", typeof(RequestOptions)); - public static readonly ParameterProvider BinaryContent = new("content", $"The content to send as the body of the request.", typeof(BinaryContent), location: ParameterLocation.Body) { Validation = ParameterValidationType.AssertNotNull }; + public static readonly ParameterProvider RequestOptions = new(ClientModelPlugin.Instance.TypeFactory.HttpRequestOptionsApi.ParameterName, $"The request options, which can override default behaviors of the client pipeline on a per-call basis.", ClientModelPlugin.Instance.TypeFactory.HttpRequestOptionsApi.HttpRequestOptionsType); + public static readonly ParameterProvider RequestContent = new("content", $"The content to send as the body of the request.", ClientModelPlugin.Instance.TypeFactory.RequestContentApi.RequestContentType, location: ParameterLocation.Body) { Validation = ParameterValidationType.AssertNotNull }; // Known header parameters public static readonly ParameterProvider RepeatabilityRequestId = new("repeatabilityRequestId", FormattableStringHelpers.Empty, typeof(Guid)) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/ClientPipelineApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/ClientPipelineApi.cs new file mode 100644 index 0000000000..b32cd0976c --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/ClientPipelineApi.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public abstract record ClientPipelineApi : ScopedApi, IClientPipelineApi + { + public abstract CSharpType ClientPipelineType { get; } + public abstract CSharpType ClientPipelineOptionsType { get; } + public abstract CSharpType PipelinePolicyType { get; } + + protected ClientPipelineApi(Type type, ValueExpression original) : base(type, original) + { + } + + public abstract HttpMessageApi CreateMessage(); + + public abstract ValueExpression CreateMessage(HttpRequestOptionsApi requestOptions, ValueExpression responseClassifier); + + public abstract InvokeMethodExpression Send(HttpMessageApi message); + + public abstract InvokeMethodExpression SendAsync(HttpMessageApi message); + + public abstract ValueExpression Create(ValueExpression options, ValueExpression perRetryPolicies); + + public abstract ValueExpression PerRetryPolicy(params ValueExpression[] arguments); + public abstract ClientPipelineApi FromExpression(ValueExpression expression); + public abstract ClientPipelineApi ToExpression(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/ClientResponseApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/ClientResponseApi.cs new file mode 100644 index 0000000000..d38f40fd24 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/ClientResponseApi.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public abstract record ClientResponseApi : ScopedApi, IClientResponseApi + { + protected ClientResponseApi(Type type, ValueExpression original) : base(type, original) + { + } + + public abstract HttpResponseApi GetRawResponse(); + + public abstract ValueExpression FromValue(ValueExpression valueExpression, HttpResponseApi response); + + public abstract ValueExpression FromValue(ValueExpression valueExpression, HttpResponseApi response); + + public abstract ValueExpression FromResponse(ValueExpression valueExpression); + + public abstract ValueExpression CreateAsync(HttpResponseApi response); + + public abstract ClientResponseApi FromExpression(ValueExpression original); + + public abstract ClientResponseApi ToExpression(); + + public abstract CSharpType ClientResponseType { get; } + + public abstract CSharpType ClientResponseOfTType { get; } + + public abstract CSharpType ClientResponseExceptionType { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpMessageApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpMessageApi.cs new file mode 100644 index 0000000000..a955d07367 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpMessageApi.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +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 +{ + public abstract record HttpMessageApi : ScopedApi, IHttpMessageApi + { + protected HttpMessageApi(Type type, ValueExpression original) : base(type, original) + { + } + + public abstract HttpRequestApi Request(); + + public abstract HttpResponseApi Response(); + + public abstract ValueExpression BufferResponse(); + + public abstract ValueExpression ResponseClassifier(); + + public abstract MethodBodyStatement Apply(ValueExpression options); + + public abstract MethodBodyStatement[] ExtractResponse(); + + public abstract HttpMessageApi FromExpression(ValueExpression original); + + public abstract HttpMessageApi ToExpression(); + + public abstract CSharpType HttpMessageType { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpRequestApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpRequestApi.cs new file mode 100644 index 0000000000..910355647a --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpRequestApi.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public abstract record HttpRequestApi : ScopedApi, IExpressionApi + { + protected HttpRequestApi(CSharpType type, ValueExpression original) : base(type, original) + { + } + + public abstract AssignmentExpression SetMethod(string httpMethod); + + public abstract AssignmentExpression SetUri(ValueExpression uri); + + public abstract InvokeMethodExpression SetHeaders(IReadOnlyList arguments); + + public abstract ValueExpression Content(); + public abstract HttpRequestApi FromExpression(ValueExpression original); + public abstract HttpRequestApi ToExpression(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpRequestOptionsApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpRequestOptionsApi.cs new file mode 100644 index 0000000000..eeb20c9c9c --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpRequestOptionsApi.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public abstract record HttpRequestOptionsApi : ScopedApi, IHttpRequestOptionsApi + { + public HttpRequestOptionsApi(CSharpType type, ValueExpression original) : base(type, original) + { + } + + public abstract ValueExpression ErrorOptions(); + + public abstract HttpRequestOptionsApi FromExpression(ValueExpression original); + + public abstract ValueExpression NoThrow(); + + public abstract HttpRequestOptionsApi ToExpression(); + + public abstract CSharpType HttpRequestOptionsType { get; } + public abstract string ParameterName { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpResponseApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpResponseApi.cs new file mode 100644 index 0000000000..57604f28e4 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/HttpResponseApi.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public abstract record HttpResponseApi : ScopedApi, IHttpResponseApi + { + protected HttpResponseApi(Type type, ValueExpression original) : base(type, original) + { + } + + public abstract ScopedApi ContentStream(); + + public abstract ScopedApi Content(); + + public abstract ScopedApi IsError(); + + public abstract CSharpType HttpResponseType { get; } + + public abstract HttpResponseApi FromExpression(ValueExpression original); + + public abstract HttpResponseApi ToExpression(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IClientPipelineApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IClientPipelineApi.cs new file mode 100644 index 0000000000..85f51aa1ee --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IClientPipelineApi.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.Primitives; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public interface IClientPipelineApi : IExpressionApi + { + CSharpType ClientPipelineType { get; } + CSharpType ClientPipelineOptionsType { get; } + CSharpType PipelinePolicyType { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IClientResponseApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IClientResponseApi.cs new file mode 100644 index 0000000000..ea4353a0bf --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IClientResponseApi.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.Primitives; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public interface IClientResponseApi : IExpressionApi + { + CSharpType ClientResponseExceptionType { get; } + + CSharpType ClientResponseType { get; } + + CSharpType ClientResponseOfTType { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IExpressionApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IExpressionApi.cs new file mode 100644 index 0000000000..08a1253fcb --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IExpressionApi.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public interface IExpressionApi where T : ScopedApi + { + T FromExpression(ValueExpression original); + + T ToExpression(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IHttpMessageApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IHttpMessageApi.cs new file mode 100644 index 0000000000..f317bb7c3b --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IHttpMessageApi.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.Primitives; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public interface IHttpMessageApi : IExpressionApi + { + CSharpType HttpMessageType { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IHttpRequestOptionsApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IHttpRequestOptionsApi.cs new file mode 100644 index 0000000000..098bd125b7 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IHttpRequestOptionsApi.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.Primitives; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public interface IHttpRequestOptionsApi : IExpressionApi + { + CSharpType HttpRequestOptionsType { get; } + + string ParameterName { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IHttpResponseApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IHttpResponseApi.cs new file mode 100644 index 0000000000..02c21a11aa --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IHttpResponseApi.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.Primitives; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public interface IHttpResponseApi : IExpressionApi + { + CSharpType HttpResponseType { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IRequestContentApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IRequestContentApi.cs new file mode 100644 index 0000000000..3b351c03a9 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IRequestContentApi.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.Primitives; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public interface IRequestContentApi : IExpressionApi + { + CSharpType RequestContentType { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IStatusCodeClassifierApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IStatusCodeClassifierApi.cs new file mode 100644 index 0000000000..56ab5a99aa --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/IStatusCodeClassifierApi.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.Primitives; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public interface IStatusCodeClassifierApi : IExpressionApi + { + CSharpType ResponseClassifierType { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/RequestContentApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/RequestContentApi.cs new file mode 100644 index 0000000000..be8170a9d8 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/RequestContentApi.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +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 +{ + public abstract record RequestContentApi : ScopedApi, IRequestContentApi + { + protected RequestContentApi(Type type, ValueExpression original) : base(type, original) + { + } + + public abstract CSharpType RequestContentType { get; } + + public abstract RequestContentApi FromExpression(ValueExpression original); + public abstract RequestContentApi ToExpression(); + public abstract MethodBodyStatement[] Create(ValueExpression argument); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/StatusCodeClassifierApi.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/StatusCodeClassifierApi.cs new file mode 100644 index 0000000000..1414b0f97f --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/StatusCodeClassifierApi.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + public abstract record StatusCodeClassifierApi : ScopedApi, IStatusCodeClassifierApi + { + public StatusCodeClassifierApi(Type type, ValueExpression original) : base(type, original) + { + } + + public abstract CSharpType ResponseClassifierType { get; } + + public abstract ValueExpression Create(int code); + public abstract StatusCodeClassifierApi FromExpression(ValueExpression original); + public abstract StatusCodeClassifierApi ToExpression(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/ValueExpressionExtensions.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/ValueExpressionExtensions.cs new file mode 100644 index 0000000000..044708c6b8 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Abstractions/ValueExpressionExtensions.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + internal static class ValueExpressionExtensions + { + public static T ToApi(this ValueExpression 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)}"); + } + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/BinaryContentProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/BinaryContentProvider.cs new file mode 100644 index 0000000000..6776722b2f --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/BinaryContentProvider.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.ClientModel; +using Microsoft.Generator.CSharp.ClientModel.Snippets; +using static Microsoft.Generator.CSharp.Snippets.Snippet; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Statements; +using Microsoft.Generator.CSharp.Primitives; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + internal record BinaryContentProvider : RequestContentApi + { + private static RequestContentApi? _instance; + internal static RequestContentApi Instance => _instance ??= new BinaryContentProvider(Empty); + + public BinaryContentProvider(ValueExpression original) : base(typeof(BinaryContent), original) + { + } + + public override CSharpType RequestContentType => typeof(BinaryContent); + + public override RequestContentApi FromExpression(ValueExpression original) + => new BinaryContentProvider(original); + + public override RequestContentApi ToExpression() => this; + + public override MethodBodyStatement[] Create(ValueExpression argument) + => [Return(Static(typeof(BinaryContent)).Invoke(nameof(BinaryContent.Create), [argument, ModelSerializationExtensionsSnippets.Wire]))]; + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Classifier2xxAnd4xxDefinition.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Classifier2xxAnd4xxDefinition.cs index a4671ccf3e..81d3330b88 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Classifier2xxAnd4xxDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Classifier2xxAnd4xxDefinition.cs @@ -31,14 +31,17 @@ protected override TypeSignatureModifiers GetDeclarationModifiers() protected override MethodProvider[] BuildMethods() { - return [BuildTryClassifyErrorMethod(), BuildTryClassifyRetryMethod()]; + // TODO: Is there a better way to implement the methods? + return ClientModelPlugin.Instance.TypeFactory.StatusCodeClassifierApi.ResponseClassifierType.FrameworkType == typeof(PipelineMessageClassifier) + ? [BuildTryClassifyErrorMethod(), BuildTryClassifyRetryMethod()] + : []; } protected override string GetNamespace() => DeclaringTypeProvider!.Type.Namespace; protected override CSharpType[] BuildImplements() { - return [typeof(PipelineMessageClassifier)]; + return [ClientModelPlugin.Instance.TypeFactory.StatusCodeClassifierApi.ResponseClassifierType]; } private MethodProvider BuildTryClassifyRetryMethod() diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientOptionsProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientOptionsProvider.cs index 7d20070968..95d7296ad9 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientOptionsProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientOptionsProvider.cs @@ -66,7 +66,7 @@ public ClientOptionsProvider(InputClient inputClient, ClientProvider clientProvi protected override CSharpType[] BuildImplements() { - return [typeof(ClientPipelineOptions)]; + return [ClientModelPlugin.Instance.TypeFactory.ClientPipelineApi.ClientPipelineOptionsType]; } protected override FieldProvider[] BuildFields() diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientPipelineExtensionsDefinition.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientPipelineExtensionsDefinition.cs index f2d77afa65..0ecac00ae2 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientPipelineExtensionsDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientPipelineExtensionsDefinition.cs @@ -2,8 +2,6 @@ // Licensed under the MIT License. using System; -using System.ClientModel; -using System.ClientModel.Primitives; using System.IO; using System.Threading.Tasks; using Microsoft.Generator.CSharp.ClientModel.Snippets; @@ -18,26 +16,21 @@ namespace Microsoft.Generator.CSharp.ClientModel.Providers { internal class ClientPipelineExtensionsDefinition : TypeProvider { - private const string _processMessageAsync = "ProcessMessageAsync"; - private const string _processMessage = "ProcessMessage"; - private const string _processHeadAsBoolMessageAsync = "ProcessHeadAsBoolMessageAsync"; - private const string _processHeadAsBoolMessage = "ProcessHeadAsBoolMessage"; - private ParameterProvider _pipelineParam; private ParameterProvider _messageParam; private ParameterProvider _requestOptionsParam; - private ScopedApi _pipeline; - private ScopedApi _message; - private ScopedApi _options; + private ClientPipelineApi _pipeline; + private HttpMessageApi _message; + private HttpRequestOptionsApi _options; public ClientPipelineExtensionsDefinition() { - _pipelineParam = new ParameterProvider("pipeline", FormattableStringHelpers.Empty, typeof(ClientPipeline)); - _messageParam = new ParameterProvider("message", FormattableStringHelpers.Empty, typeof(PipelineMessage)); - _requestOptionsParam = new ParameterProvider("options", FormattableStringHelpers.Empty, typeof(RequestOptions)); - _pipeline = _pipelineParam.As(); - _message = _messageParam.As(); - _options = _requestOptionsParam.As(); + _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(); + _message = _messageParam.AsExpression.ToApi(); + _options = _requestOptionsParam.AsExpression.ToApi(); } protected override TypeSignatureModifiers GetDeclarationModifiers() @@ -56,15 +49,16 @@ protected override MethodProvider[] BuildMethods() BuildProcessMessageAsync(), BuildProcessMessage(), ProcessHeadAsBoolMessageAsync(), - ProcessHeadAsBoolMessage() + ProcessHeadAsBoolMessage(), + BuildExtractResponseContent() ]; } private MethodProvider ProcessHeadAsBoolMessage() { MethodSignature signature = GetProcessHeadAsBoolMessageSignature(false); - var responseVariable = new VariableExpression(typeof(PipelineResponse), "response"); - var response = responseVariable.As(); + var responseVariable = new VariableExpression(ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType, "response"); + var response = responseVariable.ToApi(); return new MethodProvider(signature, new MethodBodyStatement[] { new DeclarationExpression(responseVariable, false).Assign(_pipeline.ProcessMessage(_message, _options, false)).Terminate(), @@ -75,8 +69,8 @@ private MethodProvider ProcessHeadAsBoolMessage() private MethodProvider ProcessHeadAsBoolMessageAsync() { MethodSignature signature = GetProcessHeadAsBoolMessageSignature(true); - var responseVariable = new VariableExpression(typeof(PipelineResponse), "response"); - var response = responseVariable.As(); + var responseVariable = new VariableExpression(ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType, "response"); + var response = responseVariable.ToApi(); return new MethodProvider(signature, new MethodBodyStatement[] { new DeclarationExpression(responseVariable, false).Assign(_pipeline.ProcessMessage(_message, _options, true)).Terminate(), @@ -84,25 +78,25 @@ private MethodProvider ProcessHeadAsBoolMessageAsync() }, this); } - private MethodBodyStatement GetProcessHeadAsBoolMessageBody(ScopedApi response) + private MethodBodyStatement GetProcessHeadAsBoolMessageBody(HttpResponseApi response) { return new MethodBodyStatement[] { - new SwitchStatement(new MemberExpression(response, "Status"), new SwitchCaseStatement[] - { + new SwitchStatement(new MemberExpression(response, "Status"), + [ new SwitchCaseStatement(ValueExpression.Empty.GreaterThanOrEqual(Literal(200)).AndExpr(ValueExpression.Empty.LessThan(Literal(300))), new MethodBodyStatement[] { - Return(ClientResultSnippets.FromValue(typeof(bool), True, response)) + Return(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ToExpression().FromValue(True, response)) }), new SwitchCaseStatement(ValueExpression.Empty.GreaterThanOrEqual(Literal(400)).AndExpr(ValueExpression.Empty.LessThan(Literal(500))), new MethodBodyStatement[] { - Return(ClientResultSnippets.FromValue(typeof(bool), False, response)) + Return(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ToExpression().FromValue(False, response)) }), new SwitchCaseStatement(Array.Empty(), new MethodBodyStatement[] { - Return(new NewInstanceExpression(ErrorResultSnippets.ErrorResultType.MakeGenericType([typeof(bool)]), [response, new NewInstanceExpression(typeof(ClientResultException), [response])])) + Return(new NewInstanceExpression(ErrorResultSnippets.ErrorResultType.MakeGenericType([typeof(bool)]), [response, new NewInstanceExpression(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseExceptionType, [response])])) }) - }), + ]), }; } @@ -113,11 +107,12 @@ private MethodSignature GetProcessHeadAsBoolMessageSignature(bool isAsync) { modifiers |= MethodSignatureModifiers.Async; } + var clientResultType = new CSharpType(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseOfTType.FrameworkType, typeof(bool)); return new MethodSignature( isAsync ? "ProcessHeadAsBoolMessageAsync" : "ProcessHeadAsBoolMessage", null, modifiers, - isAsync ? typeof(ValueTask>) : typeof(ClientResult), + isAsync ? new CSharpType(typeof(ValueTask<>), clientResultType) : clientResultType, null, [_pipelineParam, _messageParam, _requestOptionsParam]); } @@ -126,21 +121,29 @@ private MethodProvider BuildProcessMessage() { MethodSignature signature = GetProcessMessageSignature(false); - var clientErrorNoThrow = FrameworkEnumValue(ClientErrorBehaviors.NoThrow); + var clientErrorNoThrow = _options.NoThrow(); return new MethodProvider(signature, new MethodBodyStatement[] { - _pipeline.Invoke(nameof(ClientPipeline.Send), [_message]).Terminate(), + _pipeline.Send(_message).Terminate(), MethodBodyStatement.EmptyLine, new IfStatement(_message.Response().IsError().And(new BinaryOperatorExpression("&", _options.NullConditional().Property("ErrorOptions"), clientErrorNoThrow).NotEqual(clientErrorNoThrow))) { - Throw(New.Instance(typeof(ClientResultException), _message.Response())) + Throw(New.Instance(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseExceptionType, _message.Response())) }, MethodBodyStatement.EmptyLine, - Declare("response", typeof(PipelineResponse), new TernaryConditionalExpression(_message.BufferResponse(), _message.Response(), _message.ExtractResponse()), out var response), + Declare("response", ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType, new TernaryConditionalExpression(_message.BufferResponse(), _message.Response(), Static().Invoke(ExtractResponseContentMethodName, [_messageParam])), out var response), Return(response) }, this); } + private const string ExtractResponseContentMethodName = "ExtractResponseContent"; + private MethodProvider BuildExtractResponseContent() + { + var signature = new MethodSignature(ExtractResponseContentMethodName, null, MethodSignatureModifiers.Private | MethodSignatureModifiers.Static, ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType, null, [_messageParam]); + var body = _message.ExtractResponse(); + return new MethodProvider(signature, body, this); + } + private MethodSignature GetProcessMessageSignature(bool isAsync) { var modifiers = MethodSignatureModifiers.Public | MethodSignatureModifiers.Static | MethodSignatureModifiers.Extension; @@ -152,7 +155,7 @@ private MethodSignature GetProcessMessageSignature(bool isAsync) isAsync ? "ProcessMessageAsync" : "ProcessMessage", null, modifiers, - isAsync ? typeof(ValueTask) : typeof(PipelineResponse), + isAsync ? new CSharpType(typeof(ValueTask<>), ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType) : ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType, null, [_pipelineParam, _messageParam, _requestOptionsParam]); } @@ -161,17 +164,17 @@ private MethodProvider BuildProcessMessageAsync() { MethodSignature signature = GetProcessMessageSignature(true); - var clientErrorNoThrow = FrameworkEnumValue(ClientErrorBehaviors.NoThrow); + var clientErrorNoThrow = _options.NoThrow(); return new MethodProvider(signature, new MethodBodyStatement[] { - _pipeline.Invoke(nameof(ClientPipeline.SendAsync), [_message], true).Terminate(), + _pipeline.SendAsync(_message).Terminate(), MethodBodyStatement.EmptyLine, new IfStatement(_message.Response().IsError().And(new BinaryOperatorExpression("&", _options.NullConditional().Property("ErrorOptions"), clientErrorNoThrow).NotEqual(clientErrorNoThrow))) { - Throw(Static().Invoke(nameof(ClientResultException.CreateAsync), [_message.Response()], true)) + Throw(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ToExpression().CreateAsync(_message.Response())) }, MethodBodyStatement.EmptyLine, - Declare("response", typeof(PipelineResponse), new TernaryConditionalExpression(_message.BufferResponse(), _message.Response(), _message.ExtractResponse()), out var response), + Declare("response", ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType, new TernaryConditionalExpression(_message.BufferResponse(), _message.Response(), Static().Invoke(ExtractResponseContentMethodName, [_messageParam])), out var response), Return(response) }, this); } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientPipelineProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientPipelineProvider.cs new file mode 100644 index 0000000000..404fb05181 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientPipelineProvider.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.ClientModel.Primitives; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using static Microsoft.Generator.CSharp.Snippets.Snippet; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + internal record ClientPipelineProvider : ClientPipelineApi + { + private static ClientPipelineApi? _instance; + internal static ClientPipelineApi Instance => _instance ??= new ClientPipelineProvider(Empty); + + public ClientPipelineProvider(ValueExpression original) : base(typeof(ClientPipeline), original) + { + } + + public override CSharpType ClientPipelineType => typeof(ClientPipeline); + + public override CSharpType ClientPipelineOptionsType => typeof(ClientPipelineOptions); + + public override CSharpType PipelinePolicyType => typeof(PipelinePolicy); + + public override ValueExpression Create(ValueExpression options, ValueExpression perRetryPolicies) + => Static().Invoke(nameof(ClientPipeline.Create), [options, New.Array(ClientModelPlugin.Instance.TypeFactory.ClientPipelineApi.PipelinePolicyType), perRetryPolicies, New.Array(ClientModelPlugin.Instance.TypeFactory.ClientPipelineApi.PipelinePolicyType)]).As(); + + 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(); + + public override ClientPipelineApi FromExpression(ValueExpression expression) + => new ClientPipelineProvider(expression); + + public override ValueExpression PerRetryPolicy(params ValueExpression[] arguments) + => Static().Invoke(nameof(ApiKeyAuthenticationPolicy.CreateHeaderApiKeyPolicy), arguments).As(); + + public override InvokeMethodExpression Send(HttpMessageApi message) + => Original.Invoke(nameof(ClientPipeline.Send), [message]); + + public override InvokeMethodExpression SendAsync(HttpMessageApi message) + => Original.Invoke(nameof(ClientPipeline.SendAsync), [message], true); + + public override ClientPipelineApi ToExpression() => this; + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientProvider.cs index 58aea37cd5..edf6b09ee9 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientProvider.cs @@ -88,7 +88,7 @@ public ClientProvider(InputClient inputClient) PipelineProperty = new( description: $"The HTTP pipeline for sending and receiving REST requests and responses.", modifiers: MethodSignatureModifiers.Public, - type: typeof(ClientPipeline), + type: ClientModelPlugin.Instance.TypeFactory.ClientPipelineApi.ClientPipelineType, name: "Pipeline", body: new AutoPropertyBody(false), enclosingType: this); @@ -317,20 +317,17 @@ private MethodBodyStatement[] BuildPrimaryConstructorBody(IReadOnlyList().Invoke( - nameof(ApiKeyAuthenticationPolicy.CreateHeaderApiKeyPolicy), perRetryPolicyArgs).As(); - perRetryPolicies = New.Array(typeof(PipelinePolicy), isInline: true, perRetryPolicy); + perRetryPolicies = New.Array(ClientModelPlugin.Instance.TypeFactory.ClientPipelineApi.PipelinePolicyType, isInline: true, This.ToApi().PerRetryPolicy(perRetryPolicyArgs)); } - body.Add(PipelineProperty.Assign(ClientPipelineSnippets.Create( - ClientOptionsParameter, New.Array(typeof(PipelinePolicy)), perRetryPolicies, New.Array(typeof(PipelinePolicy)))).Terminate()); + body.Add(PipelineProperty.Assign(This.ToApi().Create(ClientOptionsParameter, perRetryPolicies)).Terminate()); var clientOptionsPropertyDict = ClientOptions.Properties.ToDictionary(p => p.Name.ToCleanName()); foreach (var f in Fields) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientResultProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientResultProvider.cs new file mode 100644 index 0000000000..7273ff9bed --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientResultProvider.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.ClientModel.Primitives; +using System.ClientModel; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Snippets; +using static Microsoft.Generator.CSharp.Snippets.Snippet; +using Microsoft.Generator.CSharp.Primitives; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + internal record ClientResultProvider : ClientResponseApi + { + public ClientResultProvider(ValueExpression clientResult) : base(typeof(ClientResult), clientResult) + { + } + + private static ClientResponseApi? _instance; + internal static ClientResponseApi Instance => _instance ??= new ClientResultProvider(Empty); + + public override CSharpType ClientResponseType => typeof(ClientResult); + + public override CSharpType ClientResponseOfTType => typeof(ClientResult<>); + + public override CSharpType ClientResponseExceptionType => typeof(ClientResultException); + + public override ValueExpression CreateAsync(HttpResponseApi response) + => Static(ClientResponseExceptionType).Invoke(nameof(CreateAsync), [response], true); + + public override ClientResponseApi FromExpression(ValueExpression original) + => new ClientResultProvider(original.As()); + + public override ClientResponseApi ToExpression() => this; + + public override ValueExpression FromResponse(ValueExpression valueExpression) + => Static(ClientResponseType).Invoke(nameof(FromResponse), [valueExpression]); + + public override ValueExpression FromValue(ValueExpression valueExpression, HttpResponseApi response) + => Static(ClientResponseType).Invoke(nameof(FromValue), [valueExpression, response]); + + public override ValueExpression FromValue(ValueExpression valueExpression, HttpResponseApi response) + => Static(ClientResponseType).Invoke(nameof(FromValue), [valueExpression, response], [typeof(ValueType)], false); + + public override HttpResponseApi GetRawResponse() + => new PipelineResponseProvider(GetRawResponseExpression()); + + private ScopedApi GetRawResponseExpression() + => Original.Invoke(nameof(ClientResponseApi.GetRawResponse)).As(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientUriBuilderDefinition.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientUriBuilderDefinition.cs index 0b66cf3894..25c9d70d54 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientUriBuilderDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ClientUriBuilderDefinition.cs @@ -91,17 +91,21 @@ protected override MethodProvider[] BuildMethods() { var methods = new List(); - methods.Add(BuildResetMethod()); + if (GetBaseType() is null) + { + methods.Add(BuildResetMethod()); + methods.AddRange(BuildAppendPathMethods()); + methods.AddRange(BuildAppendQueryMethods()); + methods.Add(BuildToUriMethod()); + } - methods.AddRange(BuildAppendPathMethods()); - methods.AddRange(BuildAppendQueryMethods()); methods.AddRange(BuildAppendQueryDelimitedMethods()); - methods.Add(BuildToUriMethod()); - return methods.ToArray(); } + protected override CSharpType? GetBaseType() => ClientModelPlugin.Instance.TypeFactory.ClientUriBuilderBaseType; + private const string _resetMethodName = "Reset"; private MethodProvider BuildResetMethod() { diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ErrorResultDefinition.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ErrorResultDefinition.cs index ca6162115e..76ca18ebe7 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ErrorResultDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ErrorResultDefinition.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System.ClientModel; -using System.ClientModel.Primitives; using System.Collections.Generic; using System.IO; using Microsoft.Generator.CSharp.Expressions; @@ -25,12 +24,14 @@ private class ErrorResultTemplate { } public ErrorResultDefinition() { - _responseField = new FieldProvider(FieldModifiers.Private | FieldModifiers.ReadOnly, typeof(PipelineResponse), "_response", this); - _exceptionField = new FieldProvider(FieldModifiers.Private | FieldModifiers.ReadOnly, typeof(ClientResultException), "_exception", this); + _responseField = new FieldProvider(FieldModifiers.Private | FieldModifiers.ReadOnly, ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType, "_response", this); + _exceptionField = new FieldProvider(FieldModifiers.Private | FieldModifiers.ReadOnly, ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseExceptionType, "_exception", this); _response = new VariableExpression(_responseField.Type, _responseField.Declaration); _exception = new VariableExpression(_exceptionField.Type, _exceptionField.Declaration); } + private bool IsClientResult => ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseOfTType.FrameworkType == typeof(ClientResult<>); + protected override TypeSignatureModifiers GetDeclarationModifiers() { return TypeSignatureModifiers.Internal; @@ -47,7 +48,7 @@ protected override CSharpType[] GetTypeArguments() protected override CSharpType[] BuildImplements() { - return [new CSharpType(typeof(ClientResult<>), _t)]; + return [new CSharpType(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseOfTType.FrameworkType, _t)]; } protected override FieldProvider[] BuildFields() @@ -62,9 +63,11 @@ protected override ConstructorProvider[] BuildConstructors() private ConstructorProvider BuildCtor() { - var response = new ParameterProvider("response", FormattableStringHelpers.Empty, typeof(PipelineResponse)); - var exception = new ParameterProvider("exception", FormattableStringHelpers.Empty, typeof(ClientResultException)); - var baseInitializer = new ConstructorInitializer(true, new List { Default, response }); + var response = new ParameterProvider("response", FormattableStringHelpers.Empty, ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType); + var exception = new ParameterProvider("exception", FormattableStringHelpers.Empty, ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseExceptionType); + var baseInitializer = IsClientResult + ? new ConstructorInitializer(true, new List { Default, response }) + : new ConstructorInitializer(true, new List()); var signature = new ConstructorSignature(Type, null, MethodSignatureModifiers.Public, [response, exception], Initializer: baseInitializer); return new ConstructorProvider(signature, new MethodBodyStatement[] { @@ -84,5 +87,26 @@ private PropertyProvider BuildValue() ThrowExpression(_exception)), this); } + + protected override MethodProvider[] BuildMethods() + { + return IsClientResult ? [] : [BuildGetRawResponse()]; + } + + private MethodProvider BuildGetRawResponse() + { + var signature = new MethodSignature( + "GetRawResponse", + FormattableStringHelpers.Empty, + MethodSignatureModifiers.Public | MethodSignatureModifiers.Override, + ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType, + null, + [] + ); + return new MethodProvider(signature, new MethodBodyStatement[] + { + Return(_response) + }, this); + } } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ModelSerializationExtensionsDefinition.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ModelSerializationExtensionsDefinition.cs index d33bc5d272..bd588effd2 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ModelSerializationExtensionsDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ModelSerializationExtensionsDefinition.cs @@ -20,7 +20,7 @@ namespace Microsoft.Generator.CSharp.ClientModel.Providers { - internal sealed class ModelSerializationExtensionsDefinition : TypeProvider + public sealed class ModelSerializationExtensionsDefinition : TypeProvider { private const string WriteStringValueMethodName = "WriteStringValue"; private const string WriteBase64StringValueMethodName = "WriteBase64StringValue"; diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/MrwSerializationTypeDefinition.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/MrwSerializationTypeDefinition.cs index 15c5376c86..1c0410ed2f 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/MrwSerializationTypeDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/MrwSerializationTypeDefinition.cs @@ -170,15 +170,15 @@ protected override MethodProvider[] BuildMethods() private MethodProvider BuildExplicitFromClientResult() { - var result = new ParameterProvider("result", $"The {typeof(ClientResult):C} to deserialize the {Type:C} from.", typeof(ClientResult)); + var result = new ParameterProvider("result", $"The {ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseType:C} to deserialize the {Type:C} from.", ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseType); var modifiers = MethodSignatureModifiers.Public | MethodSignatureModifiers.Static | MethodSignatureModifiers.Explicit | MethodSignatureModifiers.Operator; // using PipelineResponse response = result.GetRawResponse(); - var responseDeclaration = UsingDeclare("response", typeof(PipelineResponse), result.Invoke(nameof(ClientResult.GetRawResponse)), out var response); + var responseDeclaration = UsingDeclare("response", ClientModelPlugin.Instance.TypeFactory.HttpResponseApi.HttpResponseType, result.AsExpression.ToApi().GetRawResponse(), out var response); // using JsonDocument document = JsonDocument.Parse(response.Content); var document = UsingDeclare( "document", typeof(JsonDocument), - JsonDocumentSnippets.Parse(response.Property(nameof(PipelineResponse.Content)).As()), + JsonDocumentSnippets.Parse(response.Property(nameof(HttpResponseApi.Content)).As()), out var docVariable); // return DeserializeT(doc.RootElement, ModelSerializationExtensions.WireOptions); var deserialize = Return(_model.Type.Deserialize(docVariable.As().RootElement(), ModelSerializationExtensionsSnippets.Wire)); @@ -196,13 +196,12 @@ private MethodProvider BuildExplicitFromClientResult() private MethodProvider BuildImplicitToBinaryContent() { - var model = new ParameterProvider(Type.Name.ToVariableName(), $"The {Type:C} to serialize into {typeof(BinaryContent):C}", Type); + var model = new ParameterProvider(Type.Name.ToVariableName(), $"The {Type:C} to serialize into {ClientModelPlugin.Instance.TypeFactory.RequestContentApi.RequestContentType:C}", Type); var modifiers = MethodSignatureModifiers.Public | MethodSignatureModifiers.Static | MethodSignatureModifiers.Implicit | MethodSignatureModifiers.Operator; // return BinaryContent.Create(model, ModelSerializationExtensions.WireOptions); - var binaryContentMethod = Static(typeof(BinaryContent)).Invoke(nameof(BinaryContent.Create), [model, ModelSerializationExtensionsSnippets.Wire]); return new MethodProvider( - new MethodSignature(nameof(BinaryContent), null, modifiers, null, null, [model]), - Return(binaryContentMethod), + new MethodSignature(ClientModelPlugin.Instance.TypeFactory.RequestContentApi.RequestContentType.FrameworkType.Name, null, modifiers, null, null, [model]), + ClientModelPlugin.Instance.TypeFactory.RequestContentApi.ToExpression().Create(model), this); } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineMessageClassifierProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineMessageClassifierProvider.cs new file mode 100644 index 0000000000..2e1f4ea702 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineMessageClassifierProvider.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.Expressions; +using static Microsoft.Generator.CSharp.Snippets.Snippet; +using System.ClientModel.Primitives; +using Microsoft.Generator.CSharp.Primitives; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + internal record PipelineMessageClassifierProvider : StatusCodeClassifierApi + { + private static StatusCodeClassifierApi? _instance; + internal static StatusCodeClassifierApi Instance => _instance ??= new PipelineMessageClassifierProvider(Empty); + + public PipelineMessageClassifierProvider(ValueExpression original) : base(typeof(PipelineMessageClassifier), original) + { + } + + public override CSharpType ResponseClassifierType => typeof(PipelineMessageClassifier); + + public override ValueExpression Create(int code) + => Static().Invoke(nameof(PipelineMessageClassifier.Create), [New.Array(typeof(ushort), true, true, [Literal(code)])]); + + public override StatusCodeClassifierApi FromExpression(ValueExpression original) + => new PipelineMessageClassifierProvider(original); + + public override StatusCodeClassifierApi ToExpression() => this; + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineMessageProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineMessageProvider.cs new file mode 100644 index 0000000000..25467d7cf1 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineMessageProvider.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +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 +{ + internal record PipelineMessageProvider : HttpMessageApi + { + public PipelineMessageProvider(ValueExpression original) : base(typeof(PipelineMessage), original) + { + } + + private static HttpMessageApi? _instance; + internal static HttpMessageApi Instance => _instance ??= new PipelineMessageProvider(Empty); + + public override HttpRequestApi Request() + => new PipelineRequestProvider(Original.Property(nameof(PipelineMessage.Request))); + + public override ValueExpression BufferResponse() + => Original.Property(nameof(PipelineMessage.BufferResponse)); + + public override HttpResponseApi Response() + => new PipelineResponseProvider(Original.Property(nameof(PipelineMessage.Response))); + + public override ValueExpression ResponseClassifier() + => Original.Property(nameof(PipelineMessage.ResponseClassifier)); + + public override MethodBodyStatement Apply(ValueExpression options) + => Original.Invoke(nameof(PipelineMessage.Apply), options).Terminate(); + + public override MethodBodyStatement[] ExtractResponse() + => [Return(Original.Invoke(nameof(PipelineMessage.ExtractResponse)))]; + + public override HttpMessageApi FromExpression(ValueExpression original) + => new PipelineMessageProvider(original); + + public override HttpMessageApi ToExpression() + => this; + + public override CSharpType HttpMessageType => typeof(PipelineMessage); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineRequestProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineRequestProvider.cs new file mode 100644 index 0000000000..202d196655 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineRequestProvider.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.ClientModel.Primitives; +using System.Collections.Generic; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.ClientModel.Snippets; +using static Microsoft.Generator.CSharp.Snippets.Snippet; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + internal record PipelineRequestProvider : HttpRequestApi + { + public PipelineRequestProvider(ValueExpression original) : base(typeof(PipelineRequest), original) + { + } + + private static HttpRequestApi? _instance; + internal static HttpRequestApi Instance => _instance ??= new PipelineRequestProvider(Empty); + + public override ValueExpression Content() + => Original.Property(nameof(PipelineRequest.Content)); + + public override HttpRequestApi FromExpression(ValueExpression original) + => new PipelineRequestProvider(original); + + public override InvokeMethodExpression SetHeaders(IReadOnlyList arguments) + => Original.Property(nameof(PipelineRequest.Headers)).Invoke(nameof(PipelineRequestHeaders.Set), arguments); + + public override AssignmentExpression SetMethod(string httpMethod) + => Original.Property(nameof(PipelineRequest.Method)).Assign(Literal(httpMethod)); + + public override AssignmentExpression SetUri(ValueExpression value) + => Original.Property("Uri").Assign(value.As().ToUri()); + + public override HttpRequestApi ToExpression() => this; + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineResponseProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineResponseProvider.cs new file mode 100644 index 0000000000..b2a9c0a5ee --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/PipelineResponseProvider.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.ClientModel.Primitives; +using System.IO; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + internal record PipelineResponseProvider : HttpResponseApi + { + public PipelineResponseProvider(ValueExpression pipelineResponse) : base(typeof(PipelineResponse), pipelineResponse) + { + } + + private static HttpResponseApi? _instance; + internal static HttpResponseApi Instance => _instance ??= new PipelineResponseProvider(Empty); + + public override ScopedApi ContentStream() + => Original.Property(nameof(PipelineResponse.ContentStream)).As(); + + public override ScopedApi Content() + => Original.Property(nameof(PipelineResponse.Content)).As(); + + public override ScopedApi IsError() + => Original.Property(nameof(PipelineResponse.IsError)).As(); + + public override HttpResponseApi FromExpression(ValueExpression original) + => new PipelineResponseProvider(original); + + public override HttpResponseApi ToExpression() + => this; + + public override CSharpType HttpResponseType => typeof(PipelineResponse); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/RequestOptionsProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/RequestOptionsProvider.cs new file mode 100644 index 0000000000..d1d9bd1209 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/RequestOptionsProvider.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.ClientModel.Primitives; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using static Microsoft.Generator.CSharp.Snippets.Snippet; + +namespace Microsoft.Generator.CSharp.ClientModel.Providers +{ + internal record RequestOptionsProvider : HttpRequestOptionsApi + { + public RequestOptionsProvider(ValueExpression original) : base(typeof(RequestOptions), original) + { + } + + private static HttpRequestOptionsApi? _instance; + internal static HttpRequestOptionsApi Instance => _instance ??= new RequestOptionsProvider(Empty); + + public override CSharpType HttpRequestOptionsType => typeof(RequestOptions); + + public override string ParameterName => "options"; + + public override ValueExpression ErrorOptions() + => Original.NullConditional().Property(nameof(RequestOptions.ErrorOptions)); + + public override HttpRequestOptionsApi FromExpression(ValueExpression original) + => new RequestOptionsProvider(original); + + public override ValueExpression NoThrow() + => FrameworkEnumValue(ClientErrorBehaviors.NoThrow); + + public override HttpRequestOptionsApi ToExpression() => this; + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/RestClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/RestClientProvider.cs index cf342b0f74..4bfaa2676e 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/RestClientProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/RestClientProvider.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Net.Http; +using System.Xml.Linq; using Microsoft.Generator.CSharp.ClientModel.Primitives; using Microsoft.Generator.CSharp.ClientModel.Snippets; using Microsoft.Generator.CSharp.Expressions; @@ -48,8 +49,8 @@ public RestClientProvider(InputClient inputClient, ClientProvider clientProvider { _inputClient = inputClient; ClientProvider = clientProvider; - _pipelineMessageClassifier200 = new FieldProvider(FieldModifiers.Private | FieldModifiers.Static, typeof(PipelineMessageClassifier), "_pipelineMessageClassifier200", this); - _pipelineMessageClassifier204 = new FieldProvider(FieldModifiers.Private | FieldModifiers.Static, typeof(PipelineMessageClassifier), "_pipelineMessageClassifier204", this); + _pipelineMessageClassifier200 = new FieldProvider(FieldModifiers.Private | FieldModifiers.Static, ClientModelPlugin.Instance.TypeFactory.StatusCodeClassifierApi.ResponseClassifierType, "_pipelineMessageClassifier200", this); + _pipelineMessageClassifier204 = new FieldProvider(FieldModifiers.Private | FieldModifiers.Static, ClientModelPlugin.Instance.TypeFactory.StatusCodeClassifierApi.ResponseClassifierType, "_pipelineMessageClassifier204", this); _classifier2xxAnd4xxDefinition = new Classifier2xxAnd4xxDefinition(this); _pipelineMessageClassifier2xxAnd4xx = new FieldProvider(FieldModifiers.Private | FieldModifiers.Static, _classifier2xxAnd4xxDefinition.Type, "_pipelineMessageClassifier2xxAnd4xx", this); _classifier200Property = GetResponseClassifierProperty(_pipelineMessageClassifier200, 200); @@ -82,13 +83,10 @@ private PropertyProvider GetResponseClassifierProperty(FieldProvider pipelineMes return new PropertyProvider( null, MethodSignatureModifiers.Private | MethodSignatureModifiers.Static, - typeof(PipelineMessageClassifier), + ClientModelPlugin.Instance.TypeFactory.StatusCodeClassifierApi.ResponseClassifierType, pipelineMessageClassifier.Name.Substring(1).ToCleanName(), new ExpressionPropertyBody( - pipelineMessageClassifier.Assign( - Static().Invoke( - nameof(PipelineMessageClassifier.Create), - [New.Array(typeof(ushort), true, true, [Literal(code)])]))), + pipelineMessageClassifier.Assign(This.ToApi().Create(code))), this); } @@ -129,14 +127,14 @@ private bool IsCreateRequest(MethodProvider method) private MethodProvider BuildCreateRequestMethod(InputOperation operation) { - var pipelineField = ClientProvider.PipelineProperty.As(); + var pipelineField = ((MemberExpression)ClientProvider.PipelineProperty).ToApi(); var options = ScmKnownParameters.RequestOptions; var signature = new MethodSignature( $"Create{operation.Name.ToCleanName()}Request", null, MethodSignatureModifiers.Internal, - typeof(PipelineMessage), + ClientModelPlugin.Instance.TypeFactory.HttpMessageApi.HttpMessageType, null, [.. GetMethodParameters(operation, true), options]); var paramMap = new Dictionary(signature.Parameters.ToDictionary(p => p.Name)); @@ -163,27 +161,27 @@ private MethodProvider BuildCreateRequestMethod(InputOperation operation) signature, new MethodBodyStatements( [ - Declare("message", pipelineField.CreateMessage(), out ScopedApi message), + Declare("message", pipelineField.CreateMessage().ToApi(), out HttpMessageApi message), message.ResponseClassifier().Assign(classifier).Terminate(), - Declare("request", message.Request(), out ScopedApi request), - request.SetMethod(operation.HttpMethod), + Declare("request", message.Request().ToApi(), out HttpRequestApi request), // ScopedApi + request.SetMethod(operation.HttpMethod).Terminate(), Declare("uri", New.Instance(), out ScopedApi uri), uri.Reset(ClientProvider.EndpointField).Terminate(), .. AppendPathParameters(uri, operation, paramMap), .. AppendQueryParameters(uri, operation, paramMap), - request.Uri().Assign(uri.ToUri()).Terminate(), + request.SetUri(uri).Terminate(), .. AppendHeaderParameters(request, operation, paramMap), .. GetSetContent(request, signature.Parameters), - message.Apply(options).Terminate(), + message.Apply(options), Return(message) ]), this); } - private IReadOnlyList GetSetContent(ScopedApi request, IReadOnlyList parameters) + private IReadOnlyList GetSetContent(HttpRequestApi request, IReadOnlyList parameters) { - var contentParam = parameters.FirstOrDefault(p => ReferenceEquals(p, ScmKnownParameters.BinaryContent)); - return contentParam is null ? [] : [request.SetContent(contentParam)]; + var contentParam = parameters.FirstOrDefault(p => ReferenceEquals(p, ScmKnownParameters.RequestContent)); + return contentParam is null ? [] : [request.Content().Assign(contentParam).Terminate()]; } private PropertyProvider GetClassifier(InputOperation operation) @@ -206,7 +204,7 @@ private PropertyProvider GetClassifier(InputOperation operation) throw new InvalidOperationException("Multiple status codes not supported"); } - private IEnumerable AppendHeaderParameters(ScopedApi request, InputOperation operation, Dictionary paramMap) + private IEnumerable AppendHeaderParameters(HttpRequestApi request, InputOperation operation, Dictionary paramMap) { List statements = new(operation.Parameters.Count); @@ -228,7 +226,7 @@ private IEnumerable AppendHeaderParameters(ScopedApi()); + statement = request.SetHeaders([Literal(inputParameter.NameInRequest), toStringExpression.As()]).Terminate(); } statements.Add(statement); } @@ -433,7 +431,7 @@ internal static List GetMethodParameters(InputOperation opera { if (inputParam.Location == RequestLocation.Body) { - parameter = ScmKnownParameters.BinaryContent; + parameter = ScmKnownParameters.RequestContent; } else { diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ScmMethodProviderCollection.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ScmMethodProviderCollection.cs index 85d8ba54fd..caf44e5be1 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ScmMethodProviderCollection.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ScmMethodProviderCollection.cs @@ -2,8 +2,6 @@ // Licensed under the MIT License. using System; -using System.ClientModel; -using System.ClientModel.Primitives; using System.Collections.Generic; using System.Linq; using System.Text.Json; @@ -98,20 +96,15 @@ .. GetStackVariablesForProtocolParamConversion(ConvenienceMethodParameters, out methodBody = [ .. GetStackVariablesForProtocolParamConversion(ConvenienceMethodParameters, out var paramDeclarations), - Declare("result", This.Invoke(protocolMethod.Signature, [.. GetParamConversions(ConvenienceMethodParameters, paramDeclarations), Null], isAsync).As(), out ScopedApi result), + Declare("result", This.Invoke(protocolMethod.Signature, [.. GetParamConversions(ConvenienceMethodParameters, paramDeclarations), Null], isAsync).ToApi(), out ClientResponseApi result), .. GetStackVariablesForReturnValueConversion(result, responseBodyType, isAsync, out var resultDeclarations), - Return(Static().Invoke( - nameof(ClientResult.FromValue), - [ - GetResultConversion(result, responseBodyType, resultDeclarations), - result.Invoke("GetRawResponse") - ])), + Return(result.FromValue(GetResultConversion(result, result.GetRawResponse(), responseBodyType, resultDeclarations), result.GetRawResponse())), ]; } var convenienceMethod = new ScmMethodProvider(methodSignature, methodBody, EnclosingType); // XmlDocs will be null if the method isn't public - convenienceMethod.XmlDocs?.Exceptions.Add(new(typeof(ClientResultException), "Service returned a non-success status code.", [])); + convenienceMethod.XmlDocs?.Exceptions.Add(new(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseExceptionType.FrameworkType, "Service returned a non-success status code.", [])); return convenienceMethod; } @@ -146,7 +139,7 @@ private IEnumerable GetStackVariablesForProtocolParamConver var bdExpression = Operation.RequestMediaTypes?.Contains("application/json") == true ? BinaryDataSnippets.FromObjectAsJson(parameter) : BinaryDataSnippets.FromString(parameter); - statements.Add(UsingDeclare("content", BinaryContentSnippets.Create(bdExpression), out var content)); + statements.Add(UsingDeclare("content", RequestContentApiSnippets.Create(bdExpression), out var content)); declarations["content"] = content; } else if (parameter.Type.IsFrameworkType && !parameter.Type.Equals(typeof(BinaryData))) @@ -202,7 +195,7 @@ private List GetSpreadConversion(TypeProvider spreadSource) return expressions; } - private IEnumerable GetStackVariablesForReturnValueConversion(ScopedApi result, CSharpType responseBodyType, bool isAsync, out Dictionary declarations) + private IEnumerable GetStackVariablesForReturnValueConversion(ClientResponseApi result, CSharpType responseBodyType, bool isAsync, out Dictionary declarations) { if (responseBodyType.IsList) { @@ -280,11 +273,11 @@ private MethodBodyStatement AddElement(ValueExpression? dictKey, ValueExpression return scopedApi.Add(element); } - private ValueExpression GetResultConversion(ScopedApi result, CSharpType responseBodyType, Dictionary declarations) + private ValueExpression GetResultConversion(ClientResponseApi result, HttpResponseApi response, CSharpType responseBodyType, Dictionary declarations) { if (responseBodyType.Equals(typeof(BinaryData))) { - return result.GetRawResponse().Content(); + return response.Content(); } if (responseBodyType.IsList) { @@ -294,7 +287,7 @@ private ValueExpression GetResultConversion(ScopedApi result, CSha } else { - return result.GetRawResponse().Content().ToObjectFromJson(responseBodyType); + return response.Content().ToObjectFromJson(responseBodyType); } } if (responseBodyType.IsDictionary) @@ -305,20 +298,20 @@ private ValueExpression GetResultConversion(ScopedApi result, CSha } else { - return result.GetRawResponse().Content().ToObjectFromJson(responseBodyType); + return response.Content().ToObjectFromJson(responseBodyType); } } if (responseBodyType.Equals(typeof(string)) && Operation.RequestMediaTypes?.Contains("text/plain") == true) { - return result.GetRawResponse().Content().InvokeToString(); + return response.Content().InvokeToString(); } if (responseBodyType.IsFrameworkType) { - return result.GetRawResponse().Content().ToObjectFromJson(responseBodyType); + return response.Content().ToObjectFromJson(responseBodyType); } if (responseBodyType.IsEnum) { - return responseBodyType.ToEnum(result.GetRawResponse().Content().ToObjectFromJson(responseBodyType.UnderlyingEnumType)); + return responseBodyType.ToEnum(response.Content().ToObjectFromJson(responseBodyType.UnderlyingEnumType)); } return result.CastTo(responseBodyType); } @@ -345,11 +338,11 @@ private IReadOnlyList GetParamConversions(IReadOnlyList().Invoke(nameof(ClientResult.FromResponse), client.PipelineProperty.Invoke(processMessageName, [message, ScmKnownParameters.RequestOptions], isAsync, true))), + UsingDeclare("message", ClientModelPlugin.Instance.TypeFactory.HttpMessageApi.HttpMessageType, This.Invoke(createRequestMethod.Signature, [.. MethodParameters]), out var message), + Return(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ToExpression().FromResponse(client.PipelineProperty.Invoke(processMessageName, [message, ScmKnownParameters.RequestOptions], isAsync, true))), ]; var protocolMethod = @@ -412,7 +405,7 @@ private MethodProvider BuildProtocolMethod(MethodProvider createRequestMethod, b if (protocolMethod.XmlDocs != null) { protocolMethod.XmlDocs?.Exceptions.Add( - new(typeof(ClientResultException), "Service returned a non-success status code.", [])); + new(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseExceptionType.FrameworkType, "Service returned a non-success status code.", [])); List listItems = [ new XmlDocStatement("item", [], new XmlDocStatement("description", [$"This protocol method allows explicit creation of the request and processing of the response for advanced scenarios."])) @@ -426,7 +419,7 @@ private MethodProvider BuildProtocolMethod(MethodProvider createRequestMethod, b private static CSharpType? GetResponseType(IReadOnlyList responses, bool isConvenience, bool isAsync, out CSharpType? responseBodyType) { responseBodyType = null; - var returnType = isConvenience ? GetConvenienceReturnType(responses, out responseBodyType) : typeof(ClientResult); + var returnType = isConvenience ? GetConvenienceReturnType(responses, out responseBodyType) : ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseType; return isAsync ? new CSharpType(typeof(Task<>), returnType) : returnType; } @@ -435,8 +428,8 @@ private static CSharpType GetConvenienceReturnType(IReadOnlyList !r.IsErrorResponse); responseBodyType = response?.BodyType is null ? null : ClientModelPlugin.Instance.TypeFactory.CreateCSharpType(response.BodyType); return response is null || responseBodyType is null - ? typeof(ClientResult) - : new CSharpType(typeof(ClientResult<>), responseBodyType); + ? ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseType + : new CSharpType(ClientModelPlugin.Instance.TypeFactory.ClientResponseApi.ClientResponseOfTType.FrameworkType, responseBodyType); } } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Utf8JsonBinaryContentDefinition.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Utf8JsonBinaryContentDefinition.cs index 5ec4c5dfd4..3bc915e001 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Utf8JsonBinaryContentDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/Utf8JsonBinaryContentDefinition.cs @@ -16,7 +16,7 @@ namespace Microsoft.Generator.CSharp.ClientModel.Providers { - internal class Utf8JsonBinaryContentDefinition : TypeProvider + public class Utf8JsonBinaryContentDefinition : TypeProvider { private const string _jsonWriterName = "JsonWriter"; @@ -35,7 +35,7 @@ public Utf8JsonBinaryContentDefinition() enclosingType: this); _contentField = new FieldProvider( modifiers: FieldModifiers.Private | FieldModifiers.ReadOnly, - type: typeof(BinaryContent), + type: ClientModelPlugin.Instance.TypeFactory.RequestContentApi.RequestContentType, name: "_content", enclosingType: this); _writerProperty = new PropertyProvider( @@ -54,7 +54,7 @@ protected override TypeSignatureModifiers GetDeclarationModifiers() protected override string BuildRelativeFilePath() => Path.Combine("src", "Generated", "Internal", $"{Name}.cs"); - protected override CSharpType? GetBaseType() => typeof(BinaryContent); + protected override CSharpType? GetBaseType() => ClientModelPlugin.Instance.TypeFactory.RequestContentApi.RequestContentType; protected override FieldProvider[] BuildFields() { @@ -77,7 +77,7 @@ protected override ConstructorProvider[] BuildConstructors() var body = new MethodBodyStatement[] { _streamField.Assign(New.Instance(typeof(MemoryStream))).Terminate(), - _contentField.Assign(BinaryContentSnippets.Create(_streamField)).Terminate(), + _contentField.Assign(RequestContentApiSnippets.Create(_streamField)).Terminate(), _writerProperty.Assign(New.Instance(typeof(Utf8JsonWriter), _streamField)).Terminate() }; return [new ConstructorProvider(signature, body, this)]; diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/ScmTypeFactory.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/ScmTypeFactory.cs index 4a568d89bb..a6183ce503 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/ScmTypeFactory.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/ScmTypeFactory.cs @@ -23,6 +23,24 @@ public class ScmTypeFactory : TypeFactory public virtual CSharpType TokenCredentialType => throw new NotImplementedException("Token credential is not supported in Scm libraries yet"); + public virtual CSharpType? ClientUriBuilderBaseType => null; + + public virtual IClientResponseApi ClientResponseApi => ClientResultProvider.Instance; + + public virtual IHttpResponseApi HttpResponseApi => PipelineResponseProvider.Instance; + + public virtual IHttpMessageApi HttpMessageApi => PipelineMessageProvider.Instance; + + public virtual IHttpRequestOptionsApi HttpRequestOptionsApi => RequestOptionsProvider.Instance; + + public virtual IExpressionApi HttpRequestApi => PipelineRequestProvider.Instance; + + public virtual IClientPipelineApi ClientPipelineApi => ClientPipelineProvider.Instance; + + public virtual IStatusCodeClassifierApi StatusCodeClassifierApi => PipelineMessageClassifierProvider.Instance; + + public virtual IRequestContentApi RequestContentApi => BinaryContentProvider.Instance; + /// /// Returns the serialization type providers for the given input type. /// diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/BinaryContentSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/BinaryContentSnippets.cs deleted file mode 100644 index 4ccf5d43f9..0000000000 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/BinaryContentSnippets.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; -using Microsoft.Generator.CSharp.Expressions; -using Microsoft.Generator.CSharp.Primitives; -using Microsoft.Generator.CSharp.Snippets; -using static Microsoft.Generator.CSharp.Snippets.Snippet; - -namespace Microsoft.Generator.CSharp.ClientModel.Snippets -{ - internal static class BinaryContentSnippets - { - public static ScopedApi Create(ValueExpression serializable) - => Static().Invoke(nameof(BinaryContent.Create), serializable).As(); - - public static ScopedApi Create(ValueExpression serializable, ScopedApi options, CSharpType? typeArgument = null) - => Static().Invoke(nameof(BinaryContent.Create), [serializable, options], typeArgument != null ? [typeArgument] : null, false).As(); - } -} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientPipelineApiSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientPipelineApiSnippets.cs new file mode 100644 index 0000000000..8d513a9e89 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientPipelineApiSnippets.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.ClientModel.Providers; +using Microsoft.Generator.CSharp.Expressions; +using static Microsoft.Generator.CSharp.Snippets.Snippet; + +namespace Microsoft.Generator.CSharp.ClientModel.Snippets +{ + internal static class ClientPipelineApiSnippets + { + private const string _processMessageAsync = "ProcessMessageAsync"; + private const string _processMessage = "ProcessMessage"; + + public static HttpResponseApi ProcessMessage(this ClientPipelineApi pipeline, ValueExpression message, HttpRequestOptionsApi? requestOptions, bool isAsync) + => pipeline.Invoke(isAsync ? _processMessageAsync : _processMessage, [message, requestOptions ?? Null], isAsync).ToApi(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientPipelineSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientPipelineSnippets.cs deleted file mode 100644 index 3da7d8515a..0000000000 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientPipelineSnippets.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; -using Microsoft.Generator.CSharp.Expressions; -using Microsoft.Generator.CSharp.Snippets; -using static Microsoft.Generator.CSharp.Snippets.Snippet; - -namespace Microsoft.Generator.CSharp.ClientModel.Snippets -{ - internal static class ClientPipelineSnippets - { - private const string _processMessageAsync = "ProcessMessageAsync"; - private const string _processMessage = "ProcessMessage"; - private const string _processHeadAsBoolMessageAsync = "ProcessHeadAsBoolMessageAsync"; - private const string _processHeadAsBoolMessage = "ProcessHeadAsBoolMessage"; - - public static ScopedApi CreateMessage(this ScopedApi pipeline) - => pipeline.Invoke(nameof(ClientPipeline.CreateMessage)).As(); - - public static ScopedApi CreateMessage(this ScopedApi pipeline, ScopedApi requestOptions, ValueExpression responseClassifier) - => pipeline.Invoke(nameof(ClientPipeline.CreateMessage), requestOptions, responseClassifier).As(); - - public static ScopedApi ProcessMessage(this ScopedApi pipeline, ValueExpression message, ScopedApi? requestOptions, bool isAsync) - => pipeline.Invoke(isAsync ? _processMessageAsync : _processMessage, [message, requestOptions ?? Null], isAsync).As(); - - public static ScopedApi ProcessHeadAsBoolMessage(this ScopedApi pipeline, ValueExpression message, ScopedApi? requestContext, bool isAsync) - => pipeline.Invoke(isAsync ? _processHeadAsBoolMessageAsync : _processHeadAsBoolMessage, [message, requestContext ?? Null], isAsync).As(); - - public static ScopedApi Create() => Static().Invoke(nameof(ClientPipeline.Create)).As(); - public static ScopedApi Create(params ValueExpression[] arguments) - => Static().Invoke(nameof(ClientPipeline.Create), arguments).As(); - } -} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientResponseApiSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientResponseApiSnippets.cs new file mode 100644 index 0000000000..a28de1cdc3 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientResponseApiSnippets.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Generator.CSharp.ClientModel.Providers; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Snippets +{ + internal static class ClientResponseApiSnippets + { + public static ScopedApi GetRawResponse(this ClientResponseApi clientResponse) + => clientResponse.Invoke(nameof(ClientResponseApi.GetRawResponse)).As(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientResultSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientResultSnippets.cs deleted file mode 100644 index 31c1ee3cd4..0000000000 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/ClientResultSnippets.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; -using Microsoft.Generator.CSharp.Expressions; -using Microsoft.Generator.CSharp.Primitives; -using Microsoft.Generator.CSharp.Snippets; -using static Microsoft.Generator.CSharp.Snippets.Snippet; - -namespace Microsoft.Generator.CSharp.ClientModel.Snippets -{ - internal static class ClientResultSnippets - { - public static ValueExpression Value(this ScopedApi clientResult) => clientResult.Property(nameof(ClientResult.Value)); - - public static ScopedApi FromResponse(ScopedApi response) - => Static().Invoke(nameof(ClientResult.FromResponse), response).As(); - - public static ScopedApi FromValue(ValueExpression value, ScopedApi response) - => Static().Invoke(nameof(ClientResult.FromValue), value, response).As(); - - public static ScopedApi FromValue(CSharpType explicitValueType, ValueExpression value, ScopedApi response) - => Static().Invoke(nameof(ClientResult.FromValue), [value, response], [explicitValueType], false).As(); - - public static ScopedApi FromValue(this ScopedApi clientResult, ValueExpression value) - => Static().Invoke(nameof(ClientResult.FromValue), [value, clientResult]).As(); - - public static ScopedApi FromValue(this ScopedApi clientResult, CSharpType explicitValueType, ValueExpression value) - => Static().Invoke(nameof(ClientResult.FromValue), [value, clientResult], [explicitValueType], false).As(); - - public static ScopedApi GetRawResponse(this ScopedApi clientResult) - => clientResult.Invoke(nameof(ClientResult.GetRawResponse)).As(); - } -} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/PipelineRequestSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/HttpRequestApiSnippets.cs similarity index 73% rename from packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/PipelineRequestSnippets.cs rename to packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/HttpRequestApiSnippets.cs index 3bbbc8b084..f8d36d34aa 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/PipelineRequestSnippets.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/HttpRequestApiSnippets.cs @@ -3,6 +3,7 @@ using System; using System.ClientModel.Primitives; +using Microsoft.Generator.CSharp.ClientModel.Providers; using Microsoft.Generator.CSharp.Expressions; using Microsoft.Generator.CSharp.Snippets; using Microsoft.Generator.CSharp.Statements; @@ -10,14 +11,8 @@ namespace Microsoft.Generator.CSharp.ClientModel.Snippets { - internal static class PipelineRequestSnippets + internal static class HttpRequestApiSnippets { - public static ScopedApi Uri(this ScopedApi pipelineRequest) - => pipelineRequest.Property(nameof(PipelineRequest.Uri)).As(); - - public static MethodBodyStatement SetMethod(this ScopedApi pipelineRequest, string method) - => pipelineRequest.Property("Method").Assign(Literal(method)).Terminate(); - public static MethodBodyStatement SetHeaderValue(this ScopedApi pipelineRequest, string name, ValueExpression value) => pipelineRequest.Property(nameof(PipelineRequest.Headers)).Invoke(nameof(PipelineRequestHeaders.Set), Literal(name), value).Terminate(); @@ -27,7 +22,7 @@ public static MethodBodyStatement AddHeaderValue(this ScopedApi public static MethodBodyStatement SetContent(this ScopedApi pipelineRequest, ValueExpression content) => pipelineRequest.Property(nameof(PipelineRequest.Content)).Assign(content).Terminate(); - public static MethodBodyStatement SetHeaderDelimited(this ScopedApi pipelineRequest, string name, ValueExpression value, ValueExpression delimiter, ValueExpression? format = null) + public static MethodBodyStatement SetHeaderDelimited(this HttpRequestApi pipelineRequest, string name, ValueExpression value, ValueExpression delimiter, ValueExpression? format = null) { ValueExpression[] parameters = format != null ? [Literal(name), value, delimiter, format] : [Literal(name), value, delimiter]; return pipelineRequest.Property(nameof(PipelineRequest.Headers)).Invoke("SetDelimited", parameters).Terminate(); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/HttpResponseApiSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/HttpResponseApiSnippets.cs new file mode 100644 index 0000000000..8f9cc43086 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/HttpResponseApiSnippets.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using Microsoft.Generator.CSharp.ClientModel.Providers; +using Microsoft.Generator.CSharp.Snippets; + +namespace Microsoft.Generator.CSharp.ClientModel.Snippets +{ + internal static class HttpResponseApiSnippets + { + public static ScopedApi Content(this HttpResponseApi pipelineMessage) + => pipelineMessage.Property(nameof(HttpResponseApi.Content)).As(); + + public static ScopedApi ContentStream(this HttpResponseApi pipelineMessage) + => pipelineMessage.Property(nameof(HttpResponseApi.ContentStream)).As(); + + public static ScopedApi IsError(this HttpResponseApi pipelineMessage) + => pipelineMessage.Property(nameof(HttpResponseApi.IsError)).As(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/PipelineMessageSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/PipelineMessageSnippets.cs index 14db3f9ccb..ae401703b0 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/PipelineMessageSnippets.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/PipelineMessageSnippets.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System.ClientModel.Primitives; +using Microsoft.Generator.CSharp.ClientModel.Providers; using Microsoft.Generator.CSharp.Expressions; using Microsoft.Generator.CSharp.Snippets; @@ -12,14 +13,14 @@ internal static class PipelineMessageSnippets public static ScopedApi Request(this ScopedApi pipelineMessage) => pipelineMessage.Property(nameof(PipelineMessage.Request)).As(); - public static ScopedApi Response(this ScopedApi pipelineMessage) - => pipelineMessage.Property(nameof(PipelineMessage.Response)).As(); + public static HttpResponseApi Response(this ScopedApi pipelineMessage) + => pipelineMessage.Property(nameof(PipelineMessage.Response)).ToApi(); public static ScopedApi BufferResponse(this ScopedApi pipelineMessage) => pipelineMessage.Property(nameof(PipelineMessage.BufferResponse)).As(); - public static ScopedApi ExtractResponse(this ScopedApi pipelineMessage) - => pipelineMessage.Invoke(nameof(PipelineMessage.ExtractResponse), []).As(); + public static HttpResponseApi ExtractResponse(this ScopedApi pipelineMessage) + => pipelineMessage.Invoke(nameof(PipelineMessage.ExtractResponse), []).ToApi(); public static ScopedApi ResponseClassifier(this ScopedApi pipelineMessage) => pipelineMessage.Property(nameof(PipelineMessage.ResponseClassifier)).As(); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/PipelineResponseSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/PipelineResponseSnippets.cs deleted file mode 100644 index 9550656092..0000000000 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/PipelineResponseSnippets.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.ClientModel.Primitives; -using System.IO; -using Microsoft.Generator.CSharp.Snippets; - -namespace Microsoft.Generator.CSharp.ClientModel.Snippets -{ - internal static class PipelineResponseSnippets - { - public static ScopedApi Content(this ScopedApi pipelineMessage) - => pipelineMessage.Property(nameof(PipelineResponse.Content)).As(); - - public static ScopedApi ContentStream(this ScopedApi pipelineMessage) - => pipelineMessage.Property(nameof(PipelineResponse.ContentStream)).As(); - - public static ScopedApi IsError(this ScopedApi pipelineMessage) - => pipelineMessage.Property(nameof(PipelineResponse.IsError)).As(); - } -} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/RequestContentApiSnippets.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/RequestContentApiSnippets.cs new file mode 100644 index 0000000000..1b39484864 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Snippets/RequestContentApiSnippets.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.ClientModel; +using System.ClientModel.Primitives; +using Microsoft.Generator.CSharp.ClientModel.Providers; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Snippets; +using static Microsoft.Generator.CSharp.Snippets.Snippet; + +namespace Microsoft.Generator.CSharp.ClientModel.Snippets +{ + internal static class RequestContentApiSnippets + { + public static RequestContentApi Create(ValueExpression serializable) + => Static(ClientModelPlugin.Instance.TypeFactory.RequestContentApi.RequestContentType).Invoke(nameof(BinaryContent.Create), serializable).ToApi(); + + public static RequestContentApi Create(ValueExpression serializable, ScopedApi options, CSharpType? typeArgument = null) + => Static(ClientModelPlugin.Instance.TypeFactory.RequestContentApi.RequestContentType).Invoke(nameof(BinaryContent.Create), [serializable, options], typeArgument != null ? [typeArgument] : null, false).ToApi(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Microsoft.Generator.CSharp.ClientModel.Tests.csproj b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Microsoft.Generator.CSharp.ClientModel.Tests.csproj index d7462b3bbf..7f5afb0ad7 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Microsoft.Generator.CSharp.ClientModel.Tests.csproj +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Microsoft.Generator.CSharp.ClientModel.Tests.csproj @@ -1,4 +1,4 @@ - + diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/ClientPipelineApiTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/ClientPipelineApiTests.cs new file mode 100644 index 0000000000..2ea76f42bd --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/ClientPipelineApiTests.cs @@ -0,0 +1,83 @@ +using System.Linq; +using Microsoft.Generator.CSharp.ClientModel.Providers; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Tests.Common; +using NUnit.Framework; + +namespace Microsoft.Generator.CSharp.ClientModel.Tests.Providers.Abstractions +{ + internal class ClientPipelineApiTests + { + [Test] + public void ValidatePipelinePropertyTypeIsOverridden() + { + ClientProvider clientProvider = CreateTestClient(); + var pipelineProperty = clientProvider.Properties.FirstOrDefault(x => x.Name == "Pipeline"); + + Assert.NotNull(pipelineProperty); + Assert.IsTrue(pipelineProperty!.Type.Equals(typeof(string))); + } + + [Test] + public void ValidateBodyOfRestClientOperationIsOverridden() + { + var clientProvider = CreateTestClient(); + var restClient = clientProvider.RestClient; + var method = restClient.Methods.FirstOrDefault(m => m.Signature.Name == "CreateFooRequest"); + + Assert.NotNull(method); + Assert.NotNull(method!.BodyStatements); + var test = method?.BodyStatements?.ToDisplayString(); + Assert.AreEqual(Helpers.GetExpectedFromFile(), method!.BodyStatements!.ToDisplayString()); + } + + private static ClientProvider CreateTestClient() + { + var client = InputFactory.Client("TestClient", [InputFactory.Operation("foo")]); + MockHelpers.LoadMockPlugin(clientPipelineApi: TestClientPipelineApi.Instance); + var clientProvider = ClientModelPlugin.Instance.TypeFactory.CreateClient(client); + return clientProvider; + } + + private record TestClientPipelineApi : ClientPipelineApi + { + private static ClientPipelineApi? _instance; + internal static ClientPipelineApi Instance => _instance ??= new TestClientPipelineApi(Empty); + + public TestClientPipelineApi(ValueExpression original) : base(typeof(string), original) + { + } + + public override CSharpType ClientPipelineType => typeof(string); + + public override CSharpType ClientPipelineOptionsType => typeof(string); + + public override CSharpType PipelinePolicyType => typeof(string); + + public override ValueExpression Create(ValueExpression options, ValueExpression perRetryPolicies) + => Original.Invoke("GetFakeCreate", [options, perRetryPolicies]); + + public override HttpMessageApi CreateMessage() + => Original.Invoke("GetFakeCreateMessage").ToApi(); + + public override ValueExpression CreateMessage(HttpRequestOptionsApi requestOptions, ValueExpression responseClassifier) + => Original.Invoke("GetFakeCreateMessage", [requestOptions, responseClassifier]); + + public override ClientPipelineApi FromExpression(ValueExpression expression) + => new TestClientPipelineApi(expression); + + public override ValueExpression PerRetryPolicy(params ValueExpression[] arguments) + => Original.Invoke("GetFakePerRetryPolicy", arguments); + + public override InvokeMethodExpression Send(HttpMessageApi message) + => Original.Invoke("GetFakeSend", message); + + public override InvokeMethodExpression SendAsync(HttpMessageApi message) + => Original.Invoke("GetFakeSendAsync", message); + + public override ClientPipelineApi ToExpression() => this; + } + } + +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/ClientResponseApiTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/ClientResponseApiTests.cs new file mode 100644 index 0000000000..85727a302c --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/ClientResponseApiTests.cs @@ -0,0 +1,87 @@ +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Generator.CSharp.ClientModel.Providers; +using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Tests.Common; +using NUnit.Framework; +using static Microsoft.Generator.CSharp.Snippets.Snippet; + +namespace Microsoft.Generator.CSharp.ClientModel.Tests.Providers.Abstractions +{ + internal class ClientResponseApiTests + { + [Test] + public void ValidateReturnTypeIsOverridden() + { + ClientProvider clientProvider = CreateMockClientProvider(); + + // take the sync version of the method from the client provider + var method = clientProvider.Methods.FirstOrDefault(x => !x.Signature.Name.EndsWith("Async")); + Assert.NotNull(method); + Assert.NotNull(method!.Signature.ReturnType); + Assert.IsTrue(method!.Signature.ReturnType!.Equals(typeof(string))); + } + + [Test] + public void ValidateBodyOfClientOperationIsOverridden() + { + var clientProvider = CreateMockClientProvider(); + + // take the sync version of the method from the client provider + var method = clientProvider.Methods.FirstOrDefault(x => x.Signature.Parameters.Any(p => p.Type.Equals(typeof(RequestOptions))) && !x.Signature.Name.EndsWith("Async")); + Assert.NotNull(method); + Assert.NotNull(method!.BodyStatements); + Assert.AreEqual(Helpers.GetExpectedFromFile(), method.BodyStatements!.ToDisplayString()); + } + + private static ClientProvider CreateMockClientProvider() + { + var client = InputFactory.Client("TestClient", [InputFactory.Operation("foo")]); + MockHelpers.LoadMockPlugin(clientResponseApi: TestClientResponseApi.Instance); + var clientProvider = ClientModelPlugin.Instance.TypeFactory.CreateClient(client); + return clientProvider; + } + + private record TestClientResponseApi : ClientResponseApi + { + private static TestClientResponseApi? _instance; + internal static TestClientResponseApi Instance => _instance ??= new(); + private TestClientResponseApi() : base(typeof(string), Empty) + { + } + + public TestClientResponseApi(ValueExpression origin) : base(typeof(string), origin) + { + } + + public override HttpResponseApi GetRawResponse() + => Original.Invoke("GetFakeRawResponse").ToApi(); + + public override ValueExpression FromValue(ValueExpression valueExpression, HttpResponseApi response) + => Original.Invoke("GetFakeFromValue"); + + public override ValueExpression FromValue(ValueExpression valueExpression, HttpResponseApi response) + => Original.Invoke("GetFakeFromValueGeneric", [valueExpression, response]); + + public override ValueExpression FromResponse(ValueExpression valueExpression) + => Static().Invoke("GetFakeFromResponse", [valueExpression]); + + public override ValueExpression CreateAsync(HttpResponseApi response) + => Original.Invoke("GetFakeFromCreateAsync", [response]); + + public override ClientResponseApi FromExpression(ValueExpression original) + => new TestClientResponseApi(original); + + public override ClientResponseApi ToExpression() => this; + + public override CSharpType ClientResponseType => typeof(string); + + public override CSharpType ClientResponseOfTType => typeof(List<>); + + public override CSharpType ClientResponseExceptionType => typeof(NotImplementedException); + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/HttpMessageApiTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/HttpMessageApiTests.cs new file mode 100644 index 0000000000..f9ceabb91e --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/HttpMessageApiTests.cs @@ -0,0 +1,82 @@ +using System.ClientModel.Primitives; +using System.Linq; +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; +using static Microsoft.Generator.CSharp.Snippets.Snippet; + +namespace Microsoft.Generator.CSharp.ClientModel.Tests.Providers.Abstractions +{ + internal class HttpMessageApiTests + { + [Test] + public void ValidateReturnTypeOfCreateRequestIsOverridden() + { + var client = CreateTestClient(); + var restClient = client.RestClient; + var method = restClient.Methods.FirstOrDefault(m => m.Signature.Name == "CreateFooRequest"); + + Assert.IsNotNull(method); + Assert.IsNotNull(method!.Signature.ReturnType); + Assert.IsTrue(method!.Signature.ReturnType!.Equals(typeof(string))); + } + + [Test] + public void ValidateBodyOfProcessMessageIsOverridden() + { + var client = CreateTestClient(); + var method = client.Methods.FirstOrDefault(x => x.Signature.Parameters.Any(p => p.Type.Equals(typeof(RequestOptions))) && !x.Signature.Name.EndsWith("Async")); + + Assert.IsNotNull(method); + Assert.IsNotNull(method!.BodyStatements); + var test = method!.BodyStatements!.ToDisplayString(); + Assert.AreEqual(Helpers.GetExpectedFromFile(), method!.BodyStatements!.ToDisplayString()); + } + + private static ClientProvider CreateTestClient() + { + var client = InputFactory.Client("TestClient", [InputFactory.Operation("foo")]); + MockHelpers.LoadMockPlugin(httpMessageApi: TestHttpMessageApi.Instance); + var clientProvider = ClientModelPlugin.Instance.TypeFactory.CreateClient(client); + return clientProvider; + } + + private record TestHttpMessageApi : HttpMessageApi + { + private static HttpMessageApi? _instance; + internal static HttpMessageApi Instance => _instance ??= new TestHttpMessageApi(Empty); + + public TestHttpMessageApi(ValueExpression original) : base(typeof(string), original) + { + } + + public override CSharpType HttpMessageType => typeof(string); + + public override MethodBodyStatement Apply(ValueExpression options) + => Original.Invoke("GetFakeApply", [options]).Terminate(); + + public override ValueExpression BufferResponse() + => Original.Invoke("GetFakeBufferResponse"); + + public override MethodBodyStatement[] ExtractResponse() + => [Return(Original.Invoke("GetFakeExtractResponse"))]; + + public override HttpMessageApi FromExpression(ValueExpression original) + => new TestHttpMessageApi(original); + + public override HttpRequestApi Request() + => Original.Invoke("GetFakeRequest").ToApi(); + + public override HttpResponseApi Response() + => Original.Invoke("GetFakeResponse").ToApi(); + + public override ValueExpression ResponseClassifier() + => Original.Invoke("GetFakeResponseClassifier"); + + public override HttpMessageApi ToExpression() => this; + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/TestData/ClientPipelineApiTests/ValidateBodyOfRestClientOperationIsOverridden.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/TestData/ClientPipelineApiTests/ValidateBodyOfRestClientOperationIsOverridden.cs new file mode 100644 index 0000000000..82fcb29c6c --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/TestData/ClientPipelineApiTests/ValidateBodyOfRestClientOperationIsOverridden.cs @@ -0,0 +1,9 @@ +global::System.ClientModel.Primitives.PipelineMessage message = Pipeline.GetFakeCreateMessage(); +message.ResponseClassifier = PipelineMessageClassifier200; +global::System.ClientModel.Primitives.PipelineRequest request = message.Request; +request.Method = "GET"; +global::Sample.ClientUriBuilder uri = new global::Sample.ClientUriBuilder(); +uri.Reset(_endpoint); +request.Uri = uri.ToUri(); +message.Apply(options); +return message; diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/TestData/ClientResponseApiTests/ValidateBodyOfClientOperationIsOverridden.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/TestData/ClientResponseApiTests/ValidateBodyOfClientOperationIsOverridden.cs new file mode 100644 index 0000000000..7dbb1151ef --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/TestData/ClientResponseApiTests/ValidateBodyOfClientOperationIsOverridden.cs @@ -0,0 +1,2 @@ +using global::System.ClientModel.Primitives.PipelineMessage message = this.CreateFooRequest(options); +return string.GetFakeFromResponse(Pipeline.ProcessMessage(message, options)); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/TestData/HttpMessageApiTests/ValidateBodyOfProcessMessageIsOverridden.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/TestData/HttpMessageApiTests/ValidateBodyOfProcessMessageIsOverridden.cs new file mode 100644 index 0000000000..448258a711 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Abstractions/TestData/HttpMessageApiTests/ValidateBodyOfProcessMessageIsOverridden.cs @@ -0,0 +1,2 @@ +using string message = this.CreateFooRequest(options); +return global::System.ClientModel.ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Definitions/ClientPipelineExtensionsDefCustomizationTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Definitions/ClientPipelineExtensionsDefCustomizationTests.cs index fe39159437..0ed26feadd 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Definitions/ClientPipelineExtensionsDefCustomizationTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/Definitions/ClientPipelineExtensionsDefCustomizationTests.cs @@ -22,7 +22,7 @@ public async Task CanReplaceMethod() // The definitions should not have the custom method var definitionMethods = definition!.Methods; - Assert.AreEqual(3, definitionMethods.Count); + Assert.AreEqual(4, definitionMethods.Count); Assert.IsFalse(definitionMethods.Any(m => m.Signature.Name == "ProcessMessageAsync")); // The custom code view should contain the method diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/ScmKnownParametersTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/ScmKnownParametersTests.cs index b45b8f18ae..43a0318352 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/ScmKnownParametersTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/ScmKnownParametersTests.cs @@ -21,7 +21,7 @@ public void Setup() [Test] public void BinaryDataParameterHasValidation() { - var parameter = ScmKnownParameters.BinaryContent; + var parameter = ScmKnownParameters.RequestContent; Assert.AreEqual(ParameterValidationType.AssertNotNull, parameter.Validation); } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Snippets/TypedSnippetsTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Snippets/TypedSnippetsTests.cs index 0b7dcd624d..0ad32bf817 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Snippets/TypedSnippetsTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Snippets/TypedSnippetsTests.cs @@ -5,6 +5,7 @@ using System.ClientModel.Primitives; using System.Text.Json; using Microsoft.Generator.CSharp.ClientModel.Primitives; +using Microsoft.Generator.CSharp.ClientModel.Providers; using Microsoft.Generator.CSharp.ClientModel.Snippets; using Microsoft.Generator.CSharp.Expressions; using Microsoft.Generator.CSharp.Providers; @@ -50,14 +51,14 @@ public void JsonSerializerSnippet_Deserialize() public void BinaryContentSnippet_InvokeStatic(bool withOptions) { var arg = Snippet.This; - ScopedApi result; + RequestContentApi result; ScopedApi? options = null; if (withOptions) { options = new MemberExpression(null, "w").As(); } - result = options != null ? BinaryContentSnippets.Create(arg, options) : BinaryContentSnippets.Create(arg); + result = options != null ? RequestContentApiSnippets.Create(arg, options) : RequestContentApiSnippets.Create(arg); Assert.IsNotNull(result); var untyped = result.Original as InvokeMethodExpression; diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs index f6f6999335..dc80039dca 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs @@ -56,7 +56,10 @@ public static Mock LoadMockPlugin( Func>? clients = null, Func? createInputLibrary = null, Func? createClientCore = null, - string? configuration = null) + string? configuration = null, + ClientResponseApi? clientResponseApi = null, + ClientPipelineApi? clientPipelineApi = null, + HttpMessageApi? httpMessageApi = null) { IReadOnlyList inputNsApiVersions = apiVersions?.Invoke() ?? []; IReadOnlyList inputNsEnums = inputEnums?.Invoke() ?? []; @@ -115,6 +118,20 @@ public static Mock LoadMockPlugin( var mockPluginInstance = new Mock(mockGeneratorContext.Object) { CallBase = true }; mockPluginInstance.SetupGet(p => p.TypeFactory).Returns(mockTypeFactory.Object); mockPluginInstance.Setup(p => p.InputLibrary).Returns(mockInputLibrary.Object); + if (clientResponseApi is not null) + { + mockTypeFactory.Setup(p => p.ClientResponseApi).Returns(clientResponseApi); + } + + if (clientPipelineApi is not null) + { + mockTypeFactory.Setup(p => p.ClientPipelineApi).Returns(clientPipelineApi); + } + + if (httpMessageApi is not null) + { + mockTypeFactory.Setup(p => p.HttpMessageApi).Returns(httpMessageApi); + } if (createInputLibrary is not null) { diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.DeclarationStatements.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.DeclarationStatements.cs index ce95d7cd7a..a1a30edc23 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.DeclarationStatements.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.DeclarationStatements.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; using Microsoft.Generator.CSharp.Expressions; using Microsoft.Generator.CSharp.Primitives; using Microsoft.Generator.CSharp.Statements; @@ -52,6 +53,26 @@ public static MethodBodyStatement UsingDeclare(string name, ScopedApi valu return UsingDeclare(variableExpression, value); } + public static MethodBodyStatement UsingDeclare(string name, T value, out T variable) where T : ScopedApi + { + var declaration = new CodeWriterDeclaration(name); + var variableExpression = new VariableExpression(TypeReferenceExpression.GetTypeFromDefinition(value.Type)!, declaration); + + // TODO: need to constraint that subtype should have the corresponding constructor + variable = (T)Activator.CreateInstance(value.GetType(), variableExpression)!; + return UsingDeclare(variableExpression, value); + } + + public static MethodBodyStatement Declare(string name, T value, out T variable) where T : ScopedApi + { + var declaration = new CodeWriterDeclaration(name); + var variableExpression = new VariableExpression(TypeReferenceExpression.GetTypeFromDefinition(value.Type)!, declaration); + + // TODO: need to constraint that subtype should have the corresponding constructor + variable = (T)Activator.CreateInstance(value.GetType(), variableExpression)!; + return new DeclarationExpression(variableExpression).Assign(value).Terminate(); + } + public static MethodBodyStatement Declare(string name, ScopedApi value, out ScopedApi variable) { var declaration = new CodeWriterDeclaration(name); diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Internal/ClientPipelineExtensions.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Internal/ClientPipelineExtensions.cs index 6ed3aa6f71..a11fb09675 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Internal/ClientPipelineExtensions.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Internal/ClientPipelineExtensions.cs @@ -19,7 +19,7 @@ public static async ValueTask ProcessMessageAsync(this ClientP throw await ClientResultException.CreateAsync(message.Response).ConfigureAwait(false); } - PipelineResponse response = message.BufferResponse ? message.Response : message.ExtractResponse(); + PipelineResponse response = message.BufferResponse ? message.Response : ExtractResponseContent(message); return response; } @@ -32,7 +32,7 @@ public static PipelineResponse ProcessMessage(this ClientPipeline pipeline, Pipe throw new ClientResultException(message.Response); } - PipelineResponse response = message.BufferResponse ? message.Response : message.ExtractResponse(); + PipelineResponse response = message.BufferResponse ? message.Response : ExtractResponseContent(message); return response; } @@ -63,5 +63,10 @@ public static ClientResult ProcessHeadAsBoolMessage(this ClientPipeline pi return new ErrorResult(response, new ClientResultException(response)); } } + + private static PipelineResponse ExtractResponseContent(PipelineMessage message) + { + return message.ExtractResponse(); + } } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Internal/ClientUriBuilder.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Internal/ClientUriBuilder.cs index e04c544e42..4aaeb80a20 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Internal/ClientUriBuilder.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Internal/ClientUriBuilder.cs @@ -103,18 +103,6 @@ public void AppendQuery(string name, string value, bool escape) public void AppendQuery(string name, Guid value, bool escape = true) => AppendQuery(name, TypeFormatters.ConvertToString(value), escape); - public void AppendQueryDelimited(string name, IEnumerable value, string delimiter, bool escape = true) - { - IEnumerable stringValues = value.Select(v => TypeFormatters.ConvertToString(v)); - AppendQuery(name, string.Join(delimiter, stringValues), escape); - } - - public void AppendQueryDelimited(string name, IEnumerable value, string delimiter, string format, bool escape = true) - { - IEnumerable stringValues = value.Select(v => TypeFormatters.ConvertToString(v, format)); - AppendQuery(name, string.Join(delimiter, stringValues), escape); - } - public Uri ToUri() { if (_pathBuilder != null) @@ -127,5 +115,17 @@ public Uri ToUri() } return UriBuilder.Uri; } + + public void AppendQueryDelimited(string name, IEnumerable value, string delimiter, bool escape = true) + { + IEnumerable stringValues = value.Select(v => TypeFormatters.ConvertToString(v)); + AppendQuery(name, string.Join(delimiter, stringValues), escape); + } + + public void AppendQueryDelimited(string name, IEnumerable value, string delimiter, string format, bool escape = true) + { + IEnumerable stringValues = value.Select(v => TypeFormatters.ConvertToString(v, format)); + AppendQuery(name, string.Join(delimiter, stringValues), escape); + } } }