Skip to content

Commit 896e8e7

Browse files
authored
Update to latest MTG to adopt service methods (Azure#49457)
1 parent 8538555 commit 896e8e7

File tree

89 files changed

+20420
-9219
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+20420
-9219
lines changed

eng/Packages.Data.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@
206206
</ItemGroup>
207207

208208
<ItemGroup Condition="'$(IsGeneratorLibrary)' == 'true'">
209-
<PackageReference Update="Microsoft.TypeSpec.Generator.ClientModel" Version="1.0.0-alpha.20250407.1" />
209+
<PackageReference Update="Microsoft.TypeSpec.Generator.ClientModel" Version="1.0.0-alpha.20250418.3" />
210210
<PackageReference Update="System.ClientModel" Version="1.3.0" />
211211
</ItemGroup>
212212

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Mgmt/src/InputTransformation/InputClientTransformer.cs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,40 +11,35 @@ internal static class InputClientTransformer
1111
{
1212
public static InputClient? TransformInputClient(InputClient client)
1313
{
14-
var operationsToKeep = new List<InputOperation>();
15-
foreach (var operation in client.Operations)
14+
var methodsToKeep = new List<InputServiceMethod>();
15+
foreach (var method in client.Methods)
1616
{
17+
var operation = method.Operation;
1718
// operations_list has been covered in Azure.ResourceManager already, we don't need to generate it in the client
1819
if (operation.CrossLanguageDefinitionId != "Azure.ResourceManager.Operations.list")
1920
{
20-
var transformedOperation = new InputOperation(operation.Name, operation.ResourceName, operation.Summary, operation.Doc, operation.Deprecated, operation.Accessibility, TransformInputOperationParameters(operation), operation.Responses, operation.HttpMethod, operation.Uri, operation.Path, operation.ExternalDocsUrl, operation.RequestMediaTypes, operation.BufferResponse, operation.LongRunning, operation.Paging, operation.GenerateProtocolMethod, operation.GenerateConvenienceMethod, operation.CrossLanguageDefinitionId);
21-
operationsToKeep.Add(transformedOperation);
21+
SetSubscriptionIdToMethodParameter(operation);
22+
methodsToKeep.Add(method);
2223
}
2324
}
2425

2526
// We removed the list operation above, we should skip the empty client afterwards
2627
// There is no need to check sub-clients or custom code since it is specific to handle the above removing
27-
if (operationsToKeep.Count == 0) return null;
28+
if (methodsToKeep.Count == 0) return null;
2829

29-
return new InputClient(client.Name, client.Namespace, client.CrossLanguageDefinitionId, client.Summary, client.Doc, operationsToKeep, client.Parameters, client.Parent, client.Children);
30+
return new InputClient(client.Name, client.Namespace, client.CrossLanguageDefinitionId, client.Summary, client.Doc, methodsToKeep, client.Parameters, client.Parent, client.Children);
3031
}
3132

32-
private static IReadOnlyList<InputParameter> TransformInputOperationParameters(InputOperation operation)
33+
private static void SetSubscriptionIdToMethodParameter(InputOperation operation)
3334
{
34-
var parameters = new List<InputParameter>();
3535
foreach (var parameter in operation.Parameters)
3636
{
3737
if (parameter.NameInRequest.Equals("subscriptionId", StringComparison.OrdinalIgnoreCase))
3838
{
3939
// Always set subscriptionId to method parameter
40-
parameters.Add(new InputParameter(parameter.Name, parameter.NameInRequest, parameter.Summary, parameter.Doc, parameter.Type, parameter.Location, parameter.DefaultValue, InputOperationParameterKind.Method, parameter.IsRequired, parameter.IsApiVersion, parameter.IsContentType, parameter.IsEndpoint, parameter.SkipUrlEncoding, parameter.Explode, parameter.ArraySerializationDelimiter, parameter.HeaderCollectionPrefix));
41-
}
42-
else
43-
{
44-
parameters.Add(parameter);
40+
parameter.Update(InputParameterKind.Method);
4541
}
4642
}
47-
return parameters;
4843
}
4944
}
5045
}

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

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace Azure.Generator.Management.Providers
3131
/// </summary>
3232
internal class ResourceClientProvider : TypeProvider
3333
{
34-
private IReadOnlyCollection<InputOperation> _resourceOperations;
34+
private IReadOnlyCollection<InputServiceMethod> _resourceServiceMethods;
3535
private readonly IReadOnlyList<string> _contextualParameters;
3636
private bool _isSingleton;
3737

@@ -52,8 +52,8 @@ public ResourceClientProvider(InputClient inputClient)
5252
SpecName = resourceModel.Name;
5353

5454
// We should be able to assume that all operations in the resource client are for the same resource
55-
var requestPath = new RequestPath(inputClient.Operations.First().Path);
56-
_resourceOperations = inputClient.Operations;
55+
var requestPath = new RequestPath(inputClient.Methods.First().Operation.Path);
56+
_resourceServiceMethods = inputClient.Methods;
5757
ResourceData = ManagementClientGenerator.Instance.TypeFactory.CreateModel(resourceModel)!;
5858
_clientProvider = ManagementClientGenerator.Instance.TypeFactory.CreateClient(inputClient)!;
5959

@@ -203,36 +203,36 @@ protected MethodProvider BuildValidateResourceIdMethod()
203203
protected override MethodProvider[] BuildMethods()
204204
{
205205
var operationMethods = new List<MethodProvider>();
206-
foreach (var operation in _resourceOperations)
206+
foreach (var method in _resourceServiceMethods)
207207
{
208-
var convenienceMethod = GetCorrespondingConvenienceMethod(operation, false);
208+
var convenienceMethod = GetCorrespondingConvenienceMethod(method.Operation, false);
209209
// exclude the List operations for resource, they will be in ResourceCollection
210210
var returnType = convenienceMethod.Signature.ReturnType!;
211-
if ((returnType.IsFrameworkType && returnType.IsList) || operation.Paging?.ItemPropertySegments.Any() == true)
211+
if ((returnType.IsFrameworkType && returnType.IsList) || (method is InputPagingServiceMethod pagingMethod && pagingMethod.PagingMetadata.ItemPropertySegments.Any() == true))
212212
{
213213
continue;
214214
}
215215

216216
// only update for non-singleton resource
217-
var isUpdateOnly = operation.HttpMethod == HttpMethod.Put.ToString() && !_isSingleton;
218-
operationMethods.Add(BuildOperationMethod(operation, convenienceMethod, false, isUpdateOnly));
219-
var asyncConvenienceMethod = GetCorrespondingConvenienceMethod(operation, true);
220-
operationMethods.Add(BuildOperationMethod(operation, asyncConvenienceMethod, true, isUpdateOnly));
217+
var isUpdateOnly = method.Operation.HttpMethod == HttpMethod.Put.ToString() && !_isSingleton;
218+
operationMethods.Add(BuildOperationMethod(method, convenienceMethod, false, isUpdateOnly));
219+
var asyncConvenienceMethod = GetCorrespondingConvenienceMethod(method.Operation, true);
220+
operationMethods.Add(BuildOperationMethod(method, asyncConvenienceMethod, true, isUpdateOnly));
221221
}
222222

223223
return [BuildValidateResourceIdMethod(), .. operationMethods];
224224
}
225225

226-
private MethodProvider BuildOperationMethod(InputOperation operation, MethodProvider convenienceMethod, bool isAsync, bool isUpdateOnly = false)
226+
private MethodProvider BuildOperationMethod(InputServiceMethod method, MethodProvider convenienceMethod, bool isAsync, bool isUpdateOnly = false)
227227
{
228-
var isLongRunning = operation.LongRunning != null;
228+
var operation = method.Operation;
229229
var signature = new MethodSignature(
230230
isUpdateOnly ? (isAsync ? "UpdateAsync" : "Update") : convenienceMethod.Signature.Name,
231231
isUpdateOnly ? $"Update a {SpecName}" : convenienceMethod.Signature.Description,
232232
convenienceMethod.Signature.Modifiers,
233-
GetOperationMethodReturnType(isAsync, isLongRunning, operation.Responses, out var isGeneric),
233+
GetOperationMethodReturnType(isAsync, method is InputLongRunningServiceMethod || method is InputLongRunningPagingServiceMethod, operation.Responses, out var isGeneric),
234234
convenienceMethod.Signature.ReturnDescription,
235-
GetOperationMethodParameters(convenienceMethod, isLongRunning),
235+
GetOperationMethodParameters(convenienceMethod, method is InputLongRunningServiceMethod),
236236
convenienceMethod.Signature.Attributes,
237237
convenienceMethod.Signature.GenericArguments,
238238
convenienceMethod.Signature.GenericParameterConstraints,
@@ -244,7 +244,7 @@ private MethodProvider BuildOperationMethod(InputOperation operation, MethodProv
244244
UsingDeclare("scope", typeof(DiagnosticScope), _clientDiagonosticsField.Invoke(nameof(ClientDiagnostics.CreateScope), [Literal($"{Type.Namespace}.{operation.Name}")]), out var scopeVariable),
245245
scopeVariable.Invoke(nameof(DiagnosticScope.Start)).Terminate(),
246246
new TryCatchFinallyStatement
247-
(BuildOperationMethodTryStatement(convenienceMethod, isAsync, isLongRunning, operation, isGeneric), Catch(Declare<Exception>("e", out var exceptionVarialble), [scopeVariable.Invoke(nameof(DiagnosticScope.Failed), exceptionVarialble).Terminate(), Throw()]))
247+
(BuildOperationMethodTryStatement(convenienceMethod, isAsync, method, isGeneric), Catch(Declare<Exception>("e", out var exceptionVarialble), [scopeVariable.Invoke(nameof(DiagnosticScope.Failed), exceptionVarialble).Terminate(), Throw()]))
248248
};
249249

250250
return new MethodProvider(signature, bodyStatements, this);
@@ -287,8 +287,9 @@ protected CSharpType GetOperationMethodReturnType(bool isAsync, bool isLongRunni
287287
return isAsync ? new CSharpType(typeof(Task<>), new CSharpType(typeof(Response<>), Type)) : new CSharpType(typeof(Response<>), Type);
288288
}
289289

290-
private TryStatement BuildOperationMethodTryStatement(MethodProvider convenienceMethod, bool isAsync, bool isLongRunning, InputOperation operation, bool isGeneric)
290+
private TryStatement BuildOperationMethodTryStatement(MethodProvider convenienceMethod, bool isAsync, InputServiceMethod method, bool isGeneric)
291291
{
292+
var operation = method.Operation;
292293
var cancellationToken = convenienceMethod.Signature.Parameters.Single(p => p.Type.Equals(typeof(CancellationToken)));
293294
var tryStatement = new TryStatement();
294295
var contextDeclaration = Declare("context", typeof(RequestContext), New.Instance(typeof(RequestContext), new Dictionary<ValueExpression, ValueExpression> { { Identifier(nameof(RequestContext.CancellationToken)), cancellationToken } }), out var contextVariable);
@@ -311,10 +312,20 @@ private TryStatement BuildOperationMethodTryStatement(MethodProvider convenience
311312
tryStatement.Add(responseDeclaration);
312313
}
313314

314-
if (isLongRunning)
315+
if (method is InputLongRunningServiceMethod || method is InputLongRunningPagingServiceMethod)
315316
{
317+
OperationFinalStateVia finalStateVia = OperationFinalStateVia.Location;
318+
if (method is InputLongRunningServiceMethod lroMethod)
319+
{
320+
finalStateVia = (OperationFinalStateVia)lroMethod.LongRunningServiceMetadata.FinalStateVia;
321+
}
322+
else if (method is InputLongRunningPagingServiceMethod lroPagingMethod)
323+
{
324+
finalStateVia = (OperationFinalStateVia)lroPagingMethod.LongRunningServiceMetadata.FinalStateVia;
325+
}
326+
316327
var armOperationType = !isGeneric ? ManagementClientGenerator.Instance.OutputLibrary.ArmOperation.Type : ManagementClientGenerator.Instance.OutputLibrary.GenericArmOperation.Type.MakeGenericType([Type]);
317-
ValueExpression[] armOperationArguments = [_clientDiagonosticsField, This.Property("Pipeline"), messageVariable.Property("Request"), isGeneric ? responseVariable.Invoke("GetRawResponse") : responseVariable, Static(typeof(OperationFinalStateVia)).Property(((OperationFinalStateVia)operation.LongRunning!.FinalStateVia).ToString())];
328+
ValueExpression[] armOperationArguments = [_clientDiagonosticsField, This.Property("Pipeline"), messageVariable.Property("Request"), isGeneric ? responseVariable.Invoke("GetRawResponse") : responseVariable, Static(typeof(OperationFinalStateVia)).Property(finalStateVia.ToString())];
318329
var operationDeclaration = Declare("operation", armOperationType, New.Instance(armOperationType, isGeneric ? [New.Instance(Source.Type, This.Property("Client")), .. armOperationArguments] : armOperationArguments), out var operationVariable);
319330

320331
tryStatement.Add(operationDeclaration);

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,22 @@ namespace Azure.Generator.Management.Providers
2020
internal class ResourceCollectionClientProvider : ResourceClientProvider
2121
{
2222
private ResourceClientProvider _resource;
23-
private InputOperation? _getAll;
23+
private InputServiceMethod? _getAll;
2424
private InputOperation? _create;
2525
private InputOperation? _get;
2626

2727
public ResourceCollectionClientProvider(InputClient inputClient, ResourceClientProvider resource) : base(inputClient)
2828
{
2929
_resource = resource;
3030

31-
foreach (var operation in inputClient.Operations)
31+
foreach (var method in inputClient.Methods)
3232
{
33+
var operation = method.Operation;
3334
if (operation.HttpMethod == HttpMethod.Get.ToString())
3435
{
3536
if (operation.Name == "list")
3637
{
37-
_getAll = operation;
38+
_getAll = method;
3839
}
3940
else if (operation.Name == "get")
4041
{
@@ -104,8 +105,8 @@ private MethodProvider[] BuildEnumeratorMethods()
104105

105106
private MethodProvider BuildGetAllMethod(bool isAsync)
106107
{
107-
var convenienceMethod = GetCorrespondingConvenienceMethod(_getAll!, isAsync);
108-
var isLongRunning = _getAll?.LongRunning != null;
108+
var convenienceMethod = GetCorrespondingConvenienceMethod(_getAll!.Operation, isAsync);
109+
var isLongRunning = _getAll is InputLongRunningPagingServiceMethod;
109110
var signature = new MethodSignature(
110111
isAsync ? "GetAllAsync" : "GetAll",
111112
convenienceMethod.Signature.Description,

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Mgmt/test/Azure.Generator.Mgmt.Tests/Common/InputResourceData.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public static (InputClient InputClient, IReadOnlyList<InputModelType> InputModel
3030
{ KnownDecorators.ResourceModel, BinaryData.FromString($"\"{ResourceModelName}\"") },
3131
{ KnownDecorators.ResourceType, BinaryData.FromString("\"a/test\"") }
3232
};
33-
var client = InputFactory.Client(TestClientName, operations: [operation], decorators: [new InputDecoratorInfo(KnownDecorators.ResourceMetadata, resourceMetadataArguments), new InputDecoratorInfo(KnownDecorators.ArmProviderNamespace, null)]);
33+
var client = InputFactory.Client(TestClientName, methods: [InputFactory.BasicServiceMethod("Get", operation)], decorators: [new InputDecoratorInfo(KnownDecorators.ResourceMetadata, resourceMetadataArguments), new InputDecoratorInfo(KnownDecorators.ArmProviderNamespace, null)]);
3434
return (client, [responseModel]);
3535
}
3636
}

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
@@ -13,7 +13,7 @@
1313

1414
<Target Name="CheckEmitterBuild" BeforeTargets="Build">
1515
<!-- Check if the folder does not exist -->
16-
<Error Condition="!Exists('..\..\..\node_modules\@typespec\http-client-csharp')" Text="Emitter has not been built please run `pnpm i` from repo root folder, and followed by `pnpm run build` from ./eng/packages/http-client-csharp folder." />
16+
<Error Condition="!Exists('..\..\..\node_modules\@typespec\http-client-csharp')" Text="Emitter has not been built please run `npm ci` from repo root folder, and followed by `npm run build` from ./eng/packages/http-client-csharp folder." />
1717
</Target>
1818

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

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

Lines changed: 0 additions & 50 deletions
This file was deleted.

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using Microsoft.TypeSpec.Generator;
5+
using Microsoft.TypeSpec.Generator.Input;
56
using Microsoft.TypeSpec.Generator.Primitives;
67
using System;
78
using System.Collections.Generic;
@@ -86,10 +87,10 @@ private static void TraverseInput(out bool hasOperation, out bool hasLongRunning
8687
hasLongRunningOperation = false;
8788
foreach (var inputClient in AzureClientGenerator.Instance.InputLibrary.InputNamespace.Clients)
8889
{
89-
foreach (var operation in inputClient.Operations)
90+
foreach (var method in inputClient.Methods)
9091
{
9192
hasOperation = true;
92-
if (operation.LongRunning != null)
93+
if (method is InputLongRunningServiceMethod || method is InputLongRunningPagingServiceMethod)
9394
{
9495
hasLongRunningOperation = true;
9596
return;

0 commit comments

Comments
 (0)