Skip to content

Commit c325f3f

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 c325f3f

File tree

3 files changed

+87
-9
lines changed

3 files changed

+87
-9
lines changed

docs/rules/require-meta-fixable.md

+17
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 enable 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

+17-1
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,27 @@ 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+
},
30+
},
31+
additionalProperties: false,
32+
},
33+
],
2434
messages: {
2535
invalid: '`meta.fixable` must be either `code`, `whitespace`, or `null`.',
2636
missing: '`meta.fixable` must be either `code` or `whitespace` for fixable rules.',
37+
noFixerButFixableValue: '`meta.fixable` is enabled but no fixer detected.',
2738
},
2839
},
2940

3041
create (context) {
42+
const catchFixerButFixableValue = context.options[0] && context.options[0].catchNoFixerButFixableProperty;
43+
3144
const sourceCode = context.getSourceCode();
3245
const ruleInfo = utils.getRuleInfo(sourceCode);
3346
let contextIdentifiers;
@@ -82,6 +95,9 @@ module.exports = {
8295
if (usesFixFunctions && !['code', 'whitespace'].includes(staticValue.value)) {
8396
// Rule is fixable but `fixable` property does not have a fixable value.
8497
context.report({ node: metaFixableProp.value, messageId: 'missing' });
98+
} else if (catchFixerButFixableValue && !usesFixFunctions && ['code', 'whitespace'].includes(staticValue.value)) {
99+
// Rule is NOT fixable but `fixable` property has a fixable value.
100+
context.report({ node: metaFixableProp.value, messageId: 'noFixerButFixableValue' });
85101
}
86102
} else if (!metaFixableProp && usesFixFunctions) {
87103
// Rule is fixable but is missing the `fixable` property.

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

+53-8
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,25 @@ ruleTester.run('require-meta-fixable', rule, {
207232
`,
208233
errors: [{ messageId: 'missing', type: 'Identifier' }],
209234
},
235+
{
236+
code: `
237+
module.exports = {
238+
meta: { fixable: 'code' },
239+
create(context) { context.report({node, message}); }
240+
};
241+
`,
242+
options: [{ catchNoFixerButFixableProperty: true }],
243+
errors: [{ messageId: 'noFixerButFixableValue', type: 'Literal' }],
244+
},
245+
{
246+
code: `
247+
module.exports = {
248+
meta: { fixable: 'whitespace' },
249+
create(context) { context.report({node, message}); }
250+
};
251+
`,
252+
options: [{ catchNoFixerButFixableProperty: true }],
253+
errors: [{ messageId: 'noFixerButFixableValue', type: 'Literal' }],
254+
},
210255
],
211256
});

0 commit comments

Comments
 (0)