You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Those references are plain strings, resolved lazily and only for the rulesets a consumer actually extends. Nothing in the owning library's own build ever resolves them, so when a rule is renamed or removed the ruleset silently rots — and the first person to find out is a user compiling their spec, with an error pointing at a library they don't own.
That is exactly what happened to @azure-tools/typespec-azure-rulesets, which still references use-extensible-enum and no-fixed-enum-discriminator long after they were dropped from typespec-azure-core.
@typespec/library-linter already runs on every library build (tsp compile . --import @typespec/library-linter), and everything it needs is public API: program.jsSourceFiles exposes each loaded library's $lib/$linter, and getSourceFileLocationContext separates the library being compiled from its dependencies. So it now checks that every rule and ruleset a library's own rulesets reference actually resolves:
warning @typespec/library-linter/unknown-rule: Rule 'removed-rule' referenced by ruleset
'@typespec/best-practices/recommended' is not defined in library '@typespec/best-practices'.
Two deliberate limits:
Only the rulesets of the library being compiled are validated. A dependency's broken ruleset is that library's build's problem.
A reference to a library that is not part of the compilation is skipped rather than reported, since there is nothing to resolve it against.
Known gap
This does not cover ruleset packages that have no TypeSpec entrypoint. @azure-tools/typespec-azure-rulesets and @typespec/best-practices are pure-JS packages with no main.tsp, so tsp compile . is never run on them and this check never fires — which means it currently catches nothing in this repo and, notably, not the azure-rulesets breakage that motivated it. Covering those needs the same validation wired into tspd doc, the only build step they run. Worth a follow-up.
Validate that rules and rulesets referenced by the rulesets a library defines actually exist. Previously a dangling reference was only reported when a consumer happened to extend the offending ruleset.,> ,> ts,> export const $linter = defineLinter({,> rules: [casingRule],,> ruleSets: {,> recommended: {,> // warning: Rule 'removed-rule' referenced by ruleset '@typespec/best-practices/recommended',> // is not defined in library '@typespec/best-practices'.,> enable: { "@typespec/best-practices/removed-rule": true },,> },,> },,> });,> ,> ,> References to a library that is not part of the compilation are skipped, and only the rulesets of the library being compiled are validated.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A library can declare a ruleset that enables rules owned by other libraries:
Those references are plain strings, resolved lazily and only for the rulesets a consumer actually extends. Nothing in the owning library's own build ever resolves them, so when a rule is renamed or removed the ruleset silently rots — and the first person to find out is a user compiling their spec, with an error pointing at a library they don't own.
That is exactly what happened to
@azure-tools/typespec-azure-rulesets, which still referencesuse-extensible-enumandno-fixed-enum-discriminatorlong after they were dropped fromtypespec-azure-core.@typespec/library-linteralready runs on every library build (tsp compile . --import @typespec/library-linter), and everything it needs is public API:program.jsSourceFilesexposes each loaded library's$lib/$linter, andgetSourceFileLocationContextseparates the library being compiled from its dependencies. So it now checks that every rule and ruleset a library's own rulesets reference actually resolves:Two deliberate limits:
Known gap
This does not cover ruleset packages that have no TypeSpec entrypoint.
@azure-tools/typespec-azure-rulesetsand@typespec/best-practicesare pure-JS packages with nomain.tsp, sotsp compile .is never run on them and this check never fires — which means it currently catches nothing in this repo and, notably, not the azure-rulesets breakage that motivated it. Covering those needs the same validation wired intotspd doc, the only build step they run. Worth a follow-up.