Clear and concise description of the problem
Large specification repositories need to enable new TypeSpec linter rules without requiring every pre-existing violation in legacy APIs to be fixed immediately or adding #suppress annotations across many .tsp files.
Today TypeSpec provides two suppression choices:
#suppress "<diagnostic-code>" "<reason>", which must be placed on the affected declaration or a syntactic ancestor. This requires editing many source files and mixes migration bookkeeping into legacy API definitions.
linter.disable in tspconfig.yaml, which disables the rule for the entire project. This also hides violations introduced by new or actively maintained specifications, so it cannot be used to incrementally adopt a rule.
Swagger-based repositories can keep targeted suppressions centrally in a readme.md directive configuration. TypeSpec needs an equivalent centralized mechanism so a repository can record only known legacy violations while keeping the linter rule enabled for all other code.
The preferred TypeSpec-native design is an augment-style suppression construct that can live in a dedicated suppressions.tsp file. For example (syntax illustrative):
// main.tsp
import "./suppressions.tsp";
// suppressions.tsp
@@suppress(
LegacyApi.OldModel,
"@azure-tools/typespec-azure-core/example-rule",
"Existing contract; tracked for future migration"
);
@@suppress(
LegacyApi.OldModel.oldProperty,
"@azure-tools/typespec-azure-core/another-rule",
"Existing contract; changing it would be breaking"
);
Using an augment statement keeps suppressions in TypeSpec, targets declarations by stable symbol identity, and allows all legacy exceptions to be maintained in one file without modifying their original definitions.
A useful design should support:
- Applying suppression externally to a model, property, operation, namespace, or other diagnostic target using an augment-style statement such as
@@suppress(...).
- A required diagnostic/rule code and justification.
- The same descendant-scoping semantics as inline
#suppress where applicable.
- New violations remaining visible, including violations of the same rule on non-suppressed targets.
- Detection or cleanup of stale suppressions after a violation is fixed.
- Editor completion, validation, and code actions for adding a suppression to the centralized file.
This would let spec repositories enable newly introduced rules immediately: existing legacy violations are suppressed centrally, while TypeSpec authors still receive and must fix any new violations.
Checklist
Clear and concise description of the problem
Large specification repositories need to enable new TypeSpec linter rules without requiring every pre-existing violation in legacy APIs to be fixed immediately or adding
#suppressannotations across many.tspfiles.Today TypeSpec provides two suppression choices:
#suppress "<diagnostic-code>" "<reason>", which must be placed on the affected declaration or a syntactic ancestor. This requires editing many source files and mixes migration bookkeeping into legacy API definitions.linter.disableintspconfig.yaml, which disables the rule for the entire project. This also hides violations introduced by new or actively maintained specifications, so it cannot be used to incrementally adopt a rule.Swagger-based repositories can keep targeted suppressions centrally in a
readme.mddirective configuration. TypeSpec needs an equivalent centralized mechanism so a repository can record only known legacy violations while keeping the linter rule enabled for all other code.The preferred TypeSpec-native design is an augment-style suppression construct that can live in a dedicated
suppressions.tspfile. For example (syntax illustrative):Using an augment statement keeps suppressions in TypeSpec, targets declarations by stable symbol identity, and allows all legacy exceptions to be maintained in one file without modifying their original definitions.
A useful design should support:
@@suppress(...).#suppresswhere applicable.This would let spec repositories enable newly introduced rules immediately: existing legacy violations are suppressed centrally, while TypeSpec authors still receive and must fix any new violations.
Checklist