diff --git a/scripts/eslint/rules/no-keywords.ts b/scripts/eslint/rules/no-keywords.ts index b7aa08336c4..89180666647 100644 --- a/scripts/eslint/rules/no-keywords.ts +++ b/scripts/eslint/rules/no-keywords.ts @@ -36,35 +36,83 @@ export = createRule({ "any", ]; - const hasKeyword = (name: string) => keywords.includes(name); + const isKeyword = (name: string) => keywords.includes(name); - const shouldReport = (node: TSESTree.Identifier) => { - if (!node || !node.parent || !hasKeyword(node.name)) { - return false; - } - - const parent = node.parent; - if (parent.type === AST_NODE_TYPES.FunctionDeclaration || parent.type === AST_NODE_TYPES.FunctionExpression) { - return !(parent.id && hasKeyword(parent.id.name)); - } - - if (parent.type === AST_NODE_TYPES.TSMethodSignature && parent.key.type === AST_NODE_TYPES.Identifier) { - return !(parent.key && hasKeyword(parent.key.name)); - } - - return [ - AST_NODE_TYPES.ArrowFunctionExpression, - AST_NODE_TYPES.VariableDeclarator, - AST_NODE_TYPES.TSFunctionType, - ].includes(node.parent.type); + const report = (node: TSESTree.Identifier) => { + context.report({ messageId: "noKeywordsError", data: { name: node.name }, node }); }; - const check = (node: TSESTree.Identifier) => { - if (shouldReport(node)) { - context.report({ messageId: "noKeywordsError", data: { name: node.name }, node }); - } + const checkProperties = (node: TSESTree.ObjectPattern): void => { + node.properties.forEach(property => { + if ( + property && + property.type === AST_NODE_TYPES.Property && + property.key.type === AST_NODE_TYPES.Identifier && + isKeyword(property.key.name) + ) { + report(property.key); + } + }); }; - return { Identifier: check }; + const checkElements = (node: TSESTree.ArrayPattern): void => { + node.elements.forEach(element => { + if ( + element && + element.type === AST_NODE_TYPES.Identifier && + isKeyword(element.name) + ) { + report(element); + } + }); + }; + + const checkParams = ( + node: + | TSESTree.ArrowFunctionExpression + | TSESTree.FunctionDeclaration + | TSESTree.FunctionExpression + | TSESTree.TSMethodSignature + | TSESTree.TSFunctionType + ): void => { + if (!node || !node.params || !node.params.length) { + return; + } + + node.params.forEach(param => { + if ( + param && + param.type === AST_NODE_TYPES.Identifier && + isKeyword(param.name) + ) { + report(param); + } + }); + }; + + return { + VariableDeclarator(node) { + if (node.id.type === AST_NODE_TYPES.ObjectPattern) { + checkProperties(node.id); + } + + if (node.id.type === AST_NODE_TYPES.ArrayPattern) { + checkElements(node.id); + } + + if ( + node.id.type === AST_NODE_TYPES.Identifier && + isKeyword(node.id.name) + ) { + report(node.id); + } + }, + + ArrowFunctionExpression: checkParams, + FunctionDeclaration: checkParams, + FunctionExpression: checkParams, + TSMethodSignature: checkParams, + TSFunctionType: checkParams, + }; }, }); diff --git a/scripts/eslint/tests/no-keywords.test.ts b/scripts/eslint/tests/no-keywords.test.ts index e2b75838b5f..18c34872059 100644 --- a/scripts/eslint/tests/no-keywords.test.ts +++ b/scripts/eslint/tests/no-keywords.test.ts @@ -52,6 +52,31 @@ const obj = { }; `, }, + { + code: `() => undefined`, + }, + { + code: `let a = 2;`, + }, + { + code: `let b: any;`, + }, + { + code: `function foo(a: any) { }`, + }, + { + code: `let [a] = [5];`, + }, + { + code: `const { a } = { a: 5 };`, + }, + { + code: ` +interface Foo { + number: string; +} + `, + } ], invalid: [ @@ -95,5 +120,39 @@ interface A { { messageId: "noKeywordsError" }, ], }, + { + code: `let undefined = 8;`, + errors: [{ messageId: "noKeywordsError" }], + }, + { + code: `let boolean: boolean;`, + errors: [{ messageId: "noKeywordsError" }], + }, + { + code: `function foo(any: any) { }`, + errors: [{ messageId: "noKeywordsError" }], + }, + { + code: `let [number] = [3];`, + errors: [{ messageId: "noKeywordsError" }], + }, + { + code: `let { String } = { String: 1 };`, + errors: [{ messageId: "noKeywordsError" }], + }, + { + code: `let [number, string] = [3, ''];`, + errors: [ + { messageId: "noKeywordsError" }, + { messageId: "noKeywordsError" } + ], + }, + { + code: `let { String, Boolean } = { String: 1, Boolean: false };`, + errors: [ + { messageId: "noKeywordsError" }, + { messageId: "noKeywordsError" } + ], + }, ], });