Skip to content

Commit e003dd8

Browse files
authored
Fix generation (Azure#50488)
1 parent 5e07a92 commit e003dd8

File tree

10 files changed

+1175
-625
lines changed

10 files changed

+1175
-625
lines changed

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Providers/OperationMethodProviders/ResourceOperationMethodProvider.cs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ internal class ResourceOperationMethodProvider
3434
protected readonly MethodSignature _signature;
3535
protected readonly MethodBodyStatement[] _bodyStatements;
3636

37+
private readonly CSharpType? _responseGenericType;
38+
private readonly bool _isGeneric;
39+
private readonly bool _isLongRunningOperation;
40+
3741
public ResourceOperationMethodProvider(
3842
ResourceClientProvider resourceClientProvider,
3943
InputServiceMethod method,
@@ -44,6 +48,9 @@ public ResourceOperationMethodProvider(
4448
_serviceMethod = method;
4549
_convenienceMethod = convenienceMethod;
4650
_isAsync = isAsync;
51+
_responseGenericType = _serviceMethod.GetResponseBodyType();
52+
_isGeneric = _responseGenericType != null;
53+
_isLongRunningOperation = _serviceMethod.IsLongRunningOperation();
4754
_clientDiagnosticsField = resourceClientProvider.GetClientDiagnosticsField();
4855
_signature = CreateSignature();
4956
_bodyStatements = BuildBodyStatements();
@@ -87,10 +94,9 @@ protected virtual MethodSignature CreateSignature()
8794

8895
private TryExpression BuildTryExpression()
8996
{
90-
var cancellationTokenParameter = _convenienceMethod.Signature.Parameters.Single(p => p.Type.Equals(typeof(CancellationToken)));
97+
var cancellationTokenParameter = _convenienceMethod.Signature.Parameters.FirstOrDefault(p => p.Type.Equals(typeof(CancellationToken))) ?? KnownParameters.CancellationTokenParameter;
9198

9299
var requestMethod = _resourceClientProvider.GetClientProvider().GetRequestMethodByOperation(_serviceMethod.Operation);
93-
94100
var tryStatements = new List<MethodBodyStatement>
95101
{
96102
ResourceMethodSnippets.CreateRequestContext(cancellationTokenParameter, out var contextVariable)
@@ -103,7 +109,7 @@ private TryExpression BuildTryExpression()
103109

104110
tryStatements.AddRange(BuildClientPipelineProcessing(messageVariable, contextVariable, out var responseVariable));
105111

106-
if (_serviceMethod.IsLongRunningOperation())
112+
if (_isLongRunningOperation)
107113
{
108114
tryStatements.AddRange(
109115
BuildLroHandling(
@@ -123,22 +129,17 @@ private IReadOnlyList<MethodBodyStatement> BuildClientPipelineProcessing(
123129
VariableExpression contextVariable,
124130
out VariableExpression responseVariable)
125131
{
126-
var responseType = _convenienceMethod.Signature.ReturnType!.UnWrapAsync();
127-
128-
// Check if the return type is a generic Response<T> or just Response
129-
if (!responseType.Equals(typeof(Response)))
132+
if (_isGeneric && !_isLongRunningOperation)
130133
{
131-
// For methods returning Response<T> (e.g., Response<MyResource>), use generic response processing
132134
return ResourceMethodSnippets.CreateGenericResponsePipelineProcessing(
133135
messageVariable,
134136
contextVariable,
135-
responseType,
137+
_responseGenericType!,
136138
_isAsync,
137139
out responseVariable);
138140
}
139141
else
140142
{
141-
// For methods returning just Response (no generic type), use non-generic response processing
142143
return ResourceMethodSnippets.CreateNonGenericResponsePipelineProcessing(
143144
messageVariable,
144145
contextVariable,
@@ -155,9 +156,8 @@ private IReadOnlyList<MethodBodyStatement> BuildLroHandling(
155156
var statements = new List<MethodBodyStatement>();
156157

157158
var finalStateVia = _serviceMethod.GetOperationFinalStateVia();
158-
bool isGeneric = _serviceMethod.GetResponseBodyType() != null;
159159

160-
var armOperationType = isGeneric
160+
var armOperationType = _isGeneric
161161
? ManagementClientGenerator.Instance.OutputLibrary.GenericArmOperation.Type
162162
.MakeGenericType([_resourceClientProvider.ResourceClientCSharpType])
163163
: ManagementClientGenerator.Instance.OutputLibrary.ArmOperation.Type;
@@ -166,11 +166,11 @@ private IReadOnlyList<MethodBodyStatement> BuildLroHandling(
166166
_clientDiagnosticsField,
167167
This.Property("Pipeline"),
168168
messageVariable.Property("Request"),
169-
isGeneric ? responseVariable.Invoke("GetRawResponse") : responseVariable,
169+
responseVariable,
170170
Static(typeof(OperationFinalStateVia)).Property(finalStateVia.ToString())
171171
];
172172

173-
var operationInstanceArguments = isGeneric
173+
var operationInstanceArguments = _isGeneric
174174
? [
175175
New.Instance(_resourceClientProvider.Source.Type, This.Property("Client")),
176176
.. armOperationArguments
@@ -184,13 +184,13 @@ .. armOperationArguments
184184
out var operationVariable);
185185
statements.Add(operationDeclaration);
186186

187-
var waitMethod = isGeneric
187+
var waitMethod = _isGeneric
188188
? (_isAsync ? "WaitForCompletionAsync" : "WaitForCompletion")
189189
: (_isAsync ? "WaitForCompletionResponseAsync" : "WaitForCompletionResponse");
190190

191191
var waitInvocation = _isAsync
192-
? operationVariable.Invoke(waitMethod, [cancellationTokenParameter], null, _isAsync).Terminate()
193-
: operationVariable.Invoke(waitMethod, cancellationTokenParameter).Terminate();
192+
? operationVariable.Invoke(waitMethod, [cancellationTokenParameter], null, _isAsync).Terminate()
193+
: operationVariable.Invoke(waitMethod, cancellationTokenParameter).Terminate();
194194

195195
var waitIfCompletedStatement = new IfStatement(
196196
KnownAzureParameters.WaitUntil.Equal(
@@ -243,7 +243,11 @@ protected IReadOnlyList<ParameterProvider> GetOperationMethodParameters()
243243

244244
foreach (var parameter in _convenienceMethod.Signature.Parameters)
245245
{
246-
if (!_resourceClientProvider.ImplicitParameterNames.Contains(parameter.Name))
246+
if (parameter.Type.Equals(typeof(RequestContext)))
247+
{
248+
result.Add(KnownParameters.CancellationTokenParameter);
249+
}
250+
else if (!_resourceClientProvider.ImplicitParameterNames.Contains(parameter.Name))
247251
{
248252
result.Add(parameter);
249253
}

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Providers/ResourceClientProvider.cs

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -247,23 +247,23 @@ protected override MethodProvider[] BuildMethods()
247247
continue;
248248
}
249249

250-
// Check if this is an update operation (PUT method for non-singleton resource)
251-
var isUpdateOperation = method.Operation.HttpMethod == HttpMethod.Put.ToString() && !IsSingleton;
250+
// Check if this is an update operation (PUT or Patch method for non-singleton resource)
251+
var isUpdateOperation = (method.Operation.HttpMethod == HttpMethod.Put.ToString() || method.Operation.HttpMethod == HttpMethod.Patch.ToString()) && !IsSingleton;
252252

253253
if (isUpdateOperation)
254254
{
255255
var updateMethodProvider = new UpdateOperationMethodProvider(this, method, convenienceMethod, false);
256256
operationMethods.Add(updateMethodProvider);
257257

258-
var asyncConvenienceMethod = GetCorrespondingConvenienceMethod(method.Operation, true);
258+
var asyncConvenienceMethod = _restClientProvider.GetConvenienceMethodByOperation(method.Operation, true);
259259
var updateAsyncMethodProvider = new UpdateOperationMethodProvider(this, method, asyncConvenienceMethod, true);
260260
operationMethods.Add(updateAsyncMethodProvider);
261261
}
262262
else
263263
{
264-
operationMethods.Add(BuildOperationMethod(method, convenienceMethod, false));
265-
var asyncConvenienceMethod = GetCorrespondingConvenienceMethod(method.Operation, true);
266-
operationMethods.Add(BuildOperationMethod(method, asyncConvenienceMethod, true));
264+
operationMethods.Add(new ResourceOperationMethodProvider(this, method, convenienceMethod, false));
265+
var asyncConvenienceMethod = _restClientProvider.GetConvenienceMethodByOperation(method.Operation, true);
266+
operationMethods.Add(new ResourceOperationMethodProvider(this, method, asyncConvenienceMethod, true));
267267
}
268268
}
269269

@@ -280,20 +280,6 @@ protected override MethodProvider[] BuildMethods()
280280
];
281281
}
282282

283-
protected MethodProvider BuildOperationMethod(InputServiceMethod method, MethodProvider convenienceMethod, bool isAsync)
284-
{
285-
return BuildOperationMethodCore(method, convenienceMethod, isAsync);
286-
}
287-
288-
protected MethodProvider BuildOperationMethodCore(InputServiceMethod method, MethodProvider convenienceMethod, bool isAsync)
289-
{
290-
return new ResourceOperationMethodProvider(this, method, convenienceMethod, isAsync);
291-
}
292-
293-
// TODO: get clean name of operation Name
294-
protected MethodProvider GetCorrespondingConvenienceMethod(InputOperation operation, bool isAsync)
295-
=> _restClientProvider.CanonicalView.Methods.Single(m => m.Signature.Name.Equals(isAsync ? $"{operation.Name}Async" : operation.Name, StringComparison.OrdinalIgnoreCase) && m.Signature.Parameters.Any(p => p.Type.Equals(typeof(CancellationToken))));
296-
297283
public ScopedApi<bool> TryGetApiVersion(out ScopedApi<string> apiVersion)
298284
{
299285
var apiVersionDeclaration = new VariableExpression(typeof(string), $"{SpecName.ToLower()}ApiVersion");
@@ -335,7 +321,7 @@ public ValueExpression[] PopulateArguments(
335321
if (convenienceMethod != null)
336322
{
337323
var resource = convenienceMethod.Signature.Parameters
338-
.Single(p => p.Type.Equals(ResourceData.Type));
324+
.Single(p => p.Type.Equals(ResourceData.Type) || p.Type.Equals(typeof(RequestContent)));
339325
arguments.Add(resource);
340326
}
341327
else

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Providers/ResourceCollectionClientProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ private List<MethodProvider> BuildCreateOrUpdateMethods()
151151
foreach (var isAsync in new List<bool> { true, false})
152152
{
153153
var convenienceMethod = _restClientProvider.GetConvenienceMethodByOperation(_create!.Operation, isAsync);
154-
result.Add(BuildOperationMethod(_create, convenienceMethod, isAsync));
154+
result.Add(new ResourceOperationMethodProvider(this, _create, convenienceMethod, isAsync));
155155
}
156156

157157
return result;
@@ -174,7 +174,7 @@ private List<MethodProvider> BuildGetMethods()
174174
foreach (var isAsync in new List<bool> { true, false})
175175
{
176176
var convenienceMethod = _restClientProvider.GetConvenienceMethodByOperation(_get!.Operation, isAsync);
177-
result.Add(BuildOperationMethod(_get, convenienceMethod, isAsync));
177+
result.Add(new ResourceOperationMethodProvider(this, _get, convenienceMethod, isAsync));
178178
}
179179

180180
return result;

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Providers/TagMethodProviders/BaseTagMethodProvider.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,10 @@ protected static List<MethodBodyStatement> CreateRequestContextAndProcessMessage
104104

105105
statements.Add(ResourceMethodSnippets.CreateHttpMessage(resourceClientProvider, "CreateGetRequest", arguments, out var messageVariable));
106106

107-
var responseType = new CSharpType(typeof(Response<>), resourceClientProvider.ResourceData.Type);
108107
statements.AddRange(ResourceMethodSnippets.CreateGenericResponsePipelineProcessing(
109108
messageVariable,
110109
contextVariable,
111-
responseType,
110+
resourceClientProvider.ResourceData.Type,
112111
isAsync,
113112
out responseVariable));
114113

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Snippets/ResourceMethodSnippets.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public static MethodBodyStatement CreateHttpMessage(
8989
public static IReadOnlyList<MethodBodyStatement> CreateGenericResponsePipelineProcessing(
9090
VariableExpression messageVariable,
9191
VariableExpression contextVariable,
92-
CSharpType responseType,
92+
CSharpType responseGenericType,
9393
bool isAsync,
9494
out VariableExpression responseVariable)
9595
{
@@ -107,10 +107,10 @@ public static IReadOnlyList<MethodBodyStatement> CreateGenericResponsePipelinePr
107107
// Response<T> response = Response.FromValue((T)result, result);
108108
var responseDeclaration = Declare(
109109
"response",
110-
responseType,
110+
new CSharpType(typeof(Response<>), responseGenericType),
111111
Static(typeof(Response)).Invoke(
112112
nameof(Response.FromValue),
113-
[resultVariable.CastTo(responseType.Arguments[0]), resultVariable]),
113+
[resultVariable.CastTo(responseGenericType), resultVariable]),
114114
out responseVariable);
115115
statements.Add(responseDeclaration);
116116

eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/foo.tsp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,7 @@ interface Foos {
4040

4141
delete is ArmResourceDeleteWithoutOkAsync<Foo>;
4242

43+
update is ArmCustomPatchAsync<Foo>;
44+
4345
list is ArmResourceListByParent<Foo>;
4446
}

eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/FooCollection.cs

Lines changed: 4 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)