From 9cfbb64f4686ce243573c9da0e3aac760b28d1d8 Mon Sep 17 00:00:00 2001 From: Mark Cowlishaw Date: Thu, 22 Jan 2026 18:39:59 -0800 Subject: [PATCH 1/2] Fix #3829 Allow @feature to apply to operations --- .chronus/changes/add-op-feature-2026-0-22-18-38-39.md | 7 +++++++ .chronus/changes/add-op-feature-2026-0-22-18-39-10.md | 7 +++++++ packages/typespec-autorest/test/arm/arm.test.ts | 7 +++++++ packages/typespec-azure-resource-manager/README.md | 2 +- .../generated-defs/Azure.ResourceManager.Legacy.ts | 2 +- .../lib/legacy-types/legacy.decorators.tsp | 2 +- packages/typespec-azure-resource-manager/src/resource.ts | 6 ++++-- .../azure-resource-manager/reference/decorators.md | 2 +- 8 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 .chronus/changes/add-op-feature-2026-0-22-18-38-39.md create mode 100644 .chronus/changes/add-op-feature-2026-0-22-18-39-10.md diff --git a/.chronus/changes/add-op-feature-2026-0-22-18-38-39.md b/.chronus/changes/add-op-feature-2026-0-22-18-38-39.md new file mode 100644 index 0000000000..6ba5a6f685 --- /dev/null +++ b/.chronus/changes/add-op-feature-2026-0-22-18-38-39.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@azure-tools/typespec-azure-resource-manager" +--- + +Fix #3829 Allow @feature to apply to Operations \ No newline at end of file diff --git a/.chronus/changes/add-op-feature-2026-0-22-18-39-10.md b/.chronus/changes/add-op-feature-2026-0-22-18-39-10.md new file mode 100644 index 0000000000..5cf3854af9 --- /dev/null +++ b/.chronus/changes/add-op-feature-2026-0-22-18-39-10.md @@ -0,0 +1,7 @@ +--- +changeKind: internal +packages: + - "@azure-tools/typespec-autorest" +--- + +Add Test for operation feature \ No newline at end of file diff --git a/packages/typespec-autorest/test/arm/arm.test.ts b/packages/typespec-autorest/test/arm/arm.test.ts index a2d361c5b6..f6b4b42bbf 100644 --- a/packages/typespec-autorest/test/arm/arm.test.ts +++ b/packages/typespec-autorest/test/arm/arm.test.ts @@ -634,6 +634,7 @@ enum Features { @Azure.ResourceManager.Legacy.feature(Features.FeatureB) @armResourceOperations interface Bars extends Azure.ResourceManager.TrackedResourceOperations {} + @@Azure.ResourceManager.Legacy.feature(Bars.get, Features.FeatureA); `, ["featureA", "featureB", "shared"], { preset: "azure" }, @@ -656,6 +657,12 @@ enum Features { expect(aFile.definitions["FooResourceUpdate"]).toBeDefined(); expect(aFile.definitions["FooResourceUpdateProperties"]).toBeDefined(); + expect( + aFile.paths[ + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Test/barResources/{barResourceName}" + ].get, + ).toBeDefined(); + expect(bFile.definitions).toBeDefined(); expect(bFile.definitions["BarResource"]).toBeDefined(); expect(bFile.definitions["BarResource"].properties["properties"].$ref).toBe( diff --git a/packages/typespec-azure-resource-manager/README.md b/packages/typespec-azure-resource-manager/README.md index caaebbaf57..8a52f9f8fb 100644 --- a/packages/typespec-azure-resource-manager/README.md +++ b/packages/typespec-azure-resource-manager/README.md @@ -662,7 +662,7 @@ Decorator to associate a feature with a model, interface, or namespace ##### Target The target to associate the feature with -`Model | Interface | Namespace` +`Model | Operation | Interface | Namespace` ##### Parameters diff --git a/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.Legacy.ts b/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.Legacy.ts index b3378857f2..375d9a4a94 100644 --- a/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.Legacy.ts +++ b/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.Legacy.ts @@ -119,7 +119,7 @@ export type FeatureOptionsDecorator = ( */ export type FeatureDecorator = ( context: DecoratorContext, - target: Model | Interface | Namespace, + target: Model | Operation | Interface | Namespace, featureName: EnumMember, ) => DecoratorValidatorCallbacks | void; diff --git a/packages/typespec-azure-resource-manager/lib/legacy-types/legacy.decorators.tsp b/packages/typespec-azure-resource-manager/lib/legacy-types/legacy.decorators.tsp index 1978a809bb..3df6649af8 100644 --- a/packages/typespec-azure-resource-manager/lib/legacy-types/legacy.decorators.tsp +++ b/packages/typespec-azure-resource-manager/lib/legacy-types/legacy.decorators.tsp @@ -97,4 +97,4 @@ extern dec featureOptions(target: EnumMember, options: valueof ArmFeatureOptions * @param target The target to associate the feature with * @param featureName The feature to associate with the target */ -extern dec feature(target: Model | Interface | Namespace, featureName: EnumMember); +extern dec feature(target: Model | Operation | Interface | Namespace, featureName: EnumMember); diff --git a/packages/typespec-azure-resource-manager/src/resource.ts b/packages/typespec-azure-resource-manager/src/resource.ts index 8c5d35cc48..e4d0de9031 100644 --- a/packages/typespec-azure-resource-manager/src/resource.ts +++ b/packages/typespec-azure-resource-manager/src/resource.ts @@ -1293,7 +1293,7 @@ export function resolveResourceBaseType(type?: string | undefined): ResourceBase } export const [getResourceFeature, setResourceFeature] = useStateMap< - Model | Interface | Namespace, + Model | Operation | Interface | Namespace, EnumMember >(ArmStateKeys.armFeature); @@ -1363,6 +1363,8 @@ export function getFeature(program: Program, entity: Type): ArmFeatureOptions { return getFeatureOptions(program, feature); } case "Operation": { + const opFeature = getResourceFeature(program, entity); + if (opFeature !== undefined) return getFeatureOptions(program, opFeature); const opInterface = entity.interface; if (opInterface !== undefined) { return getFeature(program, opInterface); @@ -1400,7 +1402,7 @@ export function getFeature(program: Program, entity: Type): ArmFeatureOptions { export const $feature: FeatureDecorator = ( context: DecoratorContext, - entity: Model | Interface | Namespace, + entity: Model | Operation | Interface | Namespace, featureName: EnumMember, ) => { const { program } = context; diff --git a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md index 2acfc0b379..0aef814ceb 100644 --- a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md +++ b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md @@ -570,7 +570,7 @@ Decorator to associate a feature with a model, interface, or namespace #### Target The target to associate the feature with -`Model | Interface | Namespace` +`Model | Operation | Interface | Namespace` #### Parameters From 3e59fe7f9ed076c5b2b910b2aea52f9e90ec349f Mon Sep 17 00:00:00 2001 From: Mark Cowlishaw <1054056+markcowl@users.noreply.github.com> Date: Fri, 23 Jan 2026 11:50:36 -0800 Subject: [PATCH 2/2] Update .chronus/changes/add-op-feature-2026-0-22-18-38-39.md Co-authored-by: Timothee Guerin --- .chronus/changes/add-op-feature-2026-0-22-18-38-39.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.chronus/changes/add-op-feature-2026-0-22-18-38-39.md b/.chronus/changes/add-op-feature-2026-0-22-18-38-39.md index 6ba5a6f685..2ec6bef843 100644 --- a/.chronus/changes/add-op-feature-2026-0-22-18-38-39.md +++ b/.chronus/changes/add-op-feature-2026-0-22-18-38-39.md @@ -4,4 +4,4 @@ packages: - "@azure-tools/typespec-azure-resource-manager" --- -Fix #3829 Allow @feature to apply to Operations \ No newline at end of file +Fix #3829 Allow `@feature` to apply to Operations \ No newline at end of file