Skip to content

Commit 817fd7a

Browse files
committed
New: Add catchNoFixerButFixableProperty option (default false) to catch non-fixable rules that enable the fixable property in require-meta-fixable rule
1 parent fcbb65c commit 817fd7a

File tree

3 files changed

+90
-9
lines changed

3 files changed

+90
-9
lines changed

docs/rules/require-meta-fixable.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ module.exports = {
4444
};
4545
```
4646

47+
```js
48+
/* eslint eslint-plugin/require-meta-fixable: ["error", { catchNoFixerButFixableProperty: true }] */
49+
50+
module.exports = {
51+
meta: { fixable: 'code' }, // property enabled but no fixer detected
52+
create (context) {
53+
context.report({ node, message: 'foo' });
54+
},
55+
};
56+
```
57+
4758
Examples of **correct** code for this rule:
4859

4960
```js
@@ -77,6 +88,12 @@ module.exports = {
7788
};
7889
```
7990

91+
## Options
92+
93+
This rule takes an optional object containing:
94+
95+
* `boolean``catchNoFixerButFixableProperty` — default `false` - Whether the rule should attempt to detect rules that do not have a fixer but enable the `meta.fixable` property. This option is off by default because it increases the chance of false positives since fixers can't always be detected when helper functions are used.
96+
8097
## Further Reading
8198

8299
* [ESLint's autofix API](http://eslint.org/docs/developer-guide/working-with-rules#applying-fixes)

lib/rules/require-meta-fixable.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,28 @@ module.exports = {
2020
category: 'Rules',
2121
recommended: true,
2222
},
23-
schema: [],
23+
schema: [
24+
{
25+
type: 'object',
26+
properties: {
27+
catchNoFixerButFixableProperty: {
28+
type: 'boolean',
29+
default: false,
30+
},
31+
},
32+
additionalProperties: false,
33+
},
34+
],
2435
messages: {
2536
invalid: '`meta.fixable` must be either `code`, `whitespace`, or `null`.',
2637
missing: '`meta.fixable` must be either `code` or `whitespace` for fixable rules.',
38+
noFixerButFixableValue: '`meta.fixable` is enabled but no fixer detected.',
2739
},
2840
},
2941

3042
create (context) {
43+
const catchFixerButFixableValue = context.options[0] && context.options[0].catchNoFixerButFixableProperty;
44+
3145
const sourceCode = context.getSourceCode();
3246
const ruleInfo = utils.getRuleInfo(sourceCode);
3347
let contextIdentifiers;
@@ -82,6 +96,9 @@ module.exports = {
8296
if (usesFixFunctions && !['code', 'whitespace'].includes(staticValue.value)) {
8397
// Rule is fixable but `fixable` property does not have a fixable value.
8498
context.report({ node: metaFixableProp.value, messageId: 'missing' });
99+
} else if (catchFixerButFixableValue && !usesFixFunctions && ['code', 'whitespace'].includes(staticValue.value)) {
100+
// Rule is NOT fixable but `fixable` property has a fixable value.
101+
context.report({ node: metaFixableProp.value, messageId: 'noFixerButFixableValue' });
85102
}
86103
} else if (!metaFixableProp && usesFixFunctions) {
87104
// Rule is fixable but is missing the `fixable` property.

tests/lib/rules/require-meta-fixable.js

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,6 @@ ruleTester.run('require-meta-fixable', rule, {
7676
}
7777
};
7878
`,
79-
`
80-
module.exports = {
81-
meta: { fixable: 'code' },
82-
create(context) {
83-
context.report({node, message});
84-
}
85-
};
86-
`,
8779
`
8880
module.exports = {
8981
meta: { fixable: null },
@@ -132,6 +124,39 @@ ruleTester.run('require-meta-fixable', rule, {
132124
ecmaVersion: 9,
133125
},
134126
},
127+
128+
// catchNoFixerButFixableProperty = false (implicitly)
129+
`
130+
module.exports = {
131+
meta: { fixable: 'code' },
132+
create(context) { context.report({node, message}); }
133+
};
134+
`,
135+
`
136+
module.exports = {
137+
meta: { fixable: 'whitespace' },
138+
create(context) { context.report({node, message}); }
139+
};
140+
`,
141+
// catchNoFixerButFixableProperty = false (explicitly)
142+
{
143+
code: `
144+
module.exports = {
145+
meta: { fixable: 'code' },
146+
create(context) { context.report({node, message}); }
147+
};
148+
`,
149+
options: [{ catchNoFixerButFixableProperty: false }],
150+
},
151+
{
152+
code: `
153+
module.exports = {
154+
meta: { fixable: 'whitespace' },
155+
create(context) { context.report({node, message}); }
156+
};
157+
`,
158+
options: [{ catchNoFixerButFixableProperty: false }],
159+
},
135160
],
136161

137162
invalid: [
@@ -207,5 +232,27 @@ ruleTester.run('require-meta-fixable', rule, {
207232
`,
208233
errors: [{ messageId: 'missing', type: 'Identifier' }],
209234
},
235+
236+
// catchNoFixerButFixableProperty = true
237+
{
238+
code: `
239+
module.exports = {
240+
meta: { fixable: 'code' },
241+
create(context) { context.report({node, message}); }
242+
};
243+
`,
244+
options: [{ catchNoFixerButFixableProperty: true }],
245+
errors: [{ messageId: 'noFixerButFixableValue', type: 'Literal' }],
246+
},
247+
{
248+
code: `
249+
module.exports = {
250+
meta: { fixable: 'whitespace' },
251+
create(context) { context.report({node, message}); }
252+
};
253+
`,
254+
options: [{ catchNoFixerButFixableProperty: true }],
255+
errors: [{ messageId: 'noFixerButFixableValue', type: 'Literal' }],
256+
},
210257
],
211258
});

0 commit comments

Comments
 (0)