Skip to content

Commit da652aa

Browse files
authored
Update: Add catchNoFixerButFixableProperty option (default false) to catch non-fixable rules that enable the fixable property in require-meta-fixable rule (#165)
* New: Add `catchNoFixerButFixableProperty` option (default false) to catch non-fixable rules that enable the fixable property in `require-meta-fixable` rule * add tests * fix variable name
1 parent 95021dd commit da652aa

File tree

3 files changed

+114
-9
lines changed

3 files changed

+114
-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 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

+18-1
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 catchNoFixerButFixableProperty = 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 (catchNoFixerButFixableProperty && !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

+79-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,53 @@ 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+
},
160+
// catchNoFixerButFixableProperty = true
161+
{
162+
code: `
163+
module.exports = {
164+
meta: { fixable: 'code' },
165+
create(context) {
166+
foo
167+
? context.report({ node, message })
168+
: context.report({ node, message, fix });
169+
}
170+
};
171+
`,
172+
options: [{ catchNoFixerButFixableProperty: true }],
173+
},
135174
],
136175

137176
invalid: [
@@ -207,5 +246,37 @@ ruleTester.run('require-meta-fixable', rule, {
207246
`,
208247
errors: [{ messageId: 'missing', type: 'Identifier' }],
209248
},
249+
250+
// catchNoFixerButFixableProperty = true
251+
{
252+
code: `
253+
module.exports = {
254+
meta: { fixable: 'code' },
255+
create(context) { context.report({node, message}); }
256+
};
257+
`,
258+
options: [{ catchNoFixerButFixableProperty: true }],
259+
errors: [{ messageId: 'noFixerButFixableValue', type: 'Literal' }],
260+
},
261+
{
262+
code: `
263+
module.exports = {
264+
meta: { fixable: 'whitespace' },
265+
create(context) { context.report({node, message}); }
266+
};
267+
`,
268+
options: [{ catchNoFixerButFixableProperty: true }],
269+
errors: [{ messageId: 'noFixerButFixableValue', type: 'Literal' }],
270+
},
271+
{
272+
code: `
273+
module.exports = {
274+
meta: { fixable: null },
275+
create(context) { context.report({node, message, fix}); }
276+
};
277+
`,
278+
options: [{ catchNoFixerButFixableProperty: true }],
279+
errors: [{ messageId: 'missing', type: 'Literal' }],
280+
},
210281
],
211282
});

0 commit comments

Comments
 (0)