Skip to content

[Mgmt] Add 'resource-name' client option on Read operation#59335

Open
haiyuazhang wants to merge 4 commits into
Azure:mainfrom
haiyuazhang:haiyzhan/mgmt-resource-name-on-readop
Open

[Mgmt] Add 'resource-name' client option on Read operation#59335
haiyuazhang wants to merge 4 commits into
Azure:mainfrom
haiyuazhang:haiyzhan/mgmt-resource-name-on-readop

Conversation

@haiyuazhang
Copy link
Copy Markdown
Member

Summary

Introduces a new resource-name clientOption key, anchored on the ARM resource Read operation, to override the generated SDK resource class names. Supersedes the model-keyed resource-name-mappings design from #59282 per @ArcturusZhang's review feedback.

Decorator surface

Plain rename (ordinary resource):

@@clientOption(FooSettingsOperations.get, "resource-name", "FooConfiguration", "csharp");

Per-parent rename (expandable {parentType} resource):

@@clientOption(EventGridPrivateEndpointConnections.get, "resource-name",
  #{ eventGridTopics: "EventGridTopicPrivateEndpointConnection",
     eventGridDomains: "EventGridDomainPrivateEndpointConnection" },
  "csharp");

Map keys are the enum values substituted for {parentType} (TypeSpec record literal keys must be identifiers).

Implementation notes

  • New helpers extractResourceNameOverride / applyResourceNameOverrides / findReadMethod in resource-metadata.ts.
  • ResourceMetadata.expansionTypeValue records the enum value that was substituted for {parentType} per expanded resource — that's the override lookup key.
  • Override pass runs as the final step in both buildArmProviderSchema (legacy) and resolveArmResources (modern) detection paths.
  • Passes the TCGC SdkMethod (a DecoratedType) to getClientOptions; not __raw (TypeSpec Operation does not satisfy DecoratedType).
  • Diagnostics: empty value, string-on-expandable misuse, unknown map keys, post-rename name collisions.

Test coverage

  • 4 new emitter unit tests (plain rename, expandable map, unused-key diagnostic, string-on-expandable diagnostic). All 133 emitter tests pass.
  • Mgmt-TypeSpec project exercises both forms end-to-end:
    • foo.tsp: FooSettings*FooConfiguration*.
    • routedoperations.tsp: per-parent rename of EventGrid private endpoint connection.
  • Mgmt-TypeSpec dotnet build clean, regen clean.

Related

Introduce a new 'resource-name' clientOption key, anchored on the ARM
resource Read operation, to override the generated SDK resource class
names. Supports two value forms:

- string: plain rename for an ordinary (single-resource) Read op, e.g.
    @@clientoption(FooOps.get, "resource-name", "FooConfiguration", "csharp");

- Record<enumValue, string>: per-parent-type rename for an expandable
  '{parentType}' Read op. Keys are the enum values substituted for
  '{parentType}' (TypeSpec record literal keys must be identifiers):
    @@clientoption(PrivateEndpointConnections.get, "resource-name",
      #{ eventGridTopics: "EventGridTopicPrivateEndpointConnection",
         eventGridDomains: "EventGridDomainPrivateEndpointConnection" },
      "csharp");

The override is applied as a final pass over detected ARM resources in
both the legacy 'buildArmProviderSchema' and the modern
'resolveArmResources' paths, after parent inference and {parentType}
expansion. Diagnostics are emitted for empty values, string-on-
expandable misuse, unknown map keys, and post-rename name collisions.

Mgmt-TypeSpec test project exercises both forms end-to-end:
- foo.tsp: FooSettings -> FooConfiguration (plain string).
- routedoperations.tsp: per-parent rename for EventGridPrivateEndpointConnection.

Adds 4 emitter unit tests; documentation in docs/client-options.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 19, 2026 12:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a new resource-name @@clientOption (anchored on an ARM resource Read operation) to override generated C# resource class-name roots, including support for expandable {parentType} resources via a per-enum-value map.

Changes:

  • Implemented resource-name override parsing and late-stage application in both legacy (buildArmProviderSchema) and modern (resolveArmResources) detection paths.
  • Added unit tests covering plain rename, expandable map rename, and diagnostics for misuse/unused keys.
  • Updated Mgmt-TypeSpec test project inputs/outputs and added docs describing the new client option.

Reviewed changes

