Skip to content

[wip] add naming normalization for dates - #11664

Draft
Jorge Rangel (jorgerangel-msft) wants to merge 27 commits into
mainfrom
jorgerangel-msft-fix-unbranded-date-suffixes
Draft

[wip] add naming normalization for dates#11664
Jorge Rangel (jorgerangel-msft) wants to merge 27 commits into
mainfrom
jorgerangel-msft-fix-unbranded-date-suffixes

Conversation

@jorgerangel-msft

@jorgerangel-msft Jorge Rangel (jorgerangel-msft) commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

@jorgerangel-msft Jorge Rangel (jorgerangel-msft) changed the title add acaornym naming for dates add naming normalization for dates Aug 13, 2026
@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp label Aug 13, 2026
@pkg-pr-new

pkg-pr-new Bot commented Aug 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-csharp@11664

commit: 05e8a3f

@github-actions

Copy link
Copy Markdown
Contributor

No changes needing a change description found.

@jorgerangel-msft Jorge Rangel (jorgerangel-msft) changed the title add naming normalization for dates [wip] add naming normalization for dates Aug 13, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces date/time naming normalization in the C# generator so *Time/*Date/*At/*Timestamp/*DateTime-suffixed date-like shapes are surfaced with an On suffix (and some noun adjustments like Creation* -> CreatedOn), while preserving wire names.

Changes:

  • Added NormalizeDateTimeSuffix(name, inputType) and applied it during property and method-parameter naming (when not IsExactName).
  • Updated generated sample output to rename CreatedAtCreatedOn while keeping the XML element name createdAt.
  • Added/updated unit tests and golden test data to validate the new naming behavior.

Reviewed changes

Copilot reviewed 9 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecModelFactory.cs Updates factory method parameter naming to createdOn to match new normalization.
packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/XmlAdvancedModel.Serialization.cs Switches serialization/deserialization to use CreatedOn while keeping wire element name createdAt.
packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/XmlAdvancedModel.cs Renames model property/ctor parameter from CreatedAt to CreatedOn.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/PropertyProviderTests.cs Adds coverage for property name normalization for date/time suffix patterns.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ParameterProviderTests.cs Adds coverage for method parameter name normalization for date/time suffix patterns.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Shared/CSharpNameExtensions.cs Implements the new NormalizeDateTimeSuffix and date/time type detection.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/PropertyProvider.cs Applies date/time suffix normalization before acronym normalization (when allowed).
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ParameterProvider.cs Applies date/time suffix normalization to non-exact method parameters.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/XmlSerializationTests.cs Updates assertions to reflect normalized property naming in generated XML serialization.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/XmlDeserializationTests.cs Updates assertions to reflect normalized property naming in generated XML deserialization.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/XmlSerializationTests/XmlSerializationHandlesNullableDateTimeOffsetProperty.cs Updates expected generated output for nullable DateTimeOffset serialization to use On.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/ModelReaderWriterValidation/TestProjects/Sample_TypeSpec/XmlAdvancedModelXmlTests.cs Updates validation to use CreatedOn after renaming.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot there's some issues I found when regenerating the azure libraries:

  • Azure.Compute.Batch BatchClient no longer passes in the requestDate param in several ops

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Copilot there's some issues I found when regenerating the [azure libraries](https://github.com/Azure/azure-sdk-for-net/pull/62202/changes#diff-6481de7a0feb164ee708af825b4648989fa868e33f5559e5efc15cb4...

Fixed the dropped requestDate argument in cb32d19.

Root cause: normalization was only applied to InputMethodParameter, so the convenience parameter became requestOn while the protocol/create-request parameter stayed requestDate. The convenience-to-protocol argument mapping is name-based, so the value was silently dropped from the generated call. Normalization now applies to all input parameters, so both surfaces use the same name and the argument is forwarded. Added a regression test (ConvenienceMethodForwardsNormalizedDateParameter).

Both C# generator suites pass (1962 core, 1572 ClientModel) and regenerating the Local/Spector test projects produces no diff.

If there was a second issue in your list (the bullet appears truncated), let me know and I'll address it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot pull latest from main and address merge conflicts

Copilot AI and others added 2 commits August 18, 2026 20:32
…unbranded-date-suffixes

# Conflicts:
#	packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ParameterProviderTests.cs
#	packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/PropertyProviderTests.cs

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Copilot pull latest from main and address merge conflicts

Merged the latest main in df07338. Conflicts were in ParameterProviderTests and PropertyProviderTests; both sides were kept, taking main's updated acronym casing expectations. All C# generator suites pass (1968 core, 1573 ClientModel, 177 Input).

@jorgerangel-msft

Copy link
Copy Markdown
Contributor Author

Copilot there's some issues I found when regenerating the [azure libraries](https://github.com/Azure/azure-sdk-for-net/pull/62202/changes#diff-6481de7a0feb164ee708af825b4648989fa868e33f5559e5efc15cb4...

Fixed the dropped requestDate argument in cb32d19.

Root cause: normalization was only applied to InputMethodParameter, so the convenience parameter became requestOn while the protocol/create-request parameter stayed requestDate. The convenience-to-protocol argument mapping is name-based, so the value was silently dropped from the generated call. Normalization now applies to all input parameters, so both surfaces use the same name and the argument is forwarded. Added a regression test (ConvenienceMethodForwardsNormalizedDateParameter).

Both C# generator suites pass (1962 core, 1572 ClientModel) and regenerating the Local/Spector test projects produces no diff.

If there was a second issue in your list (the bullet appears truncated), let me know and I'll address it.

