Skip to content

Commit

Permalink
Update: add fixer for prefer-destructuring (fixes #11151) (#11301)
Browse files Browse the repository at this point in the history
  • Loading branch information
golopot authored and aladdin-add committed Feb 10, 2019
1 parent 173eb38 commit 5eb3121
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 6 deletions.
61 changes: 56 additions & 5 deletions lib/rules/prefer-destructuring.js
Expand Up @@ -19,6 +19,8 @@ module.exports = {
url: "https://eslint.org/docs/rules/prefer-destructuring"
},

fixable: "code",

schema: [
{

Expand Down Expand Up @@ -130,10 +132,55 @@ module.exports = {
*
* @param {ASTNode} reportNode the node to report
* @param {string} type the type of destructuring that should have been done
* @param {Function|null} fix the fix function or null to pass to context.report
* @returns {void}
*/
function report(reportNode, type) {
context.report({ node: reportNode, message: "Use {{type}} destructuring.", data: { type } });
function report(reportNode, type, fix) {
context.report({
node: reportNode,
message: "Use {{type}} destructuring.",
data: { type },
fix
});
}

/**
* Determines if a node should be fixed into object destructuring
*
* The fixer only fixes the simplest case of object destructuring,
* like: `let x = a.x`;
*
* Assignment expression is not fixed.
* Array destructuring is not fixed.
* Renamed property is not fixed.
*
* @param {ASTNode} node the the node to evaluate
* @returns {boolean} whether or not the node should be fixed
*/
function shouldFix(node) {
return node.type === "VariableDeclarator" &&
node.id.type === "Identifier" &&
node.init.type === "MemberExpression" &&
node.id.name === node.init.property.name;
}

/**
* Fix a node into object destructuring.
* This function only handles the simplest case of object destructuring,
* see {@link shouldFix}.
*
* @param {SourceCodeFixer} fixer the fixer object
* @param {ASTNode} node the node to be fixed.
* @returns {Object} a fix for the node
*/
function fixIntoObjectDestructuring(fixer, node) {
const rightNode = node.init;
const sourceCode = context.getSourceCode();

return fixer.replaceText(
node,
`{${rightNode.property.name}} = ${sourceCode.getText(rightNode.object)}`
);
}

/**
Expand All @@ -155,13 +202,17 @@ module.exports = {

if (isArrayIndexAccess(rightNode)) {
if (shouldCheck(reportNode.type, "array")) {
report(reportNode, "array");
report(reportNode, "array", null);
}
return;
}

const fix = shouldFix(reportNode)
? fixer => fixIntoObjectDestructuring(fixer, reportNode)
: null;

if (shouldCheck(reportNode.type, "object") && enforceForRenamedProperties) {
report(reportNode, "object");
report(reportNode, "object", fix);
return;
}

Expand All @@ -172,7 +223,7 @@ module.exports = {
(property.type === "Literal" && leftNode.name === property.value) ||
(property.type === "Identifier" && leftNode.name === property.name && !rightNode.computed)
) {
report(reportNode, "object");
report(reportNode, "object", fix);
}
}
}
Expand Down
35 changes: 34 additions & 1 deletion tests/lib/rules/prefer-destructuring.js
Expand Up @@ -133,33 +133,53 @@ ruleTester.run("prefer-destructuring", rule, {
},
"class Foo extends Bar { static foo() {var foo = super.foo} }",
"foo = bar[foo];",
"var foo = bar[foo];"
"var foo = bar[foo];",
{
code: "var {foo: {bar}} = object;",
options: [{ object: true }]
},
{
code: "var {bar} = object.foo;",
options: [{ object: true }]
}
],

invalid: [
{
code: "var foo = array[0];",
output: null,
errors: [{
message: "Use array destructuring.",
type: "VariableDeclarator"
}]
},
{
code: "foo = array[0];",
output: null,
errors: [{
message: "Use array destructuring.",
type: "AssignmentExpression"
}]
},
{
code: "var foo = object.foo;",
output: "var {foo} = object;",
errors: [{
message: "Use object destructuring.",
type: "VariableDeclarator"
}]
},
{
code: "var foo = object.bar.foo;",
output: "var {foo} = object.bar;",
errors: [{
message: "Use object destructuring.",
type: "VariableDeclarator"
}]
},
{
code: "var foobar = object.bar;",
output: null,
options: [{ VariableDeclarator: { object: true } }, { enforceForRenamedProperties: true }],
errors: [{
message: "Use object destructuring.",
Expand All @@ -168,6 +188,7 @@ ruleTester.run("prefer-destructuring", rule, {
},
{
code: "var foobar = object.bar;",
output: null,
options: [{ object: true }, { enforceForRenamedProperties: true }],
errors: [{
message: "Use object destructuring.",
Expand All @@ -176,6 +197,7 @@ ruleTester.run("prefer-destructuring", rule, {
},
{
code: "var foo = object[bar];",
output: null,
options: [{ VariableDeclarator: { object: true } }, { enforceForRenamedProperties: true }],
errors: [{
message: "Use object destructuring.",
Expand All @@ -184,6 +206,7 @@ ruleTester.run("prefer-destructuring", rule, {
},
{
code: "var foo = object[bar];",
output: null,
options: [{ object: true }, { enforceForRenamedProperties: true }],
errors: [{
message: "Use object destructuring.",
Expand All @@ -192,27 +215,31 @@ ruleTester.run("prefer-destructuring", rule, {
},
{
code: "var foo = object['foo'];",
output: null,
errors: [{
message: "Use object destructuring.",
type: "VariableDeclarator"
}]
},
{
code: "foo = object.foo;",
output: null,
errors: [{
message: "Use object destructuring.",
type: "AssignmentExpression"
}]
},
{
code: "foo = object['foo'];",
output: null,
errors: [{
message: "Use object destructuring.",
type: "AssignmentExpression"
}]
},
{
code: "var foo = array[0];",
output: null,
options: [{ VariableDeclarator: { array: true } }, { enforceForRenamedProperties: true }],
errors: [{
message: "Use array destructuring.",
Expand All @@ -221,6 +248,7 @@ ruleTester.run("prefer-destructuring", rule, {
},
{
code: "foo = array[0];",
output: null,
options: [{ AssignmentExpression: { array: true } }],
errors: [{
message: "Use array destructuring.",
Expand All @@ -229,6 +257,7 @@ ruleTester.run("prefer-destructuring", rule, {
},
{
code: "var foo = array[0];",
output: null,
options: [
{
VariableDeclarator: { array: true },
Expand All @@ -243,6 +272,7 @@ ruleTester.run("prefer-destructuring", rule, {
},
{
code: "var foo = array[0];",
output: null,
options: [
{
VariableDeclarator: { array: true },
Expand All @@ -256,6 +286,7 @@ ruleTester.run("prefer-destructuring", rule, {
},
{
code: "foo = array[0];",
output: null,
options: [
{
VariableDeclarator: { array: false },
Expand All @@ -269,6 +300,7 @@ ruleTester.run("prefer-destructuring", rule, {
},
{
code: "foo = object.foo;",
output: null,
options: [
{
VariableDeclarator: { array: true, object: false },
Expand All @@ -282,6 +314,7 @@ ruleTester.run("prefer-destructuring", rule, {
},
{
code: "class Foo extends Bar { static foo() {var bar = super.foo.bar} }",
output: "class Foo extends Bar { static foo() {var {bar} = super.foo} }",
errors: [{
message: "Use object destructuring.",
type: "VariableDeclarator"
Expand Down

0 comments on commit 5eb3121

Please sign in to comment.