Copilot reviewed 8 out of 22 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/tspCodeModel.json Updates expected codemodel decorators/metadata to reflect resource-name overrides.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/Models/AzureGeneratorMgmtTypeSpecTestsContext.cs Updates buildable model registrations to renamed resource types.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/FooSettingsResource.cs Regenerates resource type with overridden name (FooConfigurationResource).
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/FooSettingsResource.Serialization.cs Regenerates serialization partial for renamed Foo resource type.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/Extensions/MockableAzureGeneratorMgmtTypeSpecTestsResourceGroupResource.cs Updates mockable extension surface for renamed Foo resource accessor.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/Extensions/MockableAzureGeneratorMgmtTypeSpecTestsArmClient.cs Updates mockable ArmClient helpers for renamed Foo/EventGrid expanded resources.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/Extensions/AzureGeneratorMgmtTypeSpecTestsExtensions.cs Updates public extension methods to match renamed resource types and mockable targets.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/EventGridTopicResource.cs Updates collection/resource accessors to renamed expanded PEC types.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/EventGridTopicEventGridPrivateEndpointConnectionResource.cs Regenerates expanded PEC resource type name for Topic parent.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/EventGridTopicEventGridPrivateEndpointConnectionResource.Serialization.cs Regenerates serialization partial for expanded PEC resource (Topic/Domain).
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/EventGridTopicEventGridPrivateEndpointConnectionCollection.cs Regenerates expanded PEC collection type name for Topic parent.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/EventGridDomainResource.cs Updates collection/resource accessors to renamed expanded PEC types.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/EventGridDomainEventGridPrivateEndpointConnectionResource.cs Regenerates expanded PEC resource type name for Domain parent.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/EventGridDomainEventGridPrivateEndpointConnectionResource.Serialization.cs Regenerates serialization partial for expanded PEC resource (Topic/Domain).
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/src/Generated/EventGridDomainEventGridPrivateEndpointConnectionCollection.cs Regenerates expanded PEC collection type name for Domain parent.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/routedoperations.tsp Adds @@clientOption(..., "resource-name", #{...}) example for expandable {parentType} resource.
eng/packages/http-client-csharp-mgmt/generator/TestProjects/Local/Mgmt-TypeSpec/foo.tsp Adds @@clientOption(..., "resource-name", "FooConfiguration") example for plain rename.
eng/packages/http-client-csharp-mgmt/emitter/test/resource-detection.test.ts Adds 4 unit tests validating override behavior and diagnostics.
eng/packages/http-client-csharp-mgmt/emitter/src/resource-metadata.ts Introduces override parsing/apply helpers and tracks expansion enum value for lookup.
eng/packages/http-client-csharp-mgmt/emitter/src/resource-detection.ts Applies overrides as a final step in legacy resource detection.
eng/packages/http-client-csharp-mgmt/emitter/src/resolve-arm-resources-converter.ts Applies overrides as a final step in modern resource detection.
eng/packages/http-client-csharp-mgmt/docs/client-options.md Documents the new resource-name client option and its supported forms.

Comment thread eng/packages/http-client-csharp-mgmt/docs/client-options.md
Comment thread eng/packages/http-client-csharp-mgmt/emitter/src/resource-metadata.ts Outdated
@github-actions github-actions Bot added CodeGen Issues that relate to code generation Mgmt This issue is related to a management package. labels May 19, 2026
…able Read op

When @@clientoption(op, "resource-name", #{...}, "csharp") is used on a
Read operation that does not produce expanded {parentType} resources, emit
a single, clearer diagnostic explaining the misuse instead of one
'unused entry' diagnostic per map key.

Adds a unit test asserting exactly one diagnostic fires and the
per-entry 'did not match any expanded resource' diagnostic is suppressed
in this case.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Member Author

@haiyuazhang haiyuazhang left a comment

Choose a reason for hiding this comment

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

Phase 1 versioning: passed/not applicable (no SDK package csproj, changelog, or ApiCompatBaseline changes). Phase 2 API review: no SDK package API surface changes; reviewed the mgmt emitter logic/tests and found one non-blocking diagnostic wording issue. Phase 3 ApiCompat: skipped because this PR does not change a released management package. Total inline comments: 1.

Comment thread eng/packages/http-client-csharp-mgmt/emitter/src/resource-metadata.ts Outdated
Comment thread eng/packages/http-client-csharp-mgmt/docs/client-options.md
Comment thread eng/packages/http-client-csharp-mgmt/emitter/src/resource-detection.ts Outdated
Comment thread eng/packages/http-client-csharp-mgmt/emitter/src/resource-metadata.ts Outdated
Address review comments on PR Azure#59335:
- Move resource-name application into legacy step 2 (expansion) instead
  of running it as a late post-pass.
- Remove the auxiliary expansionTypeValue field from ResourceMetadata;
  expansion now consumes the override map directly via
  ExpandArmResourcesOptions.resourceNameOverrides.
- Drop applyResourceNameOverrides / findReadMethod helpers and remove
  the call from resolve-arm-resources-converter.ts. Modern path no
  longer supports this clientOption (per offline agreement).
- Fix misuse diagnostic wording: Record<string, string> ->
  Record<enumValue, string>.
- Adjust unit tests to match the new flow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@haiyuazhang haiyuazhang force-pushed the haiyzhan/mgmt-resource-name-on-readop branch from 375d6ed to a148029 Compare May 20, 2026 06:46
Comment on lines +168 to +190
if (clientOptionOverride !== undefined) {
const isExpandable = detectDynamicTypeSegments(path).length > 0;
if (typeof clientOptionOverride === "string") {
if (isExpandable) {
reportWarning(
`@@clientOption(..., "resource-name", "${clientOptionOverride}", ...) is a plain string but its Read operation's path '${path.path}' contains a {parentType} segment (expandable). Use a Record<enumValue, string> map form instead.`
);
} else {
// Plain string override on an ordinary Read op. Folds into the
// existing explicit-name mechanism so it's applied uniformly with
// legacy decorators in step 3.
explicitResourceName = clientOptionOverride;
}
} else {
if (!isExpandable) {
reportWarning(
`@@clientOption(..., "resource-name", ...) value is a Record but its Read operation's path '${path.path}' does not contain a {parentType} segment (non-expandable). Use a plain string instead.`
);
} else {
resourceNameOverrideMap = clientOptionOverride;
}
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

could we move the diagnostic reporting when we are expanding the resources? this could make the code here more clear.

Copy link
Copy Markdown
Member Author

@haiyuazhang haiyuazhang May 20, 2026

Choose a reason for hiding this comment

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

Good call on cleaning this up. After investigating I went with a slightly different approach than relocating into expansion — relocating would force expandDynamicParentResourcesInSchema to know about the user-facing decorator's string-vs-map shape (and the map on non-expandable case wouldn't naturally enter the expansion loop, since non-expandable resources hit continue immediately), which felt like the wrong layering.

Instead I adopted the canonical TypeSpec $lib diagnostic pattern that's already used in this emitter (e.g. resource-model-not-associated-with-arm-resource). All six resource-name diagnostics added by this PR are now registered codes in lib/lib.ts with paramMessage templates:

  • resource-name-empty-string
  • resource-name-bad-entry
  • resource-name-empty-record
  • resource-name-bad-type
  • resource-name-string-on-expandable
  • resource-name-map-on-non-expandable

extractResourceNameOverride now takes program?: Program directly. Step 2a's two misuse diagnostics emit via $lib.reportDiagnostic directly, which collapses each call site from a multi-line template literal to ~5 lines, and message text now lives in the central catalog. Net result: the step-2a block is materially shorter and clearer, layering is preserved, and we have proper registered diagnostic codes (useful for future suppression rules and tooling).

Done in 01cefba.

Address ArcturusZhang's review comment on resource-detection.ts:190
(`could we move the diagnostic reporting when we are expanding the
resources? this could make the code here more clear`).

Rather than relocating diagnostics into expansion (which would force
expansion to know about the user-facing decorator's string-vs-map
shape), this commit adopts the canonical TypeSpec `\` diagnostic
pattern that's already used elsewhere in the emitter
(resource-model-not-associated-with-arm-resource, malformed-resource-
detected). The six resource-name diagnostics added by this PR are now
registered codes in lib/lib.ts with paramMessage templates:

  - resource-name-empty-string
  - resource-name-bad-entry
  - resource-name-empty-record
  - resource-name-bad-type
  - resource-name-string-on-expandable
  - resource-name-map-on-non-expandable

extractResourceNameOverride now takes `program?: Program` instead of
the free-form callback. Step 2a in resource-detection.ts emits the two
misuse diagnostics via \.reportDiagnostic directly, collapsing each
call site to ~5 lines and moving message text to the central catalog.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@haiyuazhang haiyuazhang force-pushed the haiyzhan/mgmt-resource-name-on-readop branch from c3da6fc to 01cefba Compare May 20, 2026 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CodeGen Issues that relate to code generation Mgmt This issue is related to a management package.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants