Skip to content

Fix C# back-compat service method overloads for reserved param names; skip overload when previous method ends in CancellationToken#10642

Open
Copilot wants to merge 6 commits into
mainfrom
copilot/fix-reserved-param-names
Open

Fix C# back-compat service method overloads for reserved param names; skip overload when previous method ends in CancellationToken#10642
Copilot wants to merge 6 commits into
mainfrom
copilot/fix-reserved-param-names

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 11, 2026

Back-compat overloads generated for service methods (added in 72a95c2) produced uncompilable C# when previous parameters had raw input names that are not valid C# identifiers (e.g. OData query parameters such as $select, $top, $skip, $count). They also could not be emitted correctly when the previous method ended in a CancellationToken parameter — making CT optional introduces a CS0121 ambiguity at basic call sites with the new method, and making CT required violates the SDK guideline that CancellationToken parameters must be optional.

Changes

  • ClientProvider.BuildBackCompatOverloadForNewOptionalParameters — emit named-argument labels using the C# variable name (select:, top:) rather than the raw input name ($select:, $top:). Match previous→current parameters by ToVariableName() so renames that differ only by reserved characters still align.
  • ClientProvider.ProcessBackCompatForNewOptionalParameters — skip generating the back-compat overload entirely when the previous method's trailing parameter is a CancellationToken. In that case the library author must address the gap via custom code or by updating the spec.
  • Tests — updated the four existing back-compat baselines to reflect the skip behavior (their previous methods all ended in CancellationToken). The previously added BackCompatibility_NewOptionalParameterWithReservedName test was removed because its scenario also ends in CancellationToken and is now skipped.

Example (reserved-name fix, applies when an overload IS emitted)

Before:

[EditorBrowsable(EditorBrowsableState.Never)]
public virtual AsyncPageable<SearchIndexResponse> GetIndexesWithSelectedPropertiesAsync(
    IEnumerable<string> @select, CancellationToken cancellationToken)
{
    return this.GetIndexesWithSelectedPropertiesAsync(
        $select: default, $top: default, $skip: default, $count: default,
        cancellationToken: cancellationToken);
}

After:

[EditorBrowsable(EditorBrowsableState.Never)]
public virtual AsyncPageable<SearchIndexResponse> GetIndexesWithSelectedPropertiesAsync(
    IEnumerable<string> @select, CancellationToken cancellationToken)
{
    return this.GetIndexesWithSelectedPropertiesAsync(
        select: default, top: default, skip: default, count: default,
        cancellationToken: cancellationToken);
}

Note

For the original OData scenario (previous method ends in CancellationToken), no back-compat overload is now emitted at all, so the buggy generated C# can no longer occur. The reserved-name fix in BuildBackCompatOverloadForNewOptionalParameters is retained as defensive correctness for any future scenario where a back-compat overload is still emitted.

… preserve optional CancellationToken

Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/09ec7e5f-2d2f-4a58-8662-7d148879bb09

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@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 May 11, 2026
… on non-trailing params

Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/09ec7e5f-2d2f-4a58-8662-7d148879bb09

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix generated back compat service methods for reserved param names Fix C# back-compat service method overloads for reserved param names and CancellationToken May 11, 2026
Copilot AI requested a review from jorgerangel-msft May 11, 2026 19:51
Comment thread packages/http-client-csharp/generator/docs/backward-compatibility.md Outdated
…; use testdata for new test

Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/3f9baf01-88a8-4b30-a7ca-d0a5b5897fe4

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Copilot AI changed the title Fix C# back-compat service method overloads for reserved param names and CancellationToken Fix C# back-compat service method overloads for reserved param names May 11, 2026
Copilot AI requested a review from jorgerangel-msft May 11, 2026 20:13
Copilot AI changed the title Fix C# back-compat service method overloads for reserved param names Fix C# back-compat service method overloads for reserved param names; skip overload when previous method ends in CancellationToken May 11, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 11, 2026

Open in StackBlitz

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

commit: 712dd5a

@JonathanCrd JonathanCrd marked this pull request as ready for review May 11, 2026 23:50
Copy link
Copy Markdown
Contributor

@jorgerangel-msft jorgerangel-msft left a comment

Choose a reason for hiding this comment

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

Can we also please get a regen preview? It might also be worth running the debug profile script against Azure/azure-sdk-for-net#59156 to verify the changes

// before it).
// - Making the trailing CancellationToken required avoids the ambiguity but violates the
// SDK guideline that CancellationToken parameters must be optional.
// In this case the library author must address the gap via custom code or by updating the spec.
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.

nit: do we need such a long explanation? The log message seems self explanatory 😃

}

var lastParam = previousSignature.Parameters[previousSignature.Parameters.Count - 1];
return lastParam.Type.Equals(typeof(CancellationToken));
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.

should we ignore nullability as well?

// Match parameters by their C# variable name (which is what is rendered in C# source) so
// that previous parameters whose raw input name differs only by reserved characters such as
// a leading '$' (e.g. OData "$select"/"$top") are matched to the corresponding current
// parameter. The named-argument label below must also use the C# variable name.
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.

Copilot had added tests for this, then undid them. It would be great if we can add those back in or add new unit tests exercising this scenario

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.

Generated Back Compat Service Methods Do Not Compile If Params Have Reserved Names

3 participants