Copilot there's still issues on regenerating the batch compute client https://github.com/Azure/azure-sdk-for-net/pull/62202/changes#diff-6481de7a0feb164ee708af825b4648989fa868e33f5559e5efc15cb4dbbcedf8. The etag params are now being generated individually, instead of the expected requestConditions type. In addition, there's several call sites where there's a diff in regards to passing args by name. This is unexpected

…enience calls

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Copilot there's some issues I found when regenerating the [azure libraries](https://github.com/Azure/azure-sdk-for-net/pull/62202/changes#diff-6481de7a0feb164ee708af825b4648989fa868e33f5559e5efc15...

Both symptoms trace back to the same root cause, which is already fixed on this branch by 28d2373 ("normalize date suffix for all input parameters").

Root cause: normalization was originally applied only to InputMethodParameter, so the convenience surface got requestOn while the protocol/create-request surface kept requestDate. ScmMethodProviderCollection maps convenience → protocol arguments by C# name, so the mismatch caused the date value to be dropped (requestDate: null) and forced every remaining argument to be passed by name. Azure's MatchConditionsHeadersVisitor only rewrites arguments that are raw variable expressions, so once the args became named it could no longer group ifMatch/ifModifiedSince/etc. into RequestConditions — which is exactly the second issue you saw.

Why the regen shows it: the regen commit in Azure/azure-sdk-for-net#62202 (f4c5691, 17:18Z) predates 28d2373 (18:28Z). Confirming evidence in the regenerated BatchClient.cs: requestOn appears only in convenience signatures (CancellationToken overloads) and never in protocol signatures (RequestContext overloads) — the exact pre-fix split.

Verification: I added BackCompatibility_DateParameterNameIsPreservedInConvenienceCall (ClientProviderTests), which builds an operation with a date header param requestDate plus an ifMatch header, restores the last-contract name, and validates both generated overloads against TestData:

public virtual ClientResult TestMethod(DateTimeOffset? requestDate, string ifMatch, RequestOptions options)
public virtual ClientResult TestMethod(DateTimeOffset? requestDate = default, string ifMatch = default, CancellationToken cancellationToken = default)
{
    return this.TestMethod(requestDate, ifMatch, cancellationToken.ToRequestOptions());
}

I confirmed this test reproduces your report when the pre-28d2373 condition is restored — it then generates this.TestMethod(requestDate: null, ifMatch: ifMatch, ...) — and passes on the current branch. Could you re-run the Azure regen against the latest branch to confirm on your side? Full suites pass: 1968 core, 1574 ClientModel.

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@jorgerangel-msft

Copy link
Copy Markdown
Contributor Author

Copilot pull the latest from main and address the merge conflicts

@jorgerangel-msft

Copy link
Copy Markdown
Contributor Author

regen preview: Azure/azure-sdk-for-net#62202

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Copilot pull the latest from main and address the merge conflicts

Merged the latest main in 357194c. The only conflict was in PropertyProviderTests.cs — kept the new date-suffix test alongside main's updated ipv4/ipv6 casing expectations. Both C# generator suites pass (1968 core, 1576 ClientModel).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot from testing, I'm seeing at least 1 library introducing a breaking change https://github.com/jorgerangel-msft/azure-sdk-for-net/blob/8b18010fc3d8a195003d54940df3d1cac29c656a/sdk/apimanagement/Azure.ResourceManager.ApiManagement/src/Generated/Models/ApiManagementSubscriptionPatch.cs.

The previous GA shape was :

public class ApiManagementSubscriptionPatch : IJsonModel<ApiManagementSubscriptionPatch>, IPersistableModel<ApiManagementSubscriptionPatch> { 
public ApiManagementSubscriptionPatch(); 
public bool? AllowTracing { get; set; }
public string DisplayName { get; set; }
public DateTimeOffset? ExpireOn { get; set; }
public string OwnerId { get; set; }
public string PrimaryKey { get; set; }
public string Scope { get; set; }
public string SecondaryKey { get; set; }
public SubscriptionState? State { get; set; }
public string StateComment { get; set; }
protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options); 
}

Yet ExpireOn was renamed

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Copilot from testing, I'm seeing at least 1 library introducing a breaking change https://github.com/jorgerangel-msft/azure-sdk-for-net/blob/8b18010fc3d8a195003d54940df3d1cac29c656a/sdk/apimanagement...

Fixed in 05e8a3f.

Root cause: ExpireOn was never the raw input name — it comes from the management generator's NameVisitor.DoPreVisitPropertyForTimePropertyName, which strips the Date/Time/DateTime/At suffix and then maps a few nouns to verb forms before appending On:

{"Creation", "Created"}, {"Deletion", "Deleted"}, {"Expiration", "Expire"}, {"Modification", "Modified"}

So ExpirationDateExpirationExpire + On = ExpireOn. With this PR, upstream normalization rewrote the name to ExpirationOn first, so the downstream rule no longer saw a Date suffix and left it as-is — hence the break.

Fix: NormalizeDateTimeSuffix now applies the same noun-to-verb map (matching the visitor's exact-prefix semantics, so AccountExpirationDate still becomes AccountExpirationOn), with casing preserved for camelCase parameter names (expirationDateexpireOn). ExpirationDate now normalizes to ExpireOn upstream, which matches the previously shipped name, and the management visitor becomes a no-op for these names.

Added test cases for all four mapped nouns plus the non-exact-prefix negative case. Core suite (1981) and ClientModel suite (1576) pass; no diff when regenerating the Local/Spector test projects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Complete deterministic date-time naming in the management generator

3 participants