Skip to content

Align @experimental emitterScope with the standard scope convention #11702

Description

@JoshLove-msft

Problem

TypeSpec.HttpClient.@experimental uses options.emitterScope to control which emitters receive its lifecycle metadata:

@experimental(#{ emitterScope: "@typespec/http-client-csharp" })
op test(): void;

This differs from the established client-generator decorator convention, which uses a top-level optional argument named scope:

extern dec clientName(
  target: unknown,
  rename: valueof string,
  scope?: valueof string
);

@experimental and ClientDecoratorOptions.emitterScope were introduced together in #11094 with a package-specific scope parser.

Impact

TCGC's generic decorator handling automatically filters decorators by decoratorInfo.arguments.scope. It cannot recognize the nested decoratorInfo.arguments.options.emitterScope value used by @experimental.

As a result, emitters consuming @experimental through TCGC's generic decorator metadata must implement a second scope parser and filtering path. This creates duplicated behavior and makes the two scoping conventions easier to interpret differently over time.

Proposed compatibility path

Align @experimental with the standard top-level scope convention without immediately breaking existing TypeSpec:

  1. Add an optional top-level scope argument to @experimental.
  2. Continue accepting options.emitterScope as a deprecated compatibility alias.
  3. Use scope when provided; otherwise fall back to options.emitterScope.
  4. Report a diagnostic if both values are supplied.
  5. Update examples and documentation to use scope.
  6. Remove emitterScope only in a future breaking release.

Possible shape:

@experimental(
  #{ diagnosticId: "C", dependsOn: #["A", "B"] },
  "@typespec/http-client-csharp"
)
op test(): void;

Acceptance criteria

  • New usage follows the standard top-level scope convention.
  • Existing options.emitterScope usage continues to compile during the compatibility period.
  • TCGC automatically filters the decorator without emitter-specific scope parsing.
  • Supplying both scope forms produces a clear diagnostic.
  • Existing include/exclude behavior remains unchanged.
  • Documentation describes the migration and deprecation.

Related work

Metadata

Metadata

Assignees

No one assigned

    Labels

    emitter:client:allGeneral issue for client emittersfeatureNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions