[http-client-csharp] Serialize enum options-bag properties when protocol flattens them to string - #11488
Conversation
…col flattens them to string When an `@@override` groups parameters into an options-bag model, the generated convenience method delegates to the protocol method by reading each argument off the options model (`options.Foo`). If an options property is an enum/union but the protocol method flattens that parameter to its serialized form (e.g. `string`), the delegation passed the enum directly, producing code that does not compile. The non-grouped convenience path already serializes enums via `convenienceParam.Type.ToSerial(...)`. The grouped (MethodParameterSegments) path built a raw property-access expression and skipped that conversion. `ModelProviderSnippets.GetPropertyExpression` now optionally returns the leaf `PropertyProvider`, and `GetProtocolMethodArguments` serializes the leaf when it is an enum and the protocol parameter is not (applying a null-conditional first when the property is nullable), mirroring the non-grouped path. The generated body now emits e.g. `options.Resampling?.ToString()`. Added `MethodParameterSegments_EnumGroupedQueryParam_SerializesToProtocol`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b564000b-729c-4371-b5c4-8ce14462cee9
commit: |
|
No changes needing a change description found. |
There was a problem hiding this comment.
Pull request overview
Fixes a C# http-client-csharp generator compilation issue where options-bag convenience methods could forward an enum-typed options property directly into a protocol parameter that had been flattened to its serialized primitive type (e.g., string), by applying the same enum-to-serial conversion used in the non-grouped path.
Changes:
- Add a
ModelProviderSnippets.GetPropertyExpressionoverload that also returns the resolved leafPropertyProviderfor type inspection. - Update grouped-parameter forwarding (
ScmMethodProviderCollection.GetProtocolMethodArguments) to serialize enum leaf properties when the protocol parameter is non-enum, including?.handling for nullable enums. - Add a regression test + expected output fixture covering enum options-bag forwarding to a flattened protocol
stringparameter.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Snippets/ModelProviderSnippets.cs | Adds a GetPropertyExpression overload returning the leaf PropertyProvider so callers can apply type-based conversions. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs | Serializes grouped options-bag enum leaf properties when protocol parameters are flattened to non-enum types. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs | Adds a regression test asserting enum-to-string serialization occurs for grouped query params. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/MethodParameterSegments_EnumGroupedQueryParam_SerializesToProtocol.cs | Expected method-body output fixture validating the emitted forwarding expression. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b564000b-729c-4371-b5c4-8ce14462cee9
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs:930
- When serializing an enum options-bag property for a flattened protocol parameter, the null-conditional is only applied when the leaf property type is nullable. For nested segment paths (MethodParameterSegments.Count > 2), GetPropertyExpression will emit a null-conditional during navigation (e.g.
options.Inner?.Resampling), which makes the overall expression nullable even if the leaf enum is non-nullable. Without adding a null-conditional here, the generated code becomesoptions.Inner?.Resampling.ToString(), which callsNullable<T>.ToString()and produces an empty string whenInneris null instead of forwardingnull(and may incorrectly send a query value).
if (leafProperty.Type.IsNullable)
{
propertyExpression = propertyExpression.NullConditional();
}
propertyExpression = leafProperty.Type.ToSerial(propertyExpression);
Problem
When an
@@overridegroups operation parameters into an options-bag model, the generated convenience method delegates to the protocol method by reading each argument off the options model (options.Foo). If an options property is an enum/union but the protocol method flattens that parameter to its serialized form (e.g.string), the delegation passed the enum value directly where astringis expected — so the generated code does not compile.The non-grouped convenience path already handles this: for an enum convenience parameter it emits
convenienceParam.Type.ToSerial(...)(e.g.foo?.ToString()). The grouped path — which resolves arguments throughMethodParameterSegments(introduced in #11238) — built a raw property-access expression and skipped that conversion.Before
After
Fix
ModelProviderSnippets.GetPropertyExpressiongains an overload that also returns the leafPropertyProvider, so callers can inspect the resolved property's type.ScmMethodProviderCollection.GetProtocolMethodArgumentsserializes the leaf in the grouped path when it is an enum and the protocol parameter is not — applying a null-conditional first when the property is nullable — mirroring the non-grouped path'sToSerialbehavior. Non-enum properties are unchanged.Tests
MethodParameterSegments_EnumGroupedQueryParam_SerializesToProtocol(validated against aTestDataexpected file) — reproduces the missing conversion without the fix, passes with it.Microsoft.TypeSpec.Generator.ClientModel(1539) andMicrosoft.TypeSpec.Generator(1781) suites pass.