Skip to content

fix(compiler): enter template scope before resolving operation param defaults - #11477

Merged
iscai-msft merged 1 commit into
microsoft:mainfrom
timotheeguerin:timotheeguerin/fix-op-template-param-default-decorators
Jul 30, 2026
Merged

fix(compiler): enter template scope before resolving operation param defaults#11477
iscai-msft merged 1 commit into
microsoft:mainfrom
timotheeguerin:timotheeguerin/fix-op-template-param-default-decorators

Conversation

@timotheeguerin

Copy link
Copy Markdown
Member

Fixes #11454

Problem

checkOperation resolves template parameter defaults (via checkTemplateDeclaration) before entering the InTemplateDeclaration scope — unlike checkModelStatement and interface/union checks, which set the flag first.

As a result, when a decorated template is used as an operation template parameter default (the ARM tags-update pattern, e.g. op foo<Resource, Properties extends {} = TagsUpdateModel<Resource>>(...)), the default is instantiated with Resource still an unresolved TemplateParameter, and skipDecorators is false. The decorators on the default type (@friendlyName, @doc, …) therefore run with an unresolved template parameter argument and store unresolved {name} strings. In @typespec/http-server-csharp this surfaced as a model file named {name}TagsUpdate.cs instead of FooResourceTagsUpdate.cs.

A decorator should never run with a TemplateParameter argument — the real bug is the ordering, not the emitter.

Fix

In checkOperation, set CheckFlags.InTemplateDeclaration before calling checkTemplateDeclaration, mirroring checkModelStatement. Operations now enter the template declaration scope before resolving parameter defaults, so decorators on those defaults are no longer executed with the still-unresolved template parameter.

Tests

  • compiler: regression test using a custom @track decorator that records the kind of its argument. It asserts @track never runs with a TemplateParameter (only the concrete Model). Verified: fails before the fix, passes after.
  • http-server-csharp: integration test using the real operation default-arg pattern, asserting no emitted file name contains an unresolved {/} placeholder.

Background

This supersedes and replaces #11459, which had diverged from its original purpose and accumulated several earlier band-aid attempts. This PR contains only the root-cause compiler fix plus tests.

…defaults

Operations resolved template parameter defaults before entering the
template declaration scope, unlike models and interfaces. A decorated
template used as an operation parameter default (e.g. the ARM
`Properties = TagsUpdateModel<Resource>` pattern) therefore ran its
decorators with the still-unresolved template parameter, storing
unresolved `{name}` friendly names that leaked into emitted file names.

Move the InTemplateDeclaration flag before checkTemplateDeclaration in
checkOperation, matching checkModelStatement.

Fixes microsoft#11454
@pkg-pr-new

pkg-pr-new Bot commented Jul 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/compiler@11477
npm i https://pkg.pr.new/@typespec/http-server-csharp@11477

commit: 56074aa

@github-actions

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @typespec/compiler
Show changes

@typespec/compiler - fix ✏️

Fix decorators running with unresolved template parameters when a decorated template is used as a template parameter default of an operation (e.g. op foo<Resource, Properties = Decorated<Resource>>(...), the ARM TagsUpdateModel<Resource> pattern). Operations now enter the template declaration scope before resolving template parameter defaults, so decorators on those defaults are no longer executed with the still-unresolved template parameter. This matches the existing behavior for models and interfaces.

@typespec/http-server-csharp - fix ✏️

Fix model file name for @friendlyName ARM-style template patterns (e.g. @friendlyName("{name}TagsUpdate", Resource) on TagsUpdate<Resource>). The instantiation now correctly receives the substituted name (e.g. FooResourceTagsUpdate.cs) from the compiler.

@azure-sdk-automation

azure-sdk-automation Bot commented Jul 30, 2026

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

@timotheeguerin
timotheeguerin marked this pull request as ready for review July 30, 2026 13:44
@iscai-msft
iscai-msft added this pull request to the merge queue Jul 30, 2026
Merged via the queue into microsoft:main with commit 16caf10 Jul 30, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compiler:core Issues for @typespec/compiler int:azure-specs Run integration tests against azure-rest-api-specs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: http-server-csharp: Generated model file for NameTagsUpdate is {name}TagsUpdate.cs

2 participants