microsoft / microsoft/typespec

Align @experimental emitterScope with the standard scope convention

Open
#11,702 1 comment 1 reaction 0 assignees View on GitHub
emitter:client:all feature
Dominant language
Java
Stars
5.9k
Forks
394
Avg merge
1d 23h
Merged PRs (30d)
104

Description

## Problem

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

```typespec
@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`:

```typespec
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:

```typespec
@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

- Original implementation: #11094
- Experimental metadata enhancement: #11684
- C# emitter integration: #11685
- Experimental diagnostic design: #11690

Contributor guide

Open the contributing guide

Research direction

Start at the @experimental definition and ClientDecoratorOptions.emitterScope introduced in #11094, then trace TCGC's generic decorator handling and its scope filtering. Add the top-level scope compatibility path, diagnostic, and migration documentation while preserving existing include/exclude behavior; verify the acceptance criteria with the relevant decorator and emitter tests.

Written by the indexing model from the issue text.

Assessment

Domain
compilers, documentation
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.