diff --git a/lib/rules/id-blacklist.js b/lib/rules/id-blacklist.js index cb6e5e215f6..ddff9363aee 100644 --- a/lib/rules/id-blacklist.js +++ b/lib/rules/id-blacklist.js @@ -81,6 +81,28 @@ module.exports = { ); } + /** + * Checks whether the given node is a renamed identifier node in an ObjectPattern destructuring. + * + * Examples: + * const { a : b } = foo; // node `a` is renamed node. + * @param {ASTNode} node `Identifier` node to check. + * @returns {boolean} `true` if the node is a renamed node in an ObjectPattern destructuring. + */ + function isRenamedInDestructuring(node) { + const parent = node.parent; + + return ( + ( + !parent.computed && + parent.type === "Property" && + parent.parent.type === "ObjectPattern" && + parent.value !== node && + parent.key === node + ) + ); + } + /** * Verifies if we should report an error or not. * @param {ASTNode} node The node to check @@ -92,8 +114,8 @@ module.exports = { return ( parent.type !== "CallExpression" && parent.type !== "NewExpression" && - parent.parent.type !== "ObjectPattern" && !isRenamedImport(node) && + !isRenamedInDestructuring(node) && isInvalid(node.name) ); } @@ -141,6 +163,24 @@ module.exports = { if (isInvalid(name)) { report(node); } + + // Report the last identifier in an ObjectPattern destructuring. + } else if ( + ( + effectiveParent.type === "Property" && + effectiveParent.value === node.parent && + effectiveParent.parent.type === "ObjectPattern" + ) || + effectiveParent.type === "RestElement" || + effectiveParent.type === "ArrayPattern" || + ( + effectiveParent.type === "AssignmentPattern" && + effectiveParent.left === node.parent + ) + ) { + if (isInvalid(name)) { + report(node); + } } } else if (shouldReport(node)) { diff --git a/tests/lib/rules/id-blacklist.js b/tests/lib/rules/id-blacklist.js index f047ca07876..11c85ae0885 100644 --- a/tests/lib/rules/id-blacklist.js +++ b/tests/lib/rules/id-blacklist.js @@ -77,22 +77,42 @@ ruleTester.run("id-blacklist", rule, { }, { code: "const {foo: bar} = baz", - options: ["foo", "bar"], + options: ["foo"], parserOptions: { ecmaVersion: 6 } }, { code: "const {foo: {bar: baz}} = qux", - options: ["foo", "bar", "baz"], + options: ["foo", "bar"], parserOptions: { ecmaVersion: 6 } }, { code: "function foo({ bar: baz }) {}", - options: ["bar", "baz"], + options: ["bar"], parserOptions: { ecmaVersion: 6 } }, { code: "function foo({ bar: {baz: qux} }) {}", - options: ["bar", "baz", "qux"], + options: ["bar", "baz"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "function foo({baz} = obj.qux) {}", + options: ["qux"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "function foo({ foo: {baz} = obj.qux }) {}", + options: ["qux"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "({a: bar = obj.baz});", + options: ["baz"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "({foo: {a: bar = obj.baz}} = qux);", + options: ["baz"], parserOptions: { ecmaVersion: 6 } }, { @@ -126,6 +146,16 @@ ruleTester.run("id-blacklist", rule, { { code: "foo.bar", options: ["bar"] + }, + { + code: "({foo: obj.bar.bar.bar.baz} = {});", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "({[obj.bar]: a = baz} = qux);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 } } ], invalid: [ @@ -522,6 +552,309 @@ ruleTester.run("id-blacklist", rule, { errors: [ error ] + }, + { + code: "const {foo} = baz", + options: ["foo"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "foo" }, + type: "Identifier", + column: 8 + } + ] + }, + { + code: "const {foo: bar} = baz", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 13 + } + ] + }, + { + code: "const {[foo]: bar} = baz", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "foo" }, + type: "Identifier", + column: 9 + }, + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 15 + } + ] + }, + { + code: "const {foo: {bar: baz}} = qux", + options: ["foo", "bar", "baz"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "baz" }, + type: "Identifier", + column: 19 + } + ] + }, + { + code: "const {foo: {[bar]: baz}} = qux", + options: ["foo", "bar", "baz"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 15 + }, + { + messageId: "blacklisted", + data: { name: "baz" }, + type: "Identifier", + column: 21 + } + ] + }, + { + code: "const {[foo]: {[bar]: baz}} = qux", + options: ["foo", "bar", "baz"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "foo" }, + type: "Identifier", + column: 9 + }, + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 17 + }, + { + messageId: "blacklisted", + data: { name: "baz" }, + type: "Identifier", + column: 23 + } + ] + }, + { + code: "function foo({ bar: baz }) {}", + options: ["bar", "baz"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "baz" }, + type: "Identifier", + column: 21 + } + ] + }, + { + code: "function foo({ bar: {baz: qux} }) {}", + options: ["bar", "baz", "qux"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "qux" }, + type: "Identifier", + column: 27 + } + ] + }, + { + code: "({foo: obj.bar} = baz);", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 12 + } + ] + }, + { + code: "({foo: obj.bar.bar.bar.baz} = {});", + options: ["foo", "bar", "baz"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "baz" }, + type: "Identifier", + column: 24 + } + ] + }, + { + code: "({[foo]: obj.bar} = baz);", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "foo" }, + type: "Identifier", + column: 4 + }, + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 14 + } + ] + }, + { + code: "({foo: { a: obj.bar }} = baz);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 17 + } + ] + }, + { + code: "({a: obj.bar = baz} = qux);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 10 + } + ] + }, + { + code: "({a: obj.bar.bar.baz = obj.qux} = obj.qux);", + options: ["a", "bar", "baz", "qux"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "baz" }, + type: "Identifier", + column: 18 + } + ] + }, + { + code: "({a: obj[bar] = obj.qux} = obj.qux);", + options: ["a", "bar", "baz", "qux"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 10 + } + ] + }, + { + code: "({a: [obj.bar] = baz} = qux);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 11 + } + ] + }, + { + code: "({foo: { a: obj.bar = baz}} = qux);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 17 + } + ] + }, + { + code: "({foo: { [a]: obj.bar }} = baz);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 19 + } + ] + }, + { + code: "({...obj.bar} = baz);", + options: ["bar"], + parserOptions: { ecmaVersion: 9 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 10 + } + ] + }, + { + code: "([obj.bar] = baz);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 7 + } + ] + }, + { + code: "const [bar] = baz;", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "blacklisted", + data: { name: "bar" }, + type: "Identifier", + column: 8 + } + ] } ] });