Skip to content

Commit 47f3c9b

Browse files
authored
Implement Response abstraction for Azure (Azure#46530)
1 parent 8236e8d commit 47f3c9b

38 files changed

+1083
-631
lines changed

eng/Packages.Data.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@
243243
</ItemGroup>
244244

245245
<ItemGroup Condition="'$(IsGeneratorLibrary)' == 'true'">
246-
<PackageReference Update="Microsoft.Generator.CSharp.ClientModel" Version="1.0.0-alpha.20241010.1" />
246+
<PackageReference Update="Microsoft.Generator.CSharp.ClientModel" Version="1.0.0-alpha.20241022.3" />
247247
</ItemGroup>
248248

249249
<!--

eng/packages/http-client-csharp/generator/Azure.Generator.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ VisualStudioVersion = 17.10.35201.131
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Generator", "Azure.Generator\src\Azure.Generator.csproj", "{8DDB0B72-B3F6-4F87-8B04-163EB4880FC8}"
77
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicTypeSpec", "TestProjects\Local\Basic-TypeSpec\src\BasicTypeSpec.csproj", "{F8386530-1166-438C-99DC-AE855036A37C}"
9+
EndProject
810
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Generator.Tests", "Azure.Generator\test\Azure.Generator.Tests.csproj", "{A05E6873-DD18-44B2-88A8-DEE3AA103EC4}"
911
EndProject
1012
Global
@@ -17,6 +19,10 @@ Global
1719
{8DDB0B72-B3F6-4F87-8B04-163EB4880FC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
1820
{8DDB0B72-B3F6-4F87-8B04-163EB4880FC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
1921
{8DDB0B72-B3F6-4F87-8B04-163EB4880FC8}.Release|Any CPU.Build.0 = Release|Any CPU
22+
{F8386530-1166-438C-99DC-AE855036A37C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{F8386530-1166-438C-99DC-AE855036A37C}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{F8386530-1166-438C-99DC-AE855036A37C}.Release|Any CPU.ActiveCfg = Release|Any CPU
25+
{F8386530-1166-438C-99DC-AE855036A37C}.Release|Any CPU.Build.0 = Release|Any CPU
2026
{A05E6873-DD18-44B2-88A8-DEE3AA103EC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
2127
{A05E6873-DD18-44B2-88A8-DEE3AA103EC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
2228
{A05E6873-DD18-44B2-88A8-DEE3AA103EC4}.Release|Any CPU.ActiveCfg = Release|Any CPU

eng/packages/http-client-csharp/generator/Azure.Generator/src/Azure.Generator.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="Microsoft.Generator.CSharp.ClientModel" />
1312
<PackageReference Include="Azure.Core" />
13+
<PackageReference Include="Microsoft.Generator.CSharp.ClientModel" />
1414
</ItemGroup>
1515

1616
<!-- Copy output to package dist path for local execution -->

eng/packages/http-client-csharp/generator/Azure.Generator/src/AzureClientPlugin.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
using Microsoft.CodeAnalysis;
45
using Microsoft.Generator.CSharp;
56
using Microsoft.Generator.CSharp.ClientModel;
67
using System;
8+
using System.ClientModel;
9+
using System.Collections.Generic;
710
using System.ComponentModel.Composition;
811

912
namespace Azure.Generator;
@@ -38,6 +41,7 @@ public AzureClientPlugin(GeneratorContext context) : base(context)
3841
public override void Configure()
3942
{
4043
base.Configure();
44+
AddMetadataReference(MetadataReference.CreateFromFile(typeof(Response).Assembly.Location));
4145
}
4246

4347
/// <summary>

eng/packages/http-client-csharp/generator/Azure.Generator/src/AzureTypeFactory.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
using Azure.Core;
45
using Azure.Generator.Primitives;
6+
using Azure.Generator.Providers;
7+
using Azure.Generator.Providers.Abstraction;
58
using Microsoft.Generator.CSharp.ClientModel;
9+
using Microsoft.Generator.CSharp.ClientModel.Providers;
610
using Microsoft.Generator.CSharp.Input;
711
using Microsoft.Generator.CSharp.Primitives;
812

@@ -11,6 +15,33 @@ namespace Azure.Generator
1115
/// <inheritdoc/>
1216
public class AzureTypeFactory : ScmTypeFactory
1317
{
18+
/// <inheritdoc/>
19+
public override CSharpType ClientUriBuilderBaseType => typeof(RequestUriBuilder);
20+
21+
/// <inheritdoc/>
22+
public override IClientResponseApi ClientResponseApi => AzureClientResponseProvider.Instance;
23+
24+
/// <inheritdoc/>
25+
public override IHttpResponseApi HttpResponseApi => AzureResponseProvider.Instance;
26+
27+
/// <inheritdoc/>
28+
public override IClientPipelineApi ClientPipelineApi => HttpPipelineProvider.Instance;
29+
30+
/// <inheritdoc/>
31+
public override IHttpMessageApi HttpMessageApi => HttpMessageProvider.Instance;
32+
33+
/// <inheritdoc/>
34+
public override IExpressionApi<HttpRequestApi> HttpRequestApi => HttpRequestProvider.Instance;
35+
36+
/// <inheritdoc/>
37+
public override IStatusCodeClassifierApi StatusCodeClassifierApi => StatusCodeClassifierProvider.Instance;
38+
39+
/// <inheritdoc/>
40+
public override IRequestContentApi RequestContentApi => RequestContentProvider.Instance;
41+
42+
/// <inheritdoc/>
43+
public override IHttpRequestOptionsApi HttpRequestOptionsApi => HttpRequestOptionsProvider.Instance;
44+
1445
/// <inheritdoc/>
1546
protected override CSharpType? CreateCSharpTypeCore(InputType inputType)
1647
{
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.Generator.CSharp.ClientModel.Providers;
5+
using Microsoft.Generator.CSharp.Expressions;
6+
using Microsoft.Generator.CSharp.Primitives;
7+
using Microsoft.Generator.CSharp.Snippets;
8+
using static Microsoft.Generator.CSharp.Snippets.Snippet;
9+
10+
namespace Azure.Generator.Providers
11+
{
12+
internal record AzureClientResponseProvider : ClientResponseApi
13+
{
14+
private static ClientResponseApi? _instance;
15+
internal static ClientResponseApi Instance => _instance ??= new AzureClientResponseProvider(Empty);
16+
17+
public AzureClientResponseProvider(ValueExpression original) : base(typeof(Response), original)
18+
{
19+
}
20+
21+
public override CSharpType ClientResponseType => typeof(Response);
22+
23+
public override CSharpType ClientResponseOfTType => typeof(Response<>);
24+
25+
public override CSharpType ClientResponseExceptionType => typeof(RequestFailedException);
26+
27+
public override ValueExpression CreateAsync(HttpResponseApi response)
28+
=> New.Instance(ClientResponseExceptionType, [response]);
29+
30+
public override ClientResponseApi FromExpression(ValueExpression original)
31+
=> new AzureClientResponseProvider(original);
32+
33+
public override ValueExpression FromResponse(ValueExpression valueExpression) => valueExpression;
34+
35+
public override ValueExpression FromValue(ValueExpression valueExpression, HttpResponseApi response)
36+
=> Static(ClientResponseType).Invoke(nameof(FromValue), [valueExpression, response]);
37+
38+
public override ValueExpression FromValue<ValueType>(ValueExpression valueExpression, HttpResponseApi response)
39+
=> Static(ClientResponseType).Invoke(nameof(FromValue), [valueExpression, response], [typeof(ValueType)], false);
40+
41+
public override HttpResponseApi GetRawResponse()
42+
=> new AzureResponseProvider(GetRawResponseExpression());
43+
44+
public override ClientResponseApi ToExpression() => this;
45+
46+
private ScopedApi<Response> GetRawResponseExpression() => Original.As<Response>();
47+
}
48+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.Generator.CSharp.ClientModel.Providers;
5+
using Microsoft.Generator.CSharp.Expressions;
6+
using Microsoft.Generator.CSharp.Primitives;
7+
using Microsoft.Generator.CSharp.Snippets;
8+
using System;
9+
using System.IO;
10+
11+
namespace Azure.Generator.Providers
12+
{
13+
internal record AzureResponseProvider : HttpResponseApi
14+
{
15+
private static HttpResponseApi? _instance;
16+
internal static HttpResponseApi Instance => _instance ??= new AzureResponseProvider(Empty);
17+
18+
public AzureResponseProvider(ValueExpression original) : base(typeof(Response), original)
19+
{
20+
}
21+
22+
public override CSharpType HttpResponseType => typeof(Response);
23+
24+
public override ScopedApi<BinaryData> Content()
25+
=> Original.Property(nameof(Response.Content)).As<BinaryData>();
26+
27+
public override ScopedApi<Stream> ContentStream()
28+
=> Original.Property(nameof(Response.ContentStream)).As<Stream>();
29+
30+
public override HttpResponseApi FromExpression(ValueExpression original)
31+
=> new AzureResponseProvider(original);
32+
33+
public override ScopedApi<bool> IsError()
34+
=> Original.Property(nameof(Response.IsError)).As<bool>();
35+
36+
public override HttpResponseApi ToExpression() => this;
37+
}
38+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Azure.Core;
5+
using Microsoft.Generator.CSharp.ClientModel.Providers;
6+
using Microsoft.Generator.CSharp.Expressions;
7+
using Microsoft.Generator.CSharp.Primitives;
8+
using Microsoft.Generator.CSharp.Statements;
9+
using static Microsoft.Generator.CSharp.Snippets.Snippet;
10+
11+
namespace Azure.Generator.Providers
12+
{
13+
internal record HttpMessageProvider : HttpMessageApi
14+
{
15+
private static HttpMessageApi? _instance;
16+
internal static HttpMessageApi Instance => _instance ??= new HttpMessageProvider(Empty);
17+
18+
public HttpMessageProvider(ValueExpression original) : base(typeof(HttpMessage), original)
19+
{
20+
}
21+
22+
public override CSharpType HttpMessageType => typeof(HttpMessage);
23+
24+
public override MethodBodyStatement Apply(ValueExpression options)
25+
=> MethodBodyStatement.Empty;
26+
27+
public override ValueExpression BufferResponse()
28+
=> Original.Property(nameof(HttpMessage.BufferResponse));
29+
30+
public override MethodBodyStatement[] ExtractResponse()
31+
=> [Original.Invoke(nameof(HttpMessage.ExtractResponseContent)).Terminate(), Return(Original.Property(nameof(HttpMessage.Response)))];
32+
33+
public override HttpMessageApi FromExpression(ValueExpression original)
34+
=> new HttpMessageProvider(original);
35+
36+
public override HttpRequestApi Request()
37+
=> new HttpRequestProvider(Original.Property(nameof(HttpMessage.Request)));
38+
39+
public override HttpResponseApi Response()
40+
=> new AzureResponseProvider(Original.Property(nameof(HttpMessage.Response)));
41+
42+
public override ValueExpression ResponseClassifier()
43+
=> Original.Property(nameof(HttpMessage.ResponseClassifier));
44+
45+
public override HttpMessageApi ToExpression() => this;
46+
}
47+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Azure.Core;
5+
using Azure.Core.Pipeline;
6+
using Microsoft.Generator.CSharp.ClientModel.Providers;
7+
using Microsoft.Generator.CSharp.Expressions;
8+
using Microsoft.Generator.CSharp.Primitives;
9+
using static Microsoft.Generator.CSharp.Snippets.Snippet;
10+
11+
namespace Azure.Generator.Providers.Abstraction
12+
{
13+
internal record HttpPipelineProvider : ClientPipelineApi
14+
{
15+
private static ClientPipelineApi? _instance;
16+
internal static ClientPipelineApi Instance => _instance ??= new HttpPipelineProvider(Empty);
17+
18+
public HttpPipelineProvider(ValueExpression original) : base(typeof(HttpPipeline), original)
19+
{
20+
}
21+
22+
public override CSharpType ClientPipelineType => typeof(HttpPipeline);
23+
24+
public override CSharpType ClientPipelineOptionsType => typeof(ClientOptions);
25+
26+
public override CSharpType PipelinePolicyType => typeof(HttpPipelinePolicy);
27+
28+
public override ValueExpression Create(ValueExpression options, ValueExpression perRetryPolicies)
29+
=> Static(typeof(HttpPipelineBuilder)).Invoke(nameof(HttpPipelineBuilder.Build), [options, perRetryPolicies]);
30+
31+
public override HttpMessageApi CreateMessage()
32+
=> new HttpMessageProvider(Original.Invoke(nameof(HttpPipeline.CreateMessage)));
33+
34+
public override ValueExpression CreateMessage(HttpRequestOptionsApi requestOptions, ValueExpression responseClassifier)
35+
=> Original.Invoke(nameof(HttpPipeline.CreateMessage), requestOptions, responseClassifier).As<HttpMessage>();
36+
37+
public override ClientPipelineApi FromExpression(ValueExpression expression)
38+
=> new HttpPipelineProvider(expression);
39+
40+
public override ValueExpression PerRetryPolicy(params ValueExpression[] arguments)
41+
=> Empty; // TODO: implement with default retry policy for Azure
42+
43+
public override InvokeMethodExpression Send(HttpMessageApi message)
44+
=> Original.Invoke(nameof(HttpPipeline.Send), [message, Default]);
45+
46+
public override InvokeMethodExpression SendAsync(HttpMessageApi message)
47+
=> Original.Invoke(nameof(HttpPipeline.SendAsync), [message, Default], true);
48+
49+
public override ClientPipelineApi ToExpression() => this;
50+
}
51+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.Generator.CSharp.ClientModel.Providers;
5+
using Microsoft.Generator.CSharp.Expressions;
6+
using Microsoft.Generator.CSharp.Primitives;
7+
using static Microsoft.Generator.CSharp.Snippets.Snippet;
8+
9+
namespace Azure.Generator.Providers.Abstraction
10+
{
11+
internal record HttpRequestOptionsProvider : HttpRequestOptionsApi
12+
{
13+
private static HttpRequestOptionsApi? _instance;
14+
internal static HttpRequestOptionsApi Instance => _instance ??= new HttpRequestOptionsProvider(Empty);
15+
16+
public HttpRequestOptionsProvider(ValueExpression original) : base(typeof(RequestContext), original)
17+
{
18+
}
19+
20+
public override CSharpType HttpRequestOptionsType => typeof(RequestContext);
21+
22+
public override string ParameterName => "context";
23+
24+
public override ValueExpression ErrorOptions()
25+
=> Original.NullConditional().Property(nameof(RequestContext.ErrorOptions));
26+
27+
public override HttpRequestOptionsApi FromExpression(ValueExpression original)
28+
=> new HttpRequestOptionsProvider(original);
29+
30+
public override ValueExpression NoThrow()
31+
=> FrameworkEnumValue(Azure.ErrorOptions.NoThrow);
32+
33+
public override HttpRequestOptionsApi ToExpression() => this;
34+
}
35+
}

0 commit comments

Comments
 (0)