Skip to content

fix(http-server-csharp): fix model file name when @friendlyName contains unresolved template placeholders - #11459

Closed
abatishchev with Copilot wants to merge 5 commits into
mainfrom
copilot/http-server-csharp-bug-fix-name-tags-update
Closed

fix(http-server-csharp): fix model file name when @friendlyName contains unresolved template placeholders#11459
abatishchev with Copilot wants to merge 5 commits into
mainfrom
copilot/http-server-csharp-bug-fix-name-tags-update

Conversation

Copilot AI commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

When @friendlyName stores a format string with {paramName} placeholders that weren't substituted (e.g. {name}TagsUpdate), the generated file was named {name}TagsUpdate.cs while the class inside was correctly named NameTagsUpdate — a discrepancy caused by the class name going through pascalCase() (which treats {/} as word separators) while the file path used the raw string.

Changes

  • src/components/models/model-helpers.ts — In getModelEmitName, sanitize the @friendlyName return value by replacing {paramName} placeholders with their PascalCase equivalents before using the name as a file path:

    return friendlyName.replace(/\{(\w+)\}/g, (_, n) => n.charAt(0).toUpperCase() + n.slice(1));

    {name}TagsUpdateNameTagsUpdate.cs, matching the emitted class name.

  • test/generation.test.ts — Regression test: verifies that a model decorated with @friendlyName("{name}TagsUpdate") produces NameTagsUpdate.cs with no literal {name} in the output path.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI changed the title [WIP] Fix model file naming for NameTagsUpdate fix(http-server-csharp): fix model file name when @friendlyName contains unresolved template placeholders Jul 29, 2026
Copilot AI requested a review from abatishchev July 29, 2026 22:06
@abatishchev
abatishchev marked this pull request as ready for review July 29, 2026 22:12
@pkg-pr-new

pkg-pr-new Bot commented Jul 29, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 6f90881

@azure-sdk-automation

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

Comment thread packages/http-server-csharp/src/components/models/model-helpers.ts
Copilot AI and others added 2 commits July 29, 2026 16:57
… in model file names

Co-authored-by: abatishchev <351644+abatishchev@users.noreply.github.com>
… is a TemplateParameter

When `@friendlyName` is applied to a template model with a template parameter
as the sourceObject (e.g., `@friendlyName("{name}TagsUpdate", T)` on `Model<T>`),
the decorator is called on the template declaration with `sourceObject` being a
`TemplateParameter`. In that case, `replaceTemplatedStringFromProperties` leaves
the `{name}` placeholders unresolved in the stored friendly name.

Fix: in `$friendlyName`, return early when `sourceObject.kind === "TemplateParameter"`
rather than storing an unresolved format string. The decorator is re-applied when the
template is instantiated with a concrete type, which correctly resolves the placeholders.

Also:
- Revert the downstream workaround in `getModelEmitName` in http-server-csharp
- Update the http-server-csharp test to use the actual ARM-style template pattern
- Add a compiler test verifying template declarations don't get unresolved friendly names

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
@abatishchev
abatishchev force-pushed the copilot/http-server-csharp-bug-fix-name-tags-update branch from a7939a0 to dfd71f3 Compare July 29, 2026 23:57
@github-actions

github-actions Bot commented Jul 30, 2026

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.

Comment thread packages/compiler/src/lib/decorators.ts Outdated
Copilot AI and others added 2 commits July 30, 2026 00:26
Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
Add a safety net in `applyDecoratorToType` (checker.ts) that skips running
a decorator when any of its arguments is an unresolved `TemplateParameter` or
`TemplateParameterAccess`. The checker already ensures decorators are not
applied to template declarations via `skipDecorators: true`, but this explicit
guard at the call site makes the protection robust and self-documenting.

Also:
- Revert the incorrect guard from `decorators.ts` (wrong layer)
- Revert the `getModelEmitName` sanitization workaround (not needed)
- Update test description in `decorators.test.ts` to accurately reflect
  the mechanism (skipDecorators, not a guard in the decorator itself)
- Update the `generation.test.ts` test to use the real ARM-style pattern

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
…defaults

Operations resolved template parameter defaults before entering the
template declaration scope, unlike models/interfaces. A decorated
template used as a 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.

Move the InTemplateDeclaration flag before checkTemplateDeclaration in
checkOperation and drop the applyDecoratorToType band-aid guard.

Fixes #11454
@timotheeguerin

Copy link
Copy Markdown
Member

Superseded by #11477, which contains only the root-cause compiler fix (operations now enter the template declaration scope before resolving template parameter defaults, so decorators no longer run with unresolved template parameters). This PR had diverged from its original purpose across several earlier attempts, so closing in favor of the clean replacement.

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

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

3 participants