Skip to content

Commit df39419

Browse files
committed
Breaking: Update fixer-return and prefer-replace-text rules to also apply to suggestion fixer functions
1 parent d85c446 commit df39419

File tree

5 files changed

+166
-20
lines changed

5 files changed

+166
-20
lines changed

lib/rules/fixer-return.js

+1-11
Original file line numberDiff line numberDiff line change
@@ -98,22 +98,12 @@ module.exports = {
9898

9999
// Stacks this function's information.
100100
onCodePathStart (codePath, node) {
101-
const parent = node.parent;
102-
103-
// Whether we are inside the fixer function we care about.
104-
const shouldCheck = ['FunctionExpression', 'ArrowFunctionExpression'].includes(node.type) &&
105-
parent.parent.type === 'ObjectExpression' &&
106-
parent.parent.parent.type === 'CallExpression' &&
107-
contextIdentifiers.has(parent.parent.parent.callee.object) &&
108-
parent.parent.parent.callee.property.name === 'report' &&
109-
utils.getReportInfo(parent.parent.parent.arguments).fix === node;
110-
111101
funcInfo = {
112102
upper: funcInfo,
113103
codePath,
114104
hasYieldWithFixer: false,
115105
hasReturnWithFixer: false,
116-
shouldCheck,
106+
shouldCheck: utils.isAutoFixerFunction(node, contextIdentifiers) || utils.isSuggestionFixerFunction(node, contextIdentifiers),
117107
node,
118108
};
119109
},

lib/rules/prefer-replace-text.js

+1-9
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,10 @@ module.exports = {
4343

4444
// Stacks this function's information.
4545
onCodePathStart (codePath, node) {
46-
const parent = node.parent;
47-
const shouldCheck = (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') &&
48-
parent.parent.type === 'ObjectExpression' &&
49-
parent.parent.parent.type === 'CallExpression' &&
50-
contextIdentifiers.has(parent.parent.parent.callee.object) &&
51-
parent.parent.parent.callee.property.name === 'report' &&
52-
utils.getReportInfo(parent.parent.parent.arguments, context).fix === node;
53-
5446
funcInfo = {
5547
upper: funcInfo,
5648
codePath,
57-
shouldCheck,
49+
shouldCheck: utils.isAutoFixerFunction(node, contextIdentifiers) || utils.isSuggestionFixerFunction(node, contextIdentifiers),
5850
node,
5951
};
6052
},

lib/utils.js

+40
Original file line numberDiff line numberDiff line change
@@ -385,4 +385,44 @@ module.exports = {
385385
`,\n${propertyText}`
386386
);
387387
},
388+
389+
/**
390+
* Whether the provided node represents an autofixer function.
391+
* @param {Node} node
392+
* @param {Node[]} contextIdentifiers
393+
* @returns {boolean}
394+
*/
395+
isAutoFixerFunction (node, contextIdentifiers) {
396+
const parent = node.parent;
397+
return ['FunctionExpression', 'ArrowFunctionExpression'].includes(node.type) &&
398+
parent.parent.type === 'ObjectExpression' &&
399+
parent.parent.parent.type === 'CallExpression' &&
400+
contextIdentifiers.has(parent.parent.parent.callee.object) &&
401+
parent.parent.parent.callee.property.name === 'report' &&
402+
this.getReportInfo(parent.parent.parent.arguments).fix === node;
403+
},
404+
405+
/**
406+
* Whether the provided node represents an suggestion fixer function.
407+
* @param {Node} node
408+
* @param {Node[]} contextIdentifiers
409+
* @returns {boolean}
410+
*/
411+
isSuggestionFixerFunction (node, contextIdentifiers) {
412+
const parent = node.parent;
413+
return (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') &&
414+
parent.type === 'Property' &&
415+
parent.key.type === 'Identifier' &&
416+
parent.key.name === 'fix' &&
417+
parent.parent.type === 'ObjectExpression' &&
418+
parent.parent.parent.type === 'ArrayExpression' &&
419+
parent.parent.parent.parent.type === 'Property' &&
420+
parent.parent.parent.parent.key.type === 'Identifier' &&
421+
parent.parent.parent.parent.key.name === 'suggest' &&
422+
parent.parent.parent.parent.parent.type === 'ObjectExpression' &&
423+
parent.parent.parent.parent.parent.parent.type === 'CallExpression' &&
424+
contextIdentifiers.has(parent.parent.parent.parent.parent.parent.callee.object) &&
425+
parent.parent.parent.parent.parent.parent.callee.property.name === 'report' &&
426+
this.getReportInfo(parent.parent.parent.parent.parent.parent.arguments).suggest === parent.parent.parent;
427+
},
388428
};

tests/lib/rules/fixer-return.js

+87
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,55 @@ ruleTester.run('fixer-return', rule, {
221221
}
222222
};
223223
`,
224+
225+
// Suggestion
226+
`
227+
module.exports = {
228+
create: function(context) {
229+
context.report( {
230+
suggest: [
231+
{
232+
fix: function(fixer) {
233+
return fixer.foo();
234+
}
235+
}
236+
]
237+
});
238+
}
239+
};
240+
`,
241+
// Suggestion but wrong `suggest` key
242+
`
243+
module.exports = {
244+
create: function(context) {
245+
context.report( {
246+
notSuggest: [
247+
{
248+
fix: function(fixer) {
249+
fixer.foo();
250+
}
251+
}
252+
]
253+
});
254+
}
255+
};
256+
`,
257+
// Suggestion but wrong `fix` key
258+
`
259+
module.exports = {
260+
create: function(context) {
261+
context.report( {
262+
suggest: [
263+
{
264+
notFix: function(fixer) {
265+
fixer.foo();
266+
}
267+
}
268+
]
269+
});
270+
}
271+
};
272+
`,
224273
],
225274

226275
invalid: [
@@ -239,6 +288,25 @@ ruleTester.run('fixer-return', rule, {
239288
`,
240289
errors: [{ messageId: 'missingFix', type: 'FunctionExpression', line: 5, column: 24 }],
241290
},
291+
{
292+
// Fix but missing return (suggestion)
293+
code: `
294+
module.exports = {
295+
create: function(context) {
296+
context.report({
297+
suggest: [
298+
{
299+
fix(fixer) {
300+
fixer.foo();
301+
}
302+
}
303+
]
304+
});
305+
}
306+
};
307+
`,
308+
errors: [{ messageId: 'missingFix', type: 'FunctionExpression', line: 7, column: 36 }],
309+
},
242310
{
243311
// Fix but missing return (arrow function, report on arrow)
244312
code: `
@@ -254,6 +322,25 @@ ruleTester.run('fixer-return', rule, {
254322
`,
255323
errors: [{ messageId: 'missingFix', type: 'ArrowFunctionExpression', line: 5, endLine: 5, column: 34, endColumn: 36 }],
256324
},
325+
{
326+
// Fix but missing return (arrow function, report on arrow, suggestion)
327+
code: `
328+
module.exports = {
329+
create: function(context) {
330+
context.report({
331+
suggest: [
332+
{
333+
fix: (fixer) => {
334+
fixer.foo();
335+
}
336+
}
337+
]
338+
});
339+
}
340+
};
341+
`,
342+
errors: [{ messageId: 'missingFix', type: 'ArrowFunctionExpression', line: 7, endLine: 7, column: 46, endColumn: 48 }],
343+
},
257344
{
258345
// With no autofix (arrow function, explicit return, report on arrow)
259346
code: `

tests/lib/rules/prefer-replace-text.js

+37
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,23 @@ ruleTester.run('prefer-placeholders', rule, {
5252
`
5353
fixer.replaceTextRange([node.range[0], node.range[1]], '');
5454
`,
55+
56+
// Suggestion
57+
`
58+
module.exports = {
59+
create(context) {
60+
context.report({
61+
suggest: [
62+
{
63+
fix(fixer) {
64+
return fixer.replaceTextRange([start, end], '');
65+
}
66+
}
67+
]
68+
});
69+
}
70+
};
71+
`,
5572
],
5673

5774
invalid: [
@@ -123,5 +140,25 @@ ruleTester.run('prefer-placeholders', rule, {
123140
`,
124141
errors: [ERROR],
125142
},
143+
144+
{
145+
// Suggestion fixer
146+
code: `
147+
module.exports = {
148+
create(context) {
149+
context.report({
150+
suggest: [
151+
{
152+
fix(fixer) {
153+
return fixer.replaceTextRange([node.range[0], node.range[1]], '');
154+
}
155+
}
156+
]
157+
});
158+
}
159+
};
160+
`,
161+
errors: [ERROR],
162+
},
126163
],
127164
});

0 commit comments

Comments
 (0)