From b4f5cd7d6da74d859ccbf8b86cd5598edc32d426 Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Wed, 22 Oct 2025 10:39:56 -0700 Subject: [PATCH 1/5] minor: added long path support to prerequisite --- packages/http-client-csharp/CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/http-client-csharp/CONTRIBUTING.md b/packages/http-client-csharp/CONTRIBUTING.md index d32813e3357..53518283b9c 100644 --- a/packages/http-client-csharp/CONTRIBUTING.md +++ b/packages/http-client-csharp/CONTRIBUTING.md @@ -22,6 +22,7 @@ Before you begin, ensure you have the following installed: - [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) - [Git](https://git-scm.com/) - [PowerShell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell) (version 7.0 or higher, for advanced testing and code generation scenarios) +- [Long Path Support](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=powershell#registry-setting-to-enable-long-paths) (Windows only required to avoid path length limitations during development) ## Getting Started From 708f9cd79a74c43a864532d2f517d6a1bd62dfc4 Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Thu, 23 Oct 2025 14:14:48 -0700 Subject: [PATCH 2/5] exposed types for scmMethodProvider --- .../src/Providers/ClientProvider.cs | 3 +- .../src/Providers/RestClientProvider.cs | 1 + .../src/Providers/ScmMethodProvider.cs | 46 +++++++++++++++++-- .../Providers/ScmMethodProviderCollection.cs | 4 +- .../ScmMethodProviderCollectionTests.cs | 41 +++++++++++++++++ 5 files changed, 88 insertions(+), 7 deletions(-) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs index 90f2ad420b0..742dacaae67 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs @@ -705,7 +705,8 @@ protected override ScmMethodProvider[] BuildMethods() Return( Static(typeof(Volatile)).Invoke(nameof(Volatile.Read), cachedClientFieldVar) .NullCoalesce(interlockedCompareExchange.NullCoalesce(subClient._clientCachingField))), - this); + this, + ScmMethodProvider.MethodType.Convenience); methods.Add(factoryMethod); } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs index 240a8786d48..db1f53a9277 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs @@ -123,6 +123,7 @@ private ScmMethodProvider BuildCreateRequestMethod(InputServiceMethod serviceMet signature, messageStatements, this, + ScmMethodProvider.MethodType.CreateRequest, xmlDocProvider: XmlDocProvider.Empty, serviceMethod: serviceMethod); } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProvider.cs index ca1d0eff002..91afb297c10 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProvider.cs @@ -5,28 +5,66 @@ using Microsoft.TypeSpec.Generator.Primitives; using Microsoft.TypeSpec.Generator.Providers; using Microsoft.TypeSpec.Generator.Statements; +using Microsoft.TypeSpec.Generator.ClientModel.Primitives; namespace Microsoft.TypeSpec.Generator.ClientModel.Providers { public class ScmMethodProvider : MethodProvider { + public enum MethodType + { + /// + /// Internal method that creates HTTP request messages. + /// + CreateRequest, + /// + /// Protocol method that handles raw requests and responses. + /// + Protocol, + /// + /// Convenience method with strongly-typed parameters and return values. + /// + Convenience + } public InputServiceMethod? ServiceMethod { get; } public TypeProvider? CollectionDefinition { get; } - public bool IsProtocolMethod { get; } + + /// + /// Gets the method type (CreateRequest, Protocol, or Convenience). + /// + public MethodType Type { get; } + + /// + /// Gets a value indicating whether this method is a CreateRequest method. + /// CreateRequest methods are internal methods that create HTTP messages for protocol methods. + /// + public bool IsCreateRequestMethod => Type == MethodType.CreateRequest; + + /// + /// Gets a value indicating whether this method is a protocol method. + /// Protocol methods handle raw requests and responses. + /// + public bool IsProtocolMethod => Type == MethodType.Protocol; + + /// + /// Gets a value indicating whether this method is a convenience method. + /// Convenience methods provide strongly-typed parameters and return types. + /// + public bool IsConvenienceMethod => Type == MethodType.Convenience; public ScmMethodProvider( MethodSignature signature, MethodBodyStatement bodyStatements, TypeProvider enclosingType, + MethodType methodType, XmlDocProvider? xmlDocProvider = default, TypeProvider? collectionDefinition = default, - InputServiceMethod? serviceMethod = default, - bool isProtocolMethod = false) + InputServiceMethod? serviceMethod = default) : base(signature, bodyStatements, enclosingType, xmlDocProvider) { CollectionDefinition = collectionDefinition; - IsProtocolMethod = isProtocolMethod; ServiceMethod = serviceMethod; + Type = methodType; } } } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs index 421f297c21c..4d1af224f9c 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs @@ -159,7 +159,7 @@ .. GetStackVariablesForReturnValueConversion(result, responseBodyType, isAsync, ]; } - var convenienceMethod = new ScmMethodProvider(methodSignature, methodBody, EnclosingType, collectionDefinition: collection, serviceMethod: ServiceMethod); + var convenienceMethod = new ScmMethodProvider(methodSignature, methodBody, EnclosingType, ScmMethodProvider.MethodType.Convenience, collectionDefinition: collection, serviceMethod: ServiceMethod); if (convenienceMethod.XmlDocs != null) { @@ -649,7 +649,7 @@ private ScmMethodProvider BuildProtocolMethod(MethodProvider createRequestMethod } var protocolMethod = - new ScmMethodProvider(methodSignature, methodBody, EnclosingType, collectionDefinition: collection, serviceMethod: ServiceMethod, isProtocolMethod: true); + new ScmMethodProvider(methodSignature, methodBody, EnclosingType, ScmMethodProvider.MethodType.Protocol, collectionDefinition: collection, serviceMethod: ServiceMethod); if (protocolMethod.XmlDocs != null) { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs index dc3304feb1e..a9f9cf52ca0 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs @@ -1073,5 +1073,46 @@ public static IEnumerable DefaultCSharpMethodCollectionTestCases ])); } } + + [Test] + public void TestMethodTypeIdentification() + { + MockHelpers.LoadMockGenerator(); + + var inputOperation = InputFactory.Operation("TestOperation"); + var inputServiceMethod = InputFactory.BasicServiceMethod("Test", inputOperation); + var inputClient = InputFactory.Client("TestClient", methods: [inputServiceMethod]); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(inputClient); + var methodCollection = new ScmMethodProviderCollection(inputServiceMethod, client!); + + // Verify protocol methods + var protocolMethods = methodCollection.Where(m => ((ScmMethodProvider)m).IsProtocolMethod).ToList(); + Assert.AreEqual(2, protocolMethods.Count); // sync + async + foreach (ScmMethodProvider method in protocolMethods) + { + Assert.IsTrue(method.IsProtocolMethod); + Assert.IsFalse(method.IsConvenienceMethod); + Assert.IsFalse(method.IsCreateRequestMethod); + Assert.AreEqual(ScmMethodProvider.MethodType.Protocol, method.Type); + } + + // Verify convenience methods + var convenienceMethods = methodCollection.Where(m => ((ScmMethodProvider)m).IsConvenienceMethod).ToList(); + Assert.AreEqual(2, convenienceMethods.Count); // sync + async + foreach (ScmMethodProvider method in convenienceMethods) + { + Assert.IsFalse(method.IsProtocolMethod); + Assert.IsTrue(method.IsConvenienceMethod); + Assert.IsFalse(method.IsCreateRequestMethod); + Assert.AreEqual(ScmMethodProvider.MethodType.Convenience, method.Type); + } + + // Verify CreateRequest method + var createRequestMethod = (ScmMethodProvider)client!.RestClient.GetCreateRequestMethod(inputOperation); + Assert.IsFalse(createRequestMethod.IsProtocolMethod); + Assert.IsFalse(createRequestMethod.IsConvenienceMethod); + Assert.IsTrue(createRequestMethod.IsCreateRequestMethod); + Assert.AreEqual(ScmMethodProvider.MethodType.CreateRequest, createRequestMethod.Type); + } } } From b1c9e39cf3f77a17c811511debc0fad09ff893d0 Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Mon, 27 Oct 2025 19:19:23 -0700 Subject: [PATCH 3/5] removed duplicate methodtype enum --- .../src/Providers/RestClientProvider.cs | 23 +++++++------------ .../Providers/ScmMethodProviderCollection.cs | 4 ++-- .../RestClientProviderTests.cs | 14 +++++------ 3 files changed, 17 insertions(+), 24 deletions(-) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs index db1f53a9277..192b7fe16df 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs @@ -99,7 +99,7 @@ protected override ScmMethodProvider[] BuildMethods() private ScmMethodProvider BuildCreateRequestMethod(InputServiceMethod serviceMethod, bool isNextLinkRequest = false) { var options = ScmKnownParameters.RequestOptions; - var parameters = GetMethodParameters(serviceMethod, MethodType.CreateRequest); + var parameters = GetMethodParameters(serviceMethod, ScmMethodProvider.MethodType.CreateRequest); if (isNextLinkRequest) { parameters = [ScmKnownParameters.NextPage, .. parameters]; @@ -758,7 +758,7 @@ public MethodProvider GetCreateNextLinkRequestMethod(InputOperation operation) return NextMethodCache[operation]; } - internal static List GetMethodParameters(InputServiceMethod serviceMethod, MethodType methodType) + internal static List GetMethodParameters(InputServiceMethod serviceMethod, ScmMethodProvider.MethodType methodType) { SortedList sortedParams = []; int path = 0; @@ -769,10 +769,10 @@ internal static List GetMethodParameters(InputServiceMethod s var operation = serviceMethod.Operation; // For convenience methods, use the service method parameters - var inputParameters = methodType is MethodType.Convenience ? serviceMethod.Parameters : operation.Parameters; + var inputParameters = methodType is ScmMethodProvider.MethodType.Convenience ? serviceMethod.Parameters : operation.Parameters; ModelProvider? spreadSource = null; - if (methodType == MethodType.Convenience) + if (methodType == ScmMethodProvider.MethodType.Convenience) { InputParameter? inputOperationSpreadParameter = operation.Parameters.FirstOrDefault(p => p.Scope.HasFlag(InputParameterScope.Spread)); spreadSource = inputOperationSpreadParameter != null @@ -817,11 +817,11 @@ internal static List GetMethodParameters(InputServiceMethod s continue; } - if (methodType is MethodType.Protocol or MethodType.CreateRequest) + if (methodType is ScmMethodProvider.MethodType.Protocol or ScmMethodProvider.MethodType.CreateRequest) { if (inputParam is InputBodyParameter) { - if (methodType == MethodType.CreateRequest) + if (methodType == ScmMethodProvider.MethodType.CreateRequest) { parameter = ScmKnownParameters.RequestContent; } @@ -837,7 +837,7 @@ internal static List GetMethodParameters(InputServiceMethod s parameter.Type = parameter.Type.IsEnum ? parameter.Type.UnderlyingEnumType : parameter.Type; } } - else if (methodType is MethodType.Convenience && + else if (methodType is ScmMethodProvider.MethodType.Convenience && spreadSource != null && inputParam is InputMethodParameter inputMethodParameter && inputMethodParameter.Location == InputRequestLocation.Body) @@ -876,7 +876,7 @@ internal static List GetMethodParameters(InputServiceMethod s sortedParams.Add(bodyRequired++, ScmKnownParameters.ContentType); } - if (methodType == MethodType.CreateRequest) + if (methodType == ScmMethodProvider.MethodType.CreateRequest) { // All the parameters should be required for the CreateRequest method foreach (var parameter in sortedParams.Values) @@ -898,13 +898,6 @@ internal static InputModelType GetSpreadParameterModel(InputParameter inputParam throw new InvalidOperationException($"inputParam `{inputParam.Name}` is `Spread` but not a model type"); } - internal enum MethodType - { - CreateRequest, - Protocol, - Convenience - } - private class StatusCodesComparer : IEqualityComparer> { bool IEqualityComparer>.Equals(List? x, List? y) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs index 4d1af224f9c..5b2a3a62d64 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs @@ -27,10 +27,10 @@ public class ScmMethodProviderCollection : IReadOnlyList { private readonly MethodProvider _createRequestMethod; private static readonly ClientPipelineExtensionsDefinition _clientPipelineExtensionsDefinition = new(); - private IList ProtocolMethodParameters => _protocolMethodParameters ??= RestClientProvider.GetMethodParameters(ServiceMethod, RestClientProvider.MethodType.Protocol); + private IList ProtocolMethodParameters => _protocolMethodParameters ??= RestClientProvider.GetMethodParameters(ServiceMethod, ScmMethodProvider.MethodType.Protocol); private IList? _protocolMethodParameters; - private IReadOnlyList ConvenienceMethodParameters => _convenienceMethodParameters ??= RestClientProvider.GetMethodParameters(ServiceMethod, RestClientProvider.MethodType.Convenience); + private IReadOnlyList ConvenienceMethodParameters => _convenienceMethodParameters ??= RestClientProvider.GetMethodParameters(ServiceMethod, ScmMethodProvider.MethodType.Convenience); private IReadOnlyList? _convenienceMethodParameters; private readonly InputPagingServiceMethod? _pagingServiceMethod; private IReadOnlyList? _methods; diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs index bcba57e7b4c..419cb2b82c4 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs @@ -104,7 +104,7 @@ public void ValidateProperties() [TestCaseSource(nameof(GetMethodParametersTestCases))] public void TestGetMethodParameters(InputServiceMethod inputServiceMethod) { - var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, RestClientProvider.MethodType.Convenience); + var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodProvider.MethodType.Convenience); Assert.IsTrue(methodParameters.Count > 0); @@ -139,7 +139,7 @@ public void TestGetMethodParameters(InputServiceMethod inputServiceMethod) [TestCase] public void TestGetMethodParameters_ProperOrdering() { - var methodParameters = RestClientProvider.GetMethodParameters(ServiceMethodWithMixedParamOrdering, RestClientProvider.MethodType.Convenience); + var methodParameters = RestClientProvider.GetMethodParameters(ServiceMethodWithMixedParamOrdering, ScmMethodProvider.MethodType.Convenience); Assert.AreEqual(ServiceMethodWithMixedParamOrdering.Parameters.Count, methodParameters.Count); @@ -152,7 +152,7 @@ public void TestGetMethodParameters_ProperOrdering() Assert.AreEqual("optionalHeader", methodParameters[5].Name); Assert.AreEqual("optionalContentType", methodParameters[6].Name); - var orderedPathParams = RestClientProvider.GetMethodParameters(ServiceMethodWithOnlyPathParams, RestClientProvider.MethodType.Convenience); + var orderedPathParams = RestClientProvider.GetMethodParameters(ServiceMethodWithOnlyPathParams, ScmMethodProvider.MethodType.Convenience); Assert.AreEqual(ServiceMethodWithOnlyPathParams.Parameters.Count, orderedPathParams.Count); Assert.AreEqual("c", orderedPathParams[0].Name); Assert.AreEqual("a", orderedPathParams[1].Name); @@ -185,7 +185,7 @@ public void HeaderParameterOptionality(bool isRequired, bool isValueType) "TestClient", methods: [testServiceMethod]); var clientProvider = new ClientProvider(client); - var parameters = RestClientProvider.GetMethodParameters(testServiceMethod, RestClientProvider.MethodType.Convenience); + var parameters = RestClientProvider.GetMethodParameters(testServiceMethod, ScmMethodProvider.MethodType.Convenience); Assert.IsNotNull(parameters); if (isRequired) @@ -705,7 +705,7 @@ public void TestReadOnlyParameters_FilteredFromProtocolMethod() InputFactory.MethodParameter("normalBody", InputPrimitiveType.Boolean, isRequired: false, location: InputRequestLocation.Body) ]); - var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, RestClientProvider.MethodType.Protocol); + var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodProvider.MethodType.Protocol); // Verify read-only parameters are filtered out Assert.IsFalse(methodParameters.Any(p => p.Name == "readOnlyPath")); @@ -737,7 +737,7 @@ public void TestReadOnlyParameters_FilteredFromConvenienceMethod() InputFactory.MethodParameter("normalHeader", InputPrimitiveType.Boolean, isRequired: false, location: InputRequestLocation.Header) ]); - var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, RestClientProvider.MethodType.Convenience); + var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodProvider.MethodType.Convenience); // Verify read-only parameters are filtered out Assert.IsFalse(methodParameters.Any(p => p.Name == "readOnlyQuery")); @@ -773,7 +773,7 @@ public void TestReadOnlyParameters_WithMixedParameterTypes() InputFactory.MethodParameter("normalBody", InputPrimitiveType.Boolean, isRequired: false, location: InputRequestLocation.Body) ]); - var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, RestClientProvider.MethodType.Convenience); + var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodProvider.MethodType.Convenience); Assert.AreEqual(4, methodParameters.Count); // Only non-readonly parameters Assert.IsTrue(methodParameters.Any(p => p.Name == "normalPath")); From 3355f04916e10521a1e21b0f181c81080f6e472f Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Thu, 30 Oct 2025 09:48:31 -0700 Subject: [PATCH 4/5] fixed comments --- .../src/Providers/ClientProvider.cs | 2 +- .../src/Providers/RestClientProvider.cs | 18 ++++---- .../src/Providers/ScmMethodKind.cs | 29 +++++++++++++ .../src/Providers/ScmMethodProvider.cs | 41 ++----------------- .../Providers/ScmMethodProviderCollection.cs | 9 ++-- .../RestClientProviderTests.cs | 14 +++---- .../ScmMethodProviderCollectionTests.cs | 23 ++--------- 7 files changed, 58 insertions(+), 78 deletions(-) create mode 100644 packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodKind.cs diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs index 742dacaae67..c3506b6b12b 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs @@ -706,7 +706,7 @@ protected override ScmMethodProvider[] BuildMethods() Static(typeof(Volatile)).Invoke(nameof(Volatile.Read), cachedClientFieldVar) .NullCoalesce(interlockedCompareExchange.NullCoalesce(subClient._clientCachingField))), this, - ScmMethodProvider.MethodType.Convenience); + ScmMethodKind.Convenience); methods.Add(factoryMethod); } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs index 192b7fe16df..219359b7f0d 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs @@ -99,7 +99,7 @@ protected override ScmMethodProvider[] BuildMethods() private ScmMethodProvider BuildCreateRequestMethod(InputServiceMethod serviceMethod, bool isNextLinkRequest = false) { var options = ScmKnownParameters.RequestOptions; - var parameters = GetMethodParameters(serviceMethod, ScmMethodProvider.MethodType.CreateRequest); + var parameters = GetMethodParameters(serviceMethod, ScmMethodKind.CreateRequest); if (isNextLinkRequest) { parameters = [ScmKnownParameters.NextPage, .. parameters]; @@ -123,7 +123,7 @@ private ScmMethodProvider BuildCreateRequestMethod(InputServiceMethod serviceMet signature, messageStatements, this, - ScmMethodProvider.MethodType.CreateRequest, + ScmMethodKind.CreateRequest, xmlDocProvider: XmlDocProvider.Empty, serviceMethod: serviceMethod); } @@ -758,7 +758,7 @@ public MethodProvider GetCreateNextLinkRequestMethod(InputOperation operation) return NextMethodCache[operation]; } - internal static List GetMethodParameters(InputServiceMethod serviceMethod, ScmMethodProvider.MethodType methodType) + internal static List GetMethodParameters(InputServiceMethod serviceMethod, ScmMethodKind methodType) { SortedList sortedParams = []; int path = 0; @@ -769,10 +769,10 @@ internal static List GetMethodParameters(InputServiceMethod s var operation = serviceMethod.Operation; // For convenience methods, use the service method parameters - var inputParameters = methodType is ScmMethodProvider.MethodType.Convenience ? serviceMethod.Parameters : operation.Parameters; + var inputParameters = methodType is ScmMethodKind.Convenience ? serviceMethod.Parameters : operation.Parameters; ModelProvider? spreadSource = null; - if (methodType == ScmMethodProvider.MethodType.Convenience) + if (methodType == ScmMethodKind.Convenience) { InputParameter? inputOperationSpreadParameter = operation.Parameters.FirstOrDefault(p => p.Scope.HasFlag(InputParameterScope.Spread)); spreadSource = inputOperationSpreadParameter != null @@ -817,11 +817,11 @@ internal static List GetMethodParameters(InputServiceMethod s continue; } - if (methodType is ScmMethodProvider.MethodType.Protocol or ScmMethodProvider.MethodType.CreateRequest) + if (methodType is ScmMethodKind.Protocol or ScmMethodKind.CreateRequest) { if (inputParam is InputBodyParameter) { - if (methodType == ScmMethodProvider.MethodType.CreateRequest) + if (methodType == ScmMethodKind.CreateRequest) { parameter = ScmKnownParameters.RequestContent; } @@ -837,7 +837,7 @@ internal static List GetMethodParameters(InputServiceMethod s parameter.Type = parameter.Type.IsEnum ? parameter.Type.UnderlyingEnumType : parameter.Type; } } - else if (methodType is ScmMethodProvider.MethodType.Convenience && + else if (methodType is ScmMethodKind.Convenience && spreadSource != null && inputParam is InputMethodParameter inputMethodParameter && inputMethodParameter.Location == InputRequestLocation.Body) @@ -876,7 +876,7 @@ internal static List GetMethodParameters(InputServiceMethod s sortedParams.Add(bodyRequired++, ScmKnownParameters.ContentType); } - if (methodType == ScmMethodProvider.MethodType.CreateRequest) + if (methodType == ScmMethodKind.CreateRequest) { // All the parameters should be required for the CreateRequest method foreach (var parameter in sortedParams.Values) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodKind.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodKind.cs new file mode 100644 index 00000000000..005e0b9f2d1 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodKind.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.TypeSpec.Generator.ClientModel.Providers +{ + /// + /// Defines the different types of methods that can be generated by the SCM (Service Client Model) generator. + /// + public enum ScmMethodKind + { + /// + /// Internal method that creates HTTP request messages for protocol methods. + /// These methods are typically used internally by protocol methods to construct HTTP requests. + /// + CreateRequest, + + /// + /// Protocol method that handles raw HTTP requests and responses. + /// These methods provide low-level access to HTTP operations with minimal abstraction. + /// + Protocol, + + /// + /// Convenience method with strongly-typed parameters and return values. + /// These methods provide a high-level, developer-friendly API with strong typing. + /// + Convenience + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProvider.cs index 91afb297c10..fc4847b10e6 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProvider.cs @@ -11,52 +11,19 @@ namespace Microsoft.TypeSpec.Generator.ClientModel.Providers { public class ScmMethodProvider : MethodProvider { - public enum MethodType - { - /// - /// Internal method that creates HTTP request messages. - /// - CreateRequest, - /// - /// Protocol method that handles raw requests and responses. - /// - Protocol, - /// - /// Convenience method with strongly-typed parameters and return values. - /// - Convenience - } public InputServiceMethod? ServiceMethod { get; } public TypeProvider? CollectionDefinition { get; } /// - /// Gets the method type (CreateRequest, Protocol, or Convenience). - /// - public MethodType Type { get; } - - /// - /// Gets a value indicating whether this method is a CreateRequest method. - /// CreateRequest methods are internal methods that create HTTP messages for protocol methods. - /// - public bool IsCreateRequestMethod => Type == MethodType.CreateRequest; - - /// - /// Gets a value indicating whether this method is a protocol method. - /// Protocol methods handle raw requests and responses. - /// - public bool IsProtocolMethod => Type == MethodType.Protocol; - - /// - /// Gets a value indicating whether this method is a convenience method. - /// Convenience methods provide strongly-typed parameters and return types. + /// Gets the kind of method (CreateRequest, Protocol, or Convenience). /// - public bool IsConvenienceMethod => Type == MethodType.Convenience; + public ScmMethodKind Kind { get; } public ScmMethodProvider( MethodSignature signature, MethodBodyStatement bodyStatements, TypeProvider enclosingType, - MethodType methodType, + ScmMethodKind methodKind, XmlDocProvider? xmlDocProvider = default, TypeProvider? collectionDefinition = default, InputServiceMethod? serviceMethod = default) @@ -64,7 +31,7 @@ public ScmMethodProvider( { CollectionDefinition = collectionDefinition; ServiceMethod = serviceMethod; - Type = methodType; + Kind = methodKind; } } } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs index e98332a4a92..7089a0d2e4a 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs @@ -27,10 +27,11 @@ public class ScmMethodProviderCollection : IReadOnlyList { private readonly MethodProvider _createRequestMethod; private static readonly ClientPipelineExtensionsDefinition _clientPipelineExtensionsDefinition = new(); - private IList ProtocolMethodParameters => _protocolMethodParameters ??= RestClientProvider.GetMethodParameters(ServiceMethod, ScmMethodProvider.MethodType.Protocol); + private static readonly CancellationTokenExtensionsDefinition _cancellationTokenExtensionsDefinition = new(); + private IList ProtocolMethodParameters => _protocolMethodParameters ??= RestClientProvider.GetMethodParameters(ServiceMethod, ScmMethodKind.Protocol); private IList? _protocolMethodParameters; - private IReadOnlyList ConvenienceMethodParameters => _convenienceMethodParameters ??= RestClientProvider.GetMethodParameters(ServiceMethod, ScmMethodProvider.MethodType.Convenience); + private IReadOnlyList ConvenienceMethodParameters => _convenienceMethodParameters ??= RestClientProvider.GetMethodParameters(ServiceMethod, ScmMethodKind.Convenience); private IReadOnlyList? _convenienceMethodParameters; private readonly InputPagingServiceMethod? _pagingServiceMethod; private IReadOnlyList? _methods; @@ -159,7 +160,7 @@ .. GetStackVariablesForReturnValueConversion(result, responseBodyType, isAsync, ]; } - var convenienceMethod = new ScmMethodProvider(methodSignature, methodBody, EnclosingType, ScmMethodProvider.MethodType.Convenience, collectionDefinition: collection, serviceMethod: ServiceMethod); + var convenienceMethod = new ScmMethodProvider(methodSignature, methodBody, EnclosingType, ScmMethodKind.Convenience, collectionDefinition: collection, serviceMethod: ServiceMethod); if (convenienceMethod.XmlDocs != null) { @@ -652,7 +653,7 @@ private ScmMethodProvider BuildProtocolMethod(MethodProvider createRequestMethod } var protocolMethod = - new ScmMethodProvider(methodSignature, methodBody, EnclosingType, ScmMethodProvider.MethodType.Protocol, collectionDefinition: collection, serviceMethod: ServiceMethod); + new ScmMethodProvider(methodSignature, methodBody, EnclosingType, ScmMethodKind.Protocol, collectionDefinition: collection, serviceMethod: ServiceMethod); if (protocolMethod.XmlDocs != null) { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs index 419cb2b82c4..550c91cc461 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs @@ -104,7 +104,7 @@ public void ValidateProperties() [TestCaseSource(nameof(GetMethodParametersTestCases))] public void TestGetMethodParameters(InputServiceMethod inputServiceMethod) { - var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodProvider.MethodType.Convenience); + var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodKind.Convenience); Assert.IsTrue(methodParameters.Count > 0); @@ -139,7 +139,7 @@ public void TestGetMethodParameters(InputServiceMethod inputServiceMethod) [TestCase] public void TestGetMethodParameters_ProperOrdering() { - var methodParameters = RestClientProvider.GetMethodParameters(ServiceMethodWithMixedParamOrdering, ScmMethodProvider.MethodType.Convenience); + var methodParameters = RestClientProvider.GetMethodParameters(ServiceMethodWithMixedParamOrdering, ScmMethodKind.Convenience); Assert.AreEqual(ServiceMethodWithMixedParamOrdering.Parameters.Count, methodParameters.Count); @@ -152,7 +152,7 @@ public void TestGetMethodParameters_ProperOrdering() Assert.AreEqual("optionalHeader", methodParameters[5].Name); Assert.AreEqual("optionalContentType", methodParameters[6].Name); - var orderedPathParams = RestClientProvider.GetMethodParameters(ServiceMethodWithOnlyPathParams, ScmMethodProvider.MethodType.Convenience); + var orderedPathParams = RestClientProvider.GetMethodParameters(ServiceMethodWithOnlyPathParams, ScmMethodKind.Convenience); Assert.AreEqual(ServiceMethodWithOnlyPathParams.Parameters.Count, orderedPathParams.Count); Assert.AreEqual("c", orderedPathParams[0].Name); Assert.AreEqual("a", orderedPathParams[1].Name); @@ -185,7 +185,7 @@ public void HeaderParameterOptionality(bool isRequired, bool isValueType) "TestClient", methods: [testServiceMethod]); var clientProvider = new ClientProvider(client); - var parameters = RestClientProvider.GetMethodParameters(testServiceMethod, ScmMethodProvider.MethodType.Convenience); + var parameters = RestClientProvider.GetMethodParameters(testServiceMethod, ScmMethodKind.Convenience); Assert.IsNotNull(parameters); if (isRequired) @@ -705,7 +705,7 @@ public void TestReadOnlyParameters_FilteredFromProtocolMethod() InputFactory.MethodParameter("normalBody", InputPrimitiveType.Boolean, isRequired: false, location: InputRequestLocation.Body) ]); - var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodProvider.MethodType.Protocol); + var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodKind.Protocol); // Verify read-only parameters are filtered out Assert.IsFalse(methodParameters.Any(p => p.Name == "readOnlyPath")); @@ -737,7 +737,7 @@ public void TestReadOnlyParameters_FilteredFromConvenienceMethod() InputFactory.MethodParameter("normalHeader", InputPrimitiveType.Boolean, isRequired: false, location: InputRequestLocation.Header) ]); - var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodProvider.MethodType.Convenience); + var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodKind.Convenience); // Verify read-only parameters are filtered out Assert.IsFalse(methodParameters.Any(p => p.Name == "readOnlyQuery")); @@ -773,7 +773,7 @@ public void TestReadOnlyParameters_WithMixedParameterTypes() InputFactory.MethodParameter("normalBody", InputPrimitiveType.Boolean, isRequired: false, location: InputRequestLocation.Body) ]); - var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodProvider.MethodType.Convenience); + var methodParameters = RestClientProvider.GetMethodParameters(inputServiceMethod, ScmMethodKind.Convenience); Assert.AreEqual(4, methodParameters.Count); // Only non-readonly parameters Assert.IsTrue(methodParameters.Any(p => p.Name == "normalPath")); diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs index a9f9cf52ca0..b51d02ab8cb 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs @@ -1086,33 +1086,16 @@ public void TestMethodTypeIdentification() var methodCollection = new ScmMethodProviderCollection(inputServiceMethod, client!); // Verify protocol methods - var protocolMethods = methodCollection.Where(m => ((ScmMethodProvider)m).IsProtocolMethod).ToList(); + var protocolMethods = methodCollection.Where(m => ((ScmMethodProvider)m).Kind == ScmMethodKind.Protocol).ToList(); Assert.AreEqual(2, protocolMethods.Count); // sync + async - foreach (ScmMethodProvider method in protocolMethods) - { - Assert.IsTrue(method.IsProtocolMethod); - Assert.IsFalse(method.IsConvenienceMethod); - Assert.IsFalse(method.IsCreateRequestMethod); - Assert.AreEqual(ScmMethodProvider.MethodType.Protocol, method.Type); - } // Verify convenience methods - var convenienceMethods = methodCollection.Where(m => ((ScmMethodProvider)m).IsConvenienceMethod).ToList(); + var convenienceMethods = methodCollection.Where(m => ((ScmMethodProvider)m).Kind == ScmMethodKind.Convenience).ToList(); Assert.AreEqual(2, convenienceMethods.Count); // sync + async - foreach (ScmMethodProvider method in convenienceMethods) - { - Assert.IsFalse(method.IsProtocolMethod); - Assert.IsTrue(method.IsConvenienceMethod); - Assert.IsFalse(method.IsCreateRequestMethod); - Assert.AreEqual(ScmMethodProvider.MethodType.Convenience, method.Type); - } // Verify CreateRequest method var createRequestMethod = (ScmMethodProvider)client!.RestClient.GetCreateRequestMethod(inputOperation); - Assert.IsFalse(createRequestMethod.IsProtocolMethod); - Assert.IsFalse(createRequestMethod.IsConvenienceMethod); - Assert.IsTrue(createRequestMethod.IsCreateRequestMethod); - Assert.AreEqual(ScmMethodProvider.MethodType.CreateRequest, createRequestMethod.Type); + Assert.AreEqual(ScmMethodKind.CreateRequest, createRequestMethod.Kind); } } } From 3819769e9a8abbc0798234c15175d3f6c04a73bb Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Thu, 30 Oct 2025 10:05:53 -0700 Subject: [PATCH 5/5] minor: comment change --- .../src/Providers/ScmMethodKind.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodKind.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodKind.cs index 005e0b9f2d1..3319facdb46 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodKind.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodKind.cs @@ -4,7 +4,7 @@ namespace Microsoft.TypeSpec.Generator.ClientModel.Providers { /// - /// Defines the different types of methods that can be generated by the SCM (Service Client Model) generator. + /// Defines the different Kinds of methods that can be generated by the SCM (System Client Model) generator. /// public enum ScmMethodKind {