Skip to content

feat: report malformed rule deprecation metadata#147

Open
xbinaryx wants to merge 3 commits into
eslint:mainfrom
xbinaryx:rule-tester-meta-deprecated-validation
Open

feat: report malformed rule deprecation metadata#147
xbinaryx wants to merge 3 commits into
eslint:mainfrom
xbinaryx:rule-tester-meta-deprecated-validation

Conversation

@xbinaryx
Copy link
Copy Markdown

@xbinaryx xbinaryx commented May 2, 2026

Summary

RuleTester should validate the shape of meta.deprecated on the rule under test and throw an assertion error when the value does not match the documented boolean | DeprecatedInfo contract.

Related Issues

eslint/eslint#20603

- `message`, `url`, and `deprecatedSince` must be strings when present.
- `availableUntil` must be a string or `null` when present.
- `replacedBy` must be an array when present.
- No other top-level `DeprecatedInfo` properties are allowed.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason to disallow unknown properties when ESLint does not use them.
This would allow plugin authors to add additional metadata for their use case(see the mentioned drawbacks).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DeprecatedInfo does not allow unknown properties in its type definition. If someone writes their rule in TypeScript, trying to add a custom property to this object will result in a compiler error. Validating it strictly in RuleTester simply brings the runtime behavior in line with what the TypeScript types already enforce. Furthermore, the Rule Deprecation documentation does not mention that this object can be extended with custom metadata.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But TypeScript also allows overwriting the types of external packages which can be used to extend the type, which would then not be possible for the rule tester.
Further I think using the types as a guideline is misguided in thiscase as the types allow every defined "subobject" to be empty which I would think the validator should report.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this section is meant to be used by ESLint itself, I'm fine with disallowing unknown keys. There are plenty of other places inside of meta where people can add custom metadata for other purposes.

Comment thread designs/2026-rule-tester-meta-deprecated-validation/README.md
@nzakas nzakas added the Initial Commenting This RFC is in the initial feedback stage label May 6, 2026
nzakas
nzakas previously approved these changes May 6, 2026
Copy link
Copy Markdown
Member

@nzakas nzakas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM. Just left a couple of notes for clarification.

- `message`, `url`, and `deprecatedSince` must be strings when present.
- `availableUntil` must be a string or `null` when present.
- `replacedBy` must be an array when present.
- No other top-level `DeprecatedInfo` properties are allowed.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this section is meant to be used by ESLint itself, I'm fine with disallowing unknown keys. There are plenty of other places inside of meta where people can add custom metadata for other purposes.

Comment thread designs/2026-rule-tester-meta-deprecated-validation/README.md Outdated

## Drawbacks

This is a breaking change for rule packages whose tests currently pass with malformed deprecation metadata. Some projects may also be storing custom, nonstandard fields under `meta.deprecated`; those projects will need to remove those fields or move them elsewhere.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth noting that we've decided breaking changes to RuleTester are acceptable outside of major version bumps because they affect plugin developers only and not end users. The utility is meant to ensure compatibility with the version of ESLint being used.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't recall us deciding that, can you provide a link (to a TSC meeting where we discussed this?). As far as I'm aware, all breaking changes to RuleTester were always considered breaking changes to ESLint as well and thus required a major version bump.

Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com>

## Motivation

Rule deprecation metadata is used by ESLint to populate `usedDeprecatedRules` and by integrations to explain replacement rules. Today, malformed `meta.deprecated` values can pass through rule tests unnoticed, which allows invalid metadata to reach users and downstream tools. `RuleTester` already catches common rule authoring mistakes such as invalid option schemas, missing `meta.fixable`, and missing `meta.hasSuggestions`; deprecation metadata should receive the same early feedback.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Rule deprecation metadata is used by ESLint to populate `usedDeprecatedRules` and by integrations to explain replacement rules. Today, malformed `meta.deprecated` values can pass through rule tests unnoticed, which allows invalid metadata to reach users and downstream tools. `RuleTester` already catches common rule authoring mistakes such as invalid option schemas, missing `meta.fixable`, and missing `meta.hasSuggestions`; deprecation metadata should receive the same early feedback.
Rule deprecation metadata is used by ESLint to populate `LintResult#usedDeprecatedRules` and by integrations to explain replacement rules. Today, malformed `meta.deprecated` values can pass through rule tests unnoticed, which allows invalid metadata to reach users and downstream tools. `RuleTester` already catches common rule authoring mistakes such as invalid option schemas, missing `meta.fixable`, and missing `meta.hasSuggestions`; deprecation metadata should receive the same early feedback.

To be more specific.

Comment on lines +57 to +58
- `message`, `url`, and `deprecatedSince` must be strings when present.
- `availableUntil` must be a string or `null` when present.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For semver-format strings, perhaps we could also check that they don't start with "v"?

It should also be possible to check if the string is valid semver, but I'm not sure if we would want to add a dependency for this purpose.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Initial Commenting This RFC is in the initial feedback stage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants