From bc0ed7c4662c43a685e60a36d9d5e79a871a69c1 Mon Sep 17 00:00:00 2001 From: Daniel Martens Date: Thu, 12 Sep 2024 23:39:41 +0200 Subject: [PATCH 01/10] feat: additional rule metadata for deprecations --- .../2024-deprecated-rule-metadata/README.md | 281 ++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 designs/2024-deprecated-rule-metadata/README.md diff --git a/designs/2024-deprecated-rule-metadata/README.md b/designs/2024-deprecated-rule-metadata/README.md new file mode 100644 index 00000000..f404ed15 --- /dev/null +++ b/designs/2024-deprecated-rule-metadata/README.md @@ -0,0 +1,281 @@ +- Repo: eslint/eslint +- Start Date: 2024-02-20 +- RFC PR: +- Authors: [bmish](https://github.com/bmish), [DMartens](https://github.com/DMartens) + +# Support additional metadata for rule deprecations + +## Summary + + + +This RFC suggests a format for storing additional information in rule metadata about rule deprecations and replacement rules, allowing tooling (e.g. documentation generators) to generate more informative deprecation notices. + +## Motivation + + + +There are long-time [rule meta properties](https://eslint.org/docs/latest/extend/custom-rules#rule-structure) `meta.deprecated` and `meta.replacedBy` that have been intended to document when rules are deprecated and what their replacement rule(s) are. For the most part, usage would look something like this: + +```js +module.exports = { meta: { deprecated: true, replacedBy: ['replacement-rule-name'] } }; +``` + +These properties are often used for generating plugin/rule documentation websites and in documentation tooling like [eslint-doc-generator](https://github.com/bmish/eslint-doc-generator). + +But there are some limitations to this current format: + +- Simply providing the replacement rule name as a string doesn't yield much context/explanation of the replacement/deprecation. That means documentation tooling / websites and code editors can only generate limited information to present about the situation. +- Some rules provide the replacement rule name with the plugin prefix as in `prefix/rule-name` while others just provide it as `rule-name`, which can result in ambiguity about whether the replacement rule is in the same plugin, a different third-party plugin, or ESLint core. And for third-party plugins, there's no easy way to automatically determine where their documentation is located or how to link to them. + +## Detailed Design + + + +We propose to extend `meta.deprecated` rule property schemas to reduce ambiguity and allow additional key details to be represented, described below using TypeScript types for clarity: + +```ts +type RuleMeta = { + deprecated?: + | boolean // Existing boolean option, backwards compatible. + | string // Shorthand property for general deprecation message, such as why the deprecation occurred. Empty strings are forbidden as they are falsy. + | DeprecatedInfo // Proposed extension + + /** @deprecated */ + replacedBy?: string[] // Deprecate the top-level property and "move" into the "deprecated" object +}; + +/* At least one property is required */ +type DeprecateInfo = { + info?: Message + replacedBy?: (string|ReplacedByInfo)[] // An empty array explicitly states that there is no replacement +} + +/* At least one property is required */ +type ReplacedByInfo = { + plugin?: string | Specifier // name should be "eslint" if the replacemenet is an ESLint core rule. Omit the property if the replacement is in the same plugin + rule?: string | Specifier + info?: string | Message + kind?: ReplacementKind // Defaults to "moved" if missing + deprecatedSince?: Version // Helps users gauge when to migrate and useful for documentation + availableUntil?: Version | null // The estimated version when the rule is removed (probably the next major version). null means the rule is "frozen" (will be available but will not be changed) +} + +type Message = { + message: string // General message presented to the user. Content depends on the property (e.g. for the key rule why the rule is deprecated or for info how to replace the rule) + url: // URL to more information about this deprecation in general. +} + +type Specifier = { + name: string // Name of the rule / configuration / ... + url: string // URL to more information about this deprecation in general. +} + +type ReplacementKind = + 'moved' | // The rule has moved to another plugin if plugin is set, otherwise the rule is renamed in the same plugin + 'merged' | // The rule merged with another rule + 'option' // The current rule behavior is available as an option in the replacement rule + +/* Version string of the package containing the rule */ +type Version = string +``` + +The `meta.replacedBy` property is moved into the `meta.deprecated` property as `meta.replacedBy` requires `meta.deprecated` to be set. +The reason for this is that a rule logically must be marked as deprecated to be replaced by another rule which it currently can be. + +### Example +Real-world example of how this could be used based on the situation in : + +```js +// lib/rules/semi.js +module.exports = { + meta: { + deprecated: { + message: 'Stylistic rules are being moved out of ESLint core.', + url: 'https://eslint.org/blog/2023/10/deprecating-formatting-rules/', + replacedBy: [ + { + plugin: { + name: '@stylistic/js', + url: 'https://eslint.style/', + }, + rule: 'https://eslint.style/rules/js/semi', + }, + ], + }, + }, +}; +``` + + +This data could be used by documentation websites and tooling like [eslint-doc-generator](https://github.com/bmish/eslint-doc-generator) to generate notices and links like: + +> semi (deprecated) \ +> Replaced by [semi](https://eslint.style/rules/js/semi) from [@stylistic/js](https://eslint.style/). \ +> Use the `foo` option on the new rule to achieve the same behavior as before. [Read more](https://example.com/how-to-migrate-to-the-new-semi-rule). \ +> Stylistic rules are being moved out of ESLint core. [Read more](https://eslint.org/blog/2023/10/deprecating-formatting-rules/). + +We can also support the same `meta.deprecated` and `meta.replacedBy` properties on configurations and processors (the other kinds of objects exported by ESLint plugins), replacing `rule` with `config` or `processor` as needed. This would be part of the effort to standardize documentation properties in . + +### Shorthand +The shorthand for the properties `plugin`, `rule` and `info` is just a string representing either the `name`/`message` or the `url` based on its content. +If it starts with a protocol (e.g. `https://`) the property should be interpreted as if only the `url` property is set, otherwise it should be interpreted as `name`/`message` property. +This shorthand also applies for the existing `meta.deprecated` which then applies for the `meta.deprecated.info` properties. +Some examples: +```js +{ meta: { deprecated: { plugin: 'https://eslint.style' } } } // <=> { meta: { deprecated: { plugin: { url: 'https://eslint.style' } } } } +{ meta: { deprecated: { plugin: '@eslint-stylistic/js' } } } // <=> { meta: { deprecated: { plugin: { name: '@eslint-stylistic/js' } } } } +{ meta: { deprecated: 'https://eslint.style/guide/migration' } // <=> { meta: { deprecated: { info: { url: 'https://eslint.style/guide/migration' } } } } +``` + +### Changes +In terms of actual changes inside ESLint needed for this: + +- Mention the new schema in the [custom rule documentation](https://eslint.org/docs/latest/extend/custom-rules#rule-structure) +- Ensure these properties are allowed on configurations, parsers and processors +- Add any additional information to these properties in core rules as desired (such as in ) +- Update ESLint's website generator to take into account the additional information for rule doc deprecation notices +- Update [LintResult.usedDeprecatedRules](https://github.com/eslint/eslint/blob/0f5df509a4bc00cff2c62b90fab184bdf0231322/lib/eslint/eslint.js#L197-L211) + +External changes: + +- Update the [types](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b77d83e019025017b06953907cb77f35e4231714/types/eslint/index.d.ts#L734) in @types/eslint +- Update the [types](https://github.com/typescript-eslint/typescript-eslint/blob/82cb9dd580f62644ed988fd2bf27f519177a60bd/packages/utils/src/ts-eslint/Rule.ts#L70) in @typescript-eslint/eslint +- Update eslint-doc-generator to handle the new information: +- Update the metadata for the most common plugins +- Consider implementing an [eslint-plugin-eslint-plugin](https://github.com/eslint-community/eslint-plugin-eslint-plugin) rule to encourage more complete deprecation information to be stored in these properties + +## Documentation + + + +We don't necessarily need a formal announcement for this. The aforementioned changes to the rule documentation page and types should be sufficient. + +However, this update could be covered in a blog post about general rule documentation best practices, if anyone ever has an interest in writing something like that. + +## Drawbacks + + + +There are some limited [backwards compatibility](#backwards-compatibility-analysis) concerns for third-party tooling. + +## Backwards Compatibility Analysis + + + +Existing rules will continue to be backwards-compatible with the new format. + +Changing the format of these properties mainly affects third-party documentation tooling and websites that use this information, and not ESLint users nor ESLint plugins directly. + +For the most part, the new `meta.deprecated` format should be backwards-compatible, as code is often written to check simply for a truthy value inside of `meta.deprecated`, e.g. `if (rule.meta.deprecated) { /* ... */ }`, which will continue to work as expected. The code needs to be updated if: +- it checks specifically for the boolean `true` value in `meta.deprecated` +- it checks for whether the rule is deprecated by checking for a non-empty `meta.replacedBy` +- retrieves rule names from `meta.replacedBy` + +Overall, a limited number of third-party tools that might be affected, and these should be trivial to fix when impacts are discovered. + +We do not need to consider this to be a breaking change in terms of [ESLint's semantic versioning policy](https://github.com/eslint/eslint#semantic-versioning-policy). + +## Alternatives + + + +### Do nothing + +This would leave the current `meta.deprecated` and `meta.replacedBy` properties as they are, which would continue to be ambiguous and limited in the information they can provide. + +### Create a new property + +Create a new property, e.g. `meta.deprecation`, + +## Open Questions + + + +1. Is there additional deprecation information we'd like to represent? Note that additional information can always be added later, but it's good to consider any possible needs now. +2. Should `meta.deprecated.plugin.id` accommodate different package registries (e.g. [jsr](https://jsr.io/) with `jsr:eslint-plugin-example`) +3. Should the exact regular expression for the shorthand which decides whether it is a description or URL be specified? +4. Should the shorthand also be applied for the string form of the `meta.deprecated` property? +5. Which "extension points" (rules, processors, configurations, parsers, formatters) shold be supported? +6. Should the `rule` key be dependent on the "extension point" (e.g. `processor` for processors) or renamed (e.g. ``) so that it is the same property name for all? + +## Help Needed + + + +I should be able to handle the minimal changes needed in ESLint core, and can kick off some of the changes needed in community projects. + +## Frequently Asked Questions + +- Why not provide a property to describe how to migrate to the replacement rule which requires an option to be set? + - The options of the replacement rule could change and it is unlikely that a deprecated rules gets updated to accommodate the change + + + +## Related Discussions + + + +- [The original RFC](https://github.com/eslint/rfcs/pull/116) +- [The issue triggering this RFC](https://github.com/eslint/eslint/issues/18061) +- Inspirations + - + - +- Related + - + - + - From 83f99acf1fd05f082a79448678980e0c8053a9be Mon Sep 17 00:00:00 2001 From: Daniel Martens Date: Wed, 18 Sep 2024 12:00:43 +0200 Subject: [PATCH 02/10] fix: move deprecatedSince and availableUntil to the root deprecated object --- designs/2024-deprecated-rule-metadata/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/designs/2024-deprecated-rule-metadata/README.md b/designs/2024-deprecated-rule-metadata/README.md index f404ed15..d83b067e 100644 --- a/designs/2024-deprecated-rule-metadata/README.md +++ b/designs/2024-deprecated-rule-metadata/README.md @@ -57,6 +57,8 @@ type RuleMeta = { type DeprecateInfo = { info?: Message replacedBy?: (string|ReplacedByInfo)[] // An empty array explicitly states that there is no replacement + deprecatedSince?: Version // Helps users gauge when to migrate and useful for documentation + availableUntil?: Version | null // The estimated version when the rule is removed (probably the next major version). null means the rule is "frozen" (will be available but will not be changed) } /* At least one property is required */ @@ -65,8 +67,6 @@ type ReplacedByInfo = { rule?: string | Specifier info?: string | Message kind?: ReplacementKind // Defaults to "moved" if missing - deprecatedSince?: Version // Helps users gauge when to migrate and useful for documentation - availableUntil?: Version | null // The estimated version when the rule is removed (probably the next major version). null means the rule is "frozen" (will be available but will not be changed) } type Message = { From 0c777ea9907f11f085be1290743dac4c7d32eace Mon Sep 17 00:00:00 2001 From: Daniel Martens Date: Wed, 9 Oct 2024 21:11:25 +0200 Subject: [PATCH 03/10] drop shorthands --- .../2024-deprecated-rule-metadata/README.md | 32 ++++++------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/designs/2024-deprecated-rule-metadata/README.md b/designs/2024-deprecated-rule-metadata/README.md index d83b067e..dc8f055f 100644 --- a/designs/2024-deprecated-rule-metadata/README.md +++ b/designs/2024-deprecated-rule-metadata/README.md @@ -46,7 +46,6 @@ We propose to extend `meta.deprecated` rule property schemas to reduce ambiguity type RuleMeta = { deprecated?: | boolean // Existing boolean option, backwards compatible. - | string // Shorthand property for general deprecation message, such as why the deprecation occurred. Empty strings are forbidden as they are falsy. | DeprecatedInfo // Proposed extension /** @deprecated */ @@ -63,20 +62,20 @@ type DeprecateInfo = { /* At least one property is required */ type ReplacedByInfo = { - plugin?: string | Specifier // name should be "eslint" if the replacemenet is an ESLint core rule. Omit the property if the replacement is in the same plugin - rule?: string | Specifier - info?: string | Message + plugin?: Specifier // name should be "eslint" if the replacemenet is an ESLint core rule. Omit the property if the replacement is in the same plugin + rule?: Specifier + info?: Message kind?: ReplacementKind // Defaults to "moved" if missing } type Message = { - message: string // General message presented to the user. Content depends on the property (e.g. for the key rule why the rule is deprecated or for info how to replace the rule) - url: // URL to more information about this deprecation in general. + message?: string // General message presented to the user. Content depends on the property (e.g. for the key rule why the rule is deprecated or for info how to replace the rule) + url?: // URL to more information about this deprecation in general. } type Specifier = { - name: string // Name of the rule / configuration / ... - url: string // URL to more information about this deprecation in general. + name?: string // Name of the rule / configuration / ... + url?: string // URL to more information about this deprecation in general. } type ReplacementKind = @@ -125,17 +124,6 @@ This data could be used by documentation websites and tooling like [eslint-doc-g We can also support the same `meta.deprecated` and `meta.replacedBy` properties on configurations and processors (the other kinds of objects exported by ESLint plugins), replacing `rule` with `config` or `processor` as needed. This would be part of the effort to standardize documentation properties in . -### Shorthand -The shorthand for the properties `plugin`, `rule` and `info` is just a string representing either the `name`/`message` or the `url` based on its content. -If it starts with a protocol (e.g. `https://`) the property should be interpreted as if only the `url` property is set, otherwise it should be interpreted as `name`/`message` property. -This shorthand also applies for the existing `meta.deprecated` which then applies for the `meta.deprecated.info` properties. -Some examples: -```js -{ meta: { deprecated: { plugin: 'https://eslint.style' } } } // <=> { meta: { deprecated: { plugin: { url: 'https://eslint.style' } } } } -{ meta: { deprecated: { plugin: '@eslint-stylistic/js' } } } // <=> { meta: { deprecated: { plugin: { name: '@eslint-stylistic/js' } } } } -{ meta: { deprecated: 'https://eslint.style/guide/migration' } // <=> { meta: { deprecated: { info: { url: 'https://eslint.style/guide/migration' } } } } -``` - ### Changes In terms of actual changes inside ESLint needed for this: @@ -232,10 +220,8 @@ Create a new property, e.g. `meta.deprecation`, 1. Is there additional deprecation information we'd like to represent? Note that additional information can always be added later, but it's good to consider any possible needs now. 2. Should `meta.deprecated.plugin.id` accommodate different package registries (e.g. [jsr](https://jsr.io/) with `jsr:eslint-plugin-example`) -3. Should the exact regular expression for the shorthand which decides whether it is a description or URL be specified? -4. Should the shorthand also be applied for the string form of the `meta.deprecated` property? -5. Which "extension points" (rules, processors, configurations, parsers, formatters) shold be supported? -6. Should the `rule` key be dependent on the "extension point" (e.g. `processor` for processors) or renamed (e.g. ``) so that it is the same property name for all? +3. Which "extension points" (rules, processors, configurations, parsers, formatters) shold be supported? +4. Should the `rule` key be dependent on the "extension point" (e.g. `processor` for processors) or renamed (e.g. ``) so that it is the same property name for all? ## Help Needed From 0a796b58dda9c97e1402a64746f4abe23b827b59 Mon Sep 17 00:00:00 2001 From: fnx <966276+DMartens@users.noreply.github.com> Date: Thu, 10 Oct 2024 13:51:40 +0200 Subject: [PATCH 04/10] undo deleting string for url property Co-authored-by: Milos Djermanovic --- designs/2024-deprecated-rule-metadata/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/designs/2024-deprecated-rule-metadata/README.md b/designs/2024-deprecated-rule-metadata/README.md index dc8f055f..3de78562 100644 --- a/designs/2024-deprecated-rule-metadata/README.md +++ b/designs/2024-deprecated-rule-metadata/README.md @@ -70,7 +70,7 @@ type ReplacedByInfo = { type Message = { message?: string // General message presented to the user. Content depends on the property (e.g. for the key rule why the rule is deprecated or for info how to replace the rule) - url?: // URL to more information about this deprecation in general. + url?: string // URL to more information about this deprecation in general. } type Specifier = { From 4b88e16a017446910df95cebf5a7f20e48b6732c Mon Sep 17 00:00:00 2001 From: Daniel Martens Date: Mon, 28 Oct 2024 21:48:50 +0100 Subject: [PATCH 05/10] fix: incorporated suggestions --- .../2024-deprecated-rule-metadata/README.md | 37 +++++++------------ 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/designs/2024-deprecated-rule-metadata/README.md b/designs/2024-deprecated-rule-metadata/README.md index 3de78562..c6871577 100644 --- a/designs/2024-deprecated-rule-metadata/README.md +++ b/designs/2024-deprecated-rule-metadata/README.md @@ -40,7 +40,8 @@ But there are some limitations to this current format: used. Be sure to define any new terms in this section. --> -We propose to extend `meta.deprecated` rule property schemas to reduce ambiguity and allow additional key details to be represented, described below using TypeScript types for clarity: +We propose to extend `meta.deprecated` rule property schemas to reduce ambiguity and allow additional key details to be represented. +Plugin developers are free to add additional properties (e.g. a link to the original GitHub PR). ```ts type RuleMeta = { @@ -53,8 +54,9 @@ type RuleMeta = { }; /* At least one property is required */ -type DeprecateInfo = { - info?: Message +type DeprecatedInfo = { + message?: string // General message presented to the user, e.g. for the key rule why the rule is deprecated or for info how to replace the rule + url?: string // URL to more information about this deprecation in general replacedBy?: (string|ReplacedByInfo)[] // An empty array explicitly states that there is no replacement deprecatedSince?: Version // Helps users gauge when to migrate and useful for documentation availableUntil?: Version | null // The estimated version when the rule is removed (probably the next major version). null means the rule is "frozen" (will be available but will not be changed) @@ -62,15 +64,10 @@ type DeprecateInfo = { /* At least one property is required */ type ReplacedByInfo = { + message?: string // General message presented to the user, e.g. how to replace the rule + url?: string // URL to more information about this replacmenet in general plugin?: Specifier // name should be "eslint" if the replacemenet is an ESLint core rule. Omit the property if the replacement is in the same plugin rule?: Specifier - info?: Message - kind?: ReplacementKind // Defaults to "moved" if missing -} - -type Message = { - message?: string // General message presented to the user. Content depends on the property (e.g. for the key rule why the rule is deprecated or for info how to replace the rule) - url?: string // URL to more information about this deprecation in general. } type Specifier = { @@ -78,12 +75,7 @@ type Specifier = { url?: string // URL to more information about this deprecation in general. } -type ReplacementKind = - 'moved' | // The rule has moved to another plugin if plugin is set, otherwise the rule is renamed in the same plugin - 'merged' | // The rule merged with another rule - 'option' // The current rule behavior is available as an option in the replacement rule - -/* Version string of the package containing the rule */ +/* Version string of the package containing the rule (without a leading v and using the full semver, e.g. 8.53.0) */ type Version = string ``` @@ -104,9 +96,7 @@ module.exports = { { plugin: { name: '@stylistic/js', - url: 'https://eslint.style/', - }, - rule: 'https://eslint.style/rules/js/semi', + url: 'https://eslint.style/rules/js/semi', }, ], }, @@ -128,14 +118,14 @@ We can also support the same `meta.deprecated` and `meta.replacedBy` properties In terms of actual changes inside ESLint needed for this: - Mention the new schema in the [custom rule documentation](https://eslint.org/docs/latest/extend/custom-rules#rule-structure) -- Ensure these properties are allowed on configurations, parsers and processors +- Ensure these properties are allowed on all extension points (configurations, formatter, parsers and processors) - Add any additional information to these properties in core rules as desired (such as in ) - Update ESLint's website generator to take into account the additional information for rule doc deprecation notices -- Update [LintResult.usedDeprecatedRules](https://github.com/eslint/eslint/blob/0f5df509a4bc00cff2c62b90fab184bdf0231322/lib/eslint/eslint.js#L197-L211) +- Update [LintResult.usedDeprecatedRules](https://github.com/eslint/eslint/blob/0f5df509a4bc00cff2c62b90fab184bdf0231322/lib/eslint/eslint.js#L197-L211) by normalizing the old and new format for the existing `replacedBy` property and adding a new property with the name `info` for rules using the new deprecated format External changes: -- Update the [types](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b77d83e019025017b06953907cb77f35e4231714/types/eslint/index.d.ts#L734) in @types/eslint +- Update the [types](https://github.com/eslint/eslint/blob/35a8858d62cb050fa0b56702e55c94ffaaf6956d/lib/types/index.d.ts#L745) in eslint - Update the [types](https://github.com/typescript-eslint/typescript-eslint/blob/82cb9dd580f62644ed988fd2bf27f519177a60bd/packages/utils/src/ts-eslint/Rule.ts#L70) in @typescript-eslint/eslint - Update eslint-doc-generator to handle the new information: - Update the metadata for the most common plugins @@ -219,7 +209,8 @@ Create a new property, e.g. `meta.deprecation`, --> 1. Is there additional deprecation information we'd like to represent? Note that additional information can always be added later, but it's good to consider any possible needs now. -2. Should `meta.deprecated.plugin.id` accommodate different package registries (e.g. [jsr](https://jsr.io/) with `jsr:eslint-plugin-example`) +2. Should `meta.deprecated.plugin.name` accommodate different package registries (e.g. [jsr](https://jsr.io/) with `jsr:eslint-plugin-example`) + - If it is a concern, plugin developers can use a direct URL 3. Which "extension points" (rules, processors, configurations, parsers, formatters) shold be supported? 4. Should the `rule` key be dependent on the "extension point" (e.g. `processor` for processors) or renamed (e.g. ``) so that it is the same property name for all? From 613b13c0c4949587205369bef811c0bad9c30bf7 Mon Sep 17 00:00:00 2001 From: Daniel Martens Date: Mon, 28 Oct 2024 21:54:00 +0100 Subject: [PATCH 06/10] fix: rewrite descriptions of name and url --- designs/2024-deprecated-rule-metadata/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/designs/2024-deprecated-rule-metadata/README.md b/designs/2024-deprecated-rule-metadata/README.md index c6871577..44e77da1 100644 --- a/designs/2024-deprecated-rule-metadata/README.md +++ b/designs/2024-deprecated-rule-metadata/README.md @@ -65,14 +65,14 @@ type DeprecatedInfo = { /* At least one property is required */ type ReplacedByInfo = { message?: string // General message presented to the user, e.g. how to replace the rule - url?: string // URL to more information about this replacmenet in general + url?: string // URL to more information about this replacement in general plugin?: Specifier // name should be "eslint" if the replacemenet is an ESLint core rule. Omit the property if the replacement is in the same plugin rule?: Specifier } type Specifier = { - name?: string // Name of the rule / configuration / ... - url?: string // URL to more information about this deprecation in general. + name?: string // Name of the plugin / rule / ... + url?: string // URL to documentation for the plugin / rule } /* Version string of the package containing the rule (without a leading v and using the full semver, e.g. 8.53.0) */ From 5365fbca70ef332cbd07b5828126b9331ae5c605 Mon Sep 17 00:00:00 2001 From: Daniel Martens Date: Thu, 31 Oct 2024 21:53:48 +0100 Subject: [PATCH 07/10] fix: remove missed shorthand, fix example, make types an internal change --- designs/2024-deprecated-rule-metadata/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/designs/2024-deprecated-rule-metadata/README.md b/designs/2024-deprecated-rule-metadata/README.md index 44e77da1..f1dcbdf2 100644 --- a/designs/2024-deprecated-rule-metadata/README.md +++ b/designs/2024-deprecated-rule-metadata/README.md @@ -57,7 +57,7 @@ type RuleMeta = { type DeprecatedInfo = { message?: string // General message presented to the user, e.g. for the key rule why the rule is deprecated or for info how to replace the rule url?: string // URL to more information about this deprecation in general - replacedBy?: (string|ReplacedByInfo)[] // An empty array explicitly states that there is no replacement + replacedBy?: ReplacedByInfo[] // An empty array explicitly states that there is no replacement deprecatedSince?: Version // Helps users gauge when to migrate and useful for documentation availableUntil?: Version | null // The estimated version when the rule is removed (probably the next major version). null means the rule is "frozen" (will be available but will not be changed) } @@ -96,7 +96,11 @@ module.exports = { { plugin: { name: '@stylistic/js', - url: 'https://eslint.style/rules/js/semi', + url: 'https://eslint.style/', + rule: { + name: 'semi', + url: 'https://eslint.style/rules/js/semi' + } }, ], }, @@ -122,10 +126,10 @@ In terms of actual changes inside ESLint needed for this: - Add any additional information to these properties in core rules as desired (such as in ) - Update ESLint's website generator to take into account the additional information for rule doc deprecation notices - Update [LintResult.usedDeprecatedRules](https://github.com/eslint/eslint/blob/0f5df509a4bc00cff2c62b90fab184bdf0231322/lib/eslint/eslint.js#L197-L211) by normalizing the old and new format for the existing `replacedBy` property and adding a new property with the name `info` for rules using the new deprecated format +- Update the [types](https://github.com/eslint/eslint/blob/35a8858d62cb050fa0b56702e55c94ffaaf6956d/lib/types/index.d.ts#L745) in eslint External changes: -- Update the [types](https://github.com/eslint/eslint/blob/35a8858d62cb050fa0b56702e55c94ffaaf6956d/lib/types/index.d.ts#L745) in eslint - Update the [types](https://github.com/typescript-eslint/typescript-eslint/blob/82cb9dd580f62644ed988fd2bf27f519177a60bd/packages/utils/src/ts-eslint/Rule.ts#L70) in @typescript-eslint/eslint - Update eslint-doc-generator to handle the new information: - Update the metadata for the most common plugins From eeb67a7a1c6788f33613a8075add617fdc3752a0 Mon Sep 17 00:00:00 2001 From: Daniel Martens Date: Sat, 2 Nov 2024 20:28:40 +0100 Subject: [PATCH 08/10] focus on rules and not other extension points --- designs/2024-deprecated-rule-metadata/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/designs/2024-deprecated-rule-metadata/README.md b/designs/2024-deprecated-rule-metadata/README.md index f1dcbdf2..c5e05208 100644 --- a/designs/2024-deprecated-rule-metadata/README.md +++ b/designs/2024-deprecated-rule-metadata/README.md @@ -95,13 +95,14 @@ module.exports = { replacedBy: [ { plugin: { - name: '@stylistic/js', - url: 'https://eslint.style/', + name: '@stylistic/js', + url: 'https://eslint.style/', + }, rule: { name: 'semi', url: 'https://eslint.style/rules/js/semi' } - }, + } ], }, }, @@ -122,7 +123,6 @@ We can also support the same `meta.deprecated` and `meta.replacedBy` properties In terms of actual changes inside ESLint needed for this: - Mention the new schema in the [custom rule documentation](https://eslint.org/docs/latest/extend/custom-rules#rule-structure) -- Ensure these properties are allowed on all extension points (configurations, formatter, parsers and processors) - Add any additional information to these properties in core rules as desired (such as in ) - Update ESLint's website generator to take into account the additional information for rule doc deprecation notices - Update [LintResult.usedDeprecatedRules](https://github.com/eslint/eslint/blob/0f5df509a4bc00cff2c62b90fab184bdf0231322/lib/eslint/eslint.js#L197-L211) by normalizing the old and new format for the existing `replacedBy` property and adding a new property with the name `info` for rules using the new deprecated format @@ -216,7 +216,7 @@ Create a new property, e.g. `meta.deprecation`, 2. Should `meta.deprecated.plugin.name` accommodate different package registries (e.g. [jsr](https://jsr.io/) with `jsr:eslint-plugin-example`) - If it is a concern, plugin developers can use a direct URL 3. Which "extension points" (rules, processors, configurations, parsers, formatters) shold be supported? -4. Should the `rule` key be dependent on the "extension point" (e.g. `processor` for processors) or renamed (e.g. ``) so that it is the same property name for all? + - Focus on rules as other extension points have no well-defined use cases ## Help Needed From 21b08c6af392592a7a3b969df62e011cce855b72 Mon Sep 17 00:00:00 2001 From: Daniel Martens Date: Sun, 3 Nov 2024 21:21:23 +0100 Subject: [PATCH 09/10] fix: rule example plugin name/url and add deprecatedSince --- designs/2024-deprecated-rule-metadata/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/designs/2024-deprecated-rule-metadata/README.md b/designs/2024-deprecated-rule-metadata/README.md index c5e05208..2a22379c 100644 --- a/designs/2024-deprecated-rule-metadata/README.md +++ b/designs/2024-deprecated-rule-metadata/README.md @@ -95,8 +95,8 @@ module.exports = { replacedBy: [ { plugin: { - name: '@stylistic/js', - url: 'https://eslint.style/', + name: '@stylistic/eslint-plugin-js', + url: 'https://eslint.style/packages/js', }, rule: { name: 'semi', @@ -104,6 +104,7 @@ module.exports = { } } ], + deprecatedSince: "8.53.0", }, }, }; From 02ba56c5ec0f84b8861fc70642b6b26181c73c45 Mon Sep 17 00:00:00 2001 From: fnx <966276+DMartens@users.noreply.github.com> Date: Sun, 3 Nov 2024 22:54:56 +0100 Subject: [PATCH 10/10] remove link for issue marking rules as frozen Co-authored-by: Milos Djermanovic --- designs/2024-deprecated-rule-metadata/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/designs/2024-deprecated-rule-metadata/README.md b/designs/2024-deprecated-rule-metadata/README.md index 2a22379c..96b4dc83 100644 --- a/designs/2024-deprecated-rule-metadata/README.md +++ b/designs/2024-deprecated-rule-metadata/README.md @@ -259,5 +259,4 @@ I should be able to handle the minimal changes needed in ESLint core, and can ki - - Related - - - -