diff --git a/lib/rules/operator-assignment.js b/lib/rules/operator-assignment.js index e294668b42b..b19ba0d02e1 100644 --- a/lib/rules/operator-assignment.js +++ b/lib/rules/operator-assignment.js @@ -71,6 +71,9 @@ function same(a, b) { */ return same(a.object, b.object) && same(a.property, b.property); + case "ThisExpression": + return true; + default: return false; } @@ -83,8 +86,14 @@ function same(a, b) { * @returns {boolean} `true` if the node can be fixed */ function canBeFixed(node) { - return node.type === "Identifier" || - node.type === "MemberExpression" && node.object.type === "Identifier" && (!node.computed || node.property.type === "Literal"); + return ( + node.type === "Identifier" || + ( + node.type === "MemberExpression" && + (node.object.type === "Identifier" || node.object.type === "ThisExpression") && + (!node.computed || node.property.type === "Literal") + ) + ); } module.exports = { diff --git a/tests/lib/rules/operator-assignment.js b/tests/lib/rules/operator-assignment.js index 2f87532535e..4c6819c2703 100644 --- a/tests/lib/rules/operator-assignment.js +++ b/tests/lib/rules/operator-assignment.js @@ -72,7 +72,19 @@ ruleTester.run("operator-assignment", rule, { options: ["never"] }, "x = y ** x", - "x = x * y + z" + "x = x * y + z", + { + code: "this.x = this.y + z", + options: ["always"] + }, + { + code: "this.x = foo.x + y", + options: ["always"] + }, + { + code: "this.x = foo.this.x + y", + options: ["always"] + } ], invalid: [{ @@ -169,6 +181,15 @@ ruleTester.run("operator-assignment", rule, { output: "foo.bar = foo.bar + baz", options: ["never"], errors: UNEXPECTED_OPERATOR_ASSIGNMENT + }, { + code: "this.foo = this.foo + bar", + output: "this.foo += bar", + errors: EXPECTED_OPERATOR_ASSIGNMENT + }, { + code: "this.foo += bar", + output: "this.foo = this.foo + bar", + options: ["never"], + errors: UNEXPECTED_OPERATOR_ASSIGNMENT }, { code: "foo.bar.baz = foo.bar.baz + qux", output: null, // not fixed; fixing would cause a foo.bar getter to activate once rather than twice @@ -178,19 +199,41 @@ ruleTester.run("operator-assignment", rule, { output: null, // not fixed; fixing would cause a foo.bar getter to activate twice rather than once options: ["never"], errors: UNEXPECTED_OPERATOR_ASSIGNMENT + }, { + code: "this.foo.bar = this.foo.bar + baz", + output: null, // not fixed; fixing would cause a this.foo getter to activate once rather than twice + errors: EXPECTED_OPERATOR_ASSIGNMENT + }, { + code: "this.foo.bar += baz", + output: null, // not fixed; fixing would cause a this.foo getter to activate twice rather than once + options: ["never"], + errors: UNEXPECTED_OPERATOR_ASSIGNMENT }, { code: "foo[bar] = foo[bar] + baz", output: null, // not fixed; fixing would cause bar.toString() to get called once instead of twice errors: EXPECTED_OPERATOR_ASSIGNMENT + }, { + code: "this[foo] = this[foo] + bar", + output: null, // not fixed; fixing would cause foo.toString() to get called once instead of twice + errors: EXPECTED_OPERATOR_ASSIGNMENT }, { code: "foo[bar] >>>= baz", output: null, // not fixed; fixing would cause bar.toString() to get called twice instead of once options: ["never"], errors: UNEXPECTED_OPERATOR_ASSIGNMENT + }, { + code: "this[foo] >>>= bar", + output: null, // not fixed; fixing would cause foo.toString() to get called twice instead of once + options: ["never"], + errors: UNEXPECTED_OPERATOR_ASSIGNMENT }, { code: "foo[5] = foo[5] / baz", output: "foo[5] /= baz", // this is ok because 5 is a literal, so toString won't get called errors: EXPECTED_OPERATOR_ASSIGNMENT + }, { + code: "this[5] = this[5] / foo", + output: "this[5] /= foo", // this is ok because 5 is a literal, so toString won't get called + errors: EXPECTED_OPERATOR_ASSIGNMENT }, { code: "/*1*/x/*2*/./*3*/y/*4*/= x.y +/*5*/z/*6*/./*7*/w/*8*/;", output: "/*1*/x/*2*/./*3*/y/*4*/+=/*5*/z/*6*/./*7*/w/*8*/;", // these comments are preserved