From 8e66bf744448b8a3c64bf32c5ba893d16fa7f3ac Mon Sep 17 00:00:00 2001 From: Bryan Mishkin <698306+bmish@users.noreply.github.com> Date: Sun, 10 Jul 2022 22:08:53 -0400 Subject: [PATCH] fix: detect rules with TypeScript `export = rule` syntax (#267) --- lib/utils.js | 9 +++++-- tests/lib/utils.js | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 5b744964..d2bc6505 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -121,8 +121,13 @@ function isTypeScriptRuleHelper(node) { function getRuleExportsESM(ast, scopeManager) { return ( ast.body - .filter((statement) => statement.type === 'ExportDefaultDeclaration') - .map((statement) => statement.declaration) + .filter((statement) => + [ + 'ExportDefaultDeclaration', // export default rule; + 'TSExportAssignment', // export = rule; + ].includes(statement.type) + ) + .map((statement) => statement.declaration || statement.expression) // eslint-disable-next-line unicorn/prefer-object-from-entries .reduce((currentExports, node) => { if (node.type === 'ObjectExpression') { diff --git a/tests/lib/utils.js b/tests/lib/utils.js index c6ecb382..66e1b02d 100644 --- a/tests/lib/utils.js +++ b/tests/lib/utils.js @@ -119,6 +119,9 @@ describe('utils', () => { 'const notRule = foo(); export default notRule;', 'const notRule = function(){}; export default notRule;', 'const notRule = {}; export default notRule;', + 'const notRule = {}; export = notRule;', + 'const notRule: Rule.RuleModule = {}; export = notRule;', + 'export = {};', ].forEach((noRuleCase) => { it(`returns null for ${noRuleCase}`, () => { const ast = typescriptEslintParser.parse(noRuleCase, { @@ -188,6 +191,65 @@ describe('utils', () => { isNewStyle: true, }, + // No helper. + 'export default { create() {}, meta: {} };': { + create: { type: 'FunctionExpression' }, + meta: { type: 'ObjectExpression' }, + isNewStyle: true, + }, + // No helper, `export =` syntax. + 'export = { create() {}, meta: {} };': { + create: { type: 'FunctionExpression' }, + meta: { type: 'ObjectExpression' }, + isNewStyle: true, + }, + // No helper, variable. + 'const rule = { create() {}, meta: {} }; export default rule;': { + create: { type: 'FunctionExpression' }, + meta: { type: 'ObjectExpression' }, + isNewStyle: true, + }, + // no helper, variable with type. + 'const rule: Rule.RuleModule = { create() {}, meta: {} }; export default rule;': + { + create: { type: 'FunctionExpression' }, + meta: { type: 'ObjectExpression' }, + isNewStyle: true, + }, + // No helper, variable, `export =` syntax. + 'const rule = { create() {}, meta: {} }; export = rule;': { + create: { type: 'FunctionExpression' }, + meta: { type: 'ObjectExpression' }, + isNewStyle: true, + }, + // No helper, variable with type, `export =` syntax. + 'const rule: Rule.RuleModule = { create() {}, meta: {} }; export = rule;': + { + create: { type: 'FunctionExpression' }, + meta: { type: 'ObjectExpression' }, + isNewStyle: true, + }, + // Helper, variable, `export =` syntax. + 'const rule = createESLintRule({ create() {}, meta: {} }); export = rule;': + { + create: { type: 'FunctionExpression' }, + meta: { type: 'ObjectExpression' }, + isNewStyle: true, + }, + // Helper, variable with type, `export =` syntax. + 'const rule: Rule.RuleModule = createESLintRule({ create() {}, meta: {} }); export = rule;': + { + create: { type: 'FunctionExpression' }, + meta: { type: 'ObjectExpression' }, + isNewStyle: true, + }, + // Helper, `export =` syntax. + 'export = createESLintRule({ create() {}, meta: {} });': { + create: { type: 'FunctionExpression' }, + meta: { type: 'ObjectExpression' }, + isNewStyle: true, + }, + // Util function with "{} as const". 'export default createESLintRule({ create() {}, meta: {} as const });': {