Skip to content

Commit

Permalink
feat: Add suggestions to require-meta-docs-recommended rule (#500)
Browse files Browse the repository at this point in the history
* Add suggestions to `require-meta-docs-recommended` rule

* Update docs
  • Loading branch information
FloEdelmann authored Nov 19, 2024
1 parent e9c75eb commit 8fda55a
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ module.exports = [
| [prefer-replace-text](docs/rules/prefer-replace-text.md) | require using `replaceText()` instead of `replaceTextRange()` | | | | |
| [report-message-format](docs/rules/report-message-format.md) | enforce a consistent format for rule report messages | | | | |
| [require-meta-docs-description](docs/rules/require-meta-docs-description.md) | require rules to implement a `meta.docs.description` property with the correct format | | | | |
| [require-meta-docs-recommended](docs/rules/require-meta-docs-recommended.md) | require rules to implement a `meta.docs.recommended` property | | | | |
| [require-meta-docs-recommended](docs/rules/require-meta-docs-recommended.md) | require rules to implement a `meta.docs.recommended` property | | | 💡 | |
| [require-meta-docs-url](docs/rules/require-meta-docs-url.md) | require rules to implement a `meta.docs.url` property | | 🔧 | | |
| [require-meta-fixable](docs/rules/require-meta-fixable.md) | require rules to implement a `meta.fixable` property || | | |
| [require-meta-has-suggestions](docs/rules/require-meta-has-suggestions.md) | require suggestable rules to implement a `meta.hasSuggestions` property || 🔧 | | |
Expand Down
2 changes: 2 additions & 0 deletions docs/rules/require-meta-docs-recommended.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Require rules to implement a `meta.docs.recommended` property (`eslint-plugin/require-meta-docs-recommended`)

💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).

<!-- end auto-generated rule header -->

Utilizing `meta.docs.recommended` makes it clear from each rule implementation whether a rule is part of the `recommended` config. Some plugins also have scripting for conveniently generating their config based on this flag.
Expand Down
48 changes: 48 additions & 0 deletions lib/rules/require-meta-docs-recommended.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,24 @@
const { getStaticValue } = require('@eslint-community/eslint-utils');
const utils = require('../utils');

/**
* @param {import('eslint').Rule.RuleFixer} fixer
* @param {import('estree').ObjectExpression} objectNode
* @param {boolean} recommendedValue
*/
function insertRecommendedProperty(fixer, objectNode, recommendedValue) {
if (objectNode.properties.length === 0) {
return fixer.replaceText(
objectNode,
`{ recommended: ${recommendedValue} }`,
);
}
return fixer.insertTextAfter(
objectNode.properties.at(-1),
`, recommended: ${recommendedValue}`,
);
}

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
Expand All @@ -15,6 +33,7 @@ module.exports = {
url: 'https://github.com/eslint-community/eslint-plugin-eslint-plugin/tree/HEAD/docs/rules/require-meta-docs-recommended.md',
},
fixable: null,
hasSuggestions: true,
schema: [
{
type: 'object',
Expand All @@ -31,6 +50,8 @@ module.exports = {
messages: {
incorrect: '`meta.docs.recommended` is required to be a boolean.',
missing: '`meta.docs.recommended` is required.',
setRecommendedTrue: 'Set `meta.docs.recommended` to `true`.',
setRecommendedFalse: 'Set `meta.docs.recommended` to `false`.',
},
},

Expand All @@ -49,9 +70,26 @@ module.exports = {
} = utils.getMetaDocsProperty('recommended', ruleInfo, scopeManager);

if (!descriptionNode) {
const suggestions =
docsNode?.value?.type === 'ObjectExpression'
? [
{
messageId: 'setRecommendedTrue',
fix: (fixer) =>
insertRecommendedProperty(fixer, docsNode.value, true),
},
{
messageId: 'setRecommendedFalse',
fix: (fixer) =>
insertRecommendedProperty(fixer, docsNode.value, false),
},
]
: [];

context.report({
node: docsNode || metaNode || ruleInfo.create,
messageId: 'missing',
suggest: suggestions,
});
return {};
}
Expand All @@ -68,6 +106,16 @@ module.exports = {
context.report({
node: descriptionNode.value,
messageId: 'incorrect',
suggest: [
{
messageId: 'setRecommendedTrue',
fix: (fixer) => fixer.replaceText(descriptionNode.value, 'true'),
},
{
messageId: 'setRecommendedFalse',
fix: (fixer) => fixer.replaceText(descriptionNode.value, 'false'),
},
],
});
return {};
}
Expand Down
132 changes: 124 additions & 8 deletions tests/lib/rules/require-meta-docs-recommended.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ ruleTester.run('require-meta-docs-recommended', rule, {
{
code: 'module.exports = { create(context) {} };',
output: null,
errors: [{ messageId: 'missing', type: 'FunctionExpression' }],
errors: [
{ messageId: 'missing', type: 'FunctionExpression', suggestions: [] },
],
},
{
code: `
Expand All @@ -100,7 +102,13 @@ ruleTester.run('require-meta-docs-recommended', rule, {
};
`,
output: null,
errors: [{ messageId: 'missing', type: 'ObjectExpression' }],
errors: [
{
messageId: 'missing',
type: 'ObjectExpression',
suggestions: [],
},
],
},
{
code: `
Expand All @@ -110,7 +118,32 @@ ruleTester.run('require-meta-docs-recommended', rule, {
};
`,
output: null,
errors: [{ messageId: 'missing', type: 'Property' }],
errors: [
{
messageId: 'missing',
type: 'Property',
suggestions: [
{
messageId: 'setRecommendedTrue',
output: `
module.exports = {
meta: { docs: { recommended: true } },
create(context) {}
};
`,
},
{
messageId: 'setRecommendedFalse',
output: `
module.exports = {
meta: { docs: { recommended: false } },
create(context) {}
};
`,
},
],
},
],
},
{
code: `
Expand All @@ -120,7 +153,32 @@ ruleTester.run('require-meta-docs-recommended', rule, {
};
`,
output: null,
errors: [{ messageId: 'incorrect', type: 'Identifier' }],
errors: [
{
messageId: 'incorrect',
type: 'Identifier',
suggestions: [
{
messageId: 'setRecommendedTrue',
output: `
module.exports = {
meta: { docs: { recommended: true } },
create(context) {}
};
`,
},
{
messageId: 'setRecommendedFalse',
output: `
module.exports = {
meta: { docs: { recommended: false } },
create(context) {}
};
`,
},
],
},
],
},
{
code: `
Expand All @@ -130,7 +188,32 @@ ruleTester.run('require-meta-docs-recommended', rule, {
};
`,
output: null,
errors: [{ messageId: 'incorrect', type: 'Literal' }],
errors: [
{
messageId: 'incorrect',
type: 'Literal',
suggestions: [
{
messageId: 'setRecommendedTrue',
output: `
module.exports = {
meta: { docs: { recommended: true } },
create(context) {}
};
`,
},
{
messageId: 'setRecommendedFalse',
output: `
module.exports = {
meta: { docs: { recommended: false } },
create(context) {}
};
`,
},
],
},
],
},
{
code: `
Expand All @@ -142,13 +225,44 @@ ruleTester.run('require-meta-docs-recommended', rule, {
};
`,
output: null,
errors: [{ messageId: 'missing', type: 'Property' }],
errors: [
{
messageId: 'missing',
type: 'Property',
suggestions: [
{
messageId: 'setRecommendedTrue',
output: `
const extraDocs = { };
const extraMeta = { docs: { ...extraDocs, recommended: true } };
module.exports = {
meta: { ...extraMeta },
create(context) {}
};
`,
},
{
messageId: 'setRecommendedFalse',
output: `
const extraDocs = { };
const extraMeta = { docs: { ...extraDocs, recommended: false } };
module.exports = {
meta: { ...extraMeta },
create(context) {}
};
`,
},
],
},
],
},
{
code: 'module.exports = { create(context) {} };',
output: null,
options: [{ allowNonBoolean: true }],
errors: [{ messageId: 'missing', type: 'FunctionExpression' }],
errors: [
{ messageId: 'missing', type: 'FunctionExpression', suggestions: [] },
],
},
],
});
Expand Down Expand Up @@ -178,7 +292,9 @@ ruleTesterTypeScript.run('require-meta-docs-recommended (TypeScript)', rule, {
});
`,
output: null,
errors: [{ messageId: 'missing', type: 'ObjectExpression' }],
errors: [
{ messageId: 'missing', type: 'ObjectExpression', suggestions: [] },
],
},
],
});

0 comments on commit 8fda55a

Please sign in to comment.