diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b47aaa55..10c77d4e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel ### Fixed - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella]) +- [`order`]: ignore non-module-level requires ([#1940], thanks [@golopot]) ## [2.22.1] - 2020-09-27 ### Fixed @@ -735,6 +736,7 @@ for info on changes for earlier releases. [`memo-parser`]: ./memo-parser/README.md +[#1940]: https://github.com/benmosher/eslint-plugin-import/pull/1940 [#1889]: https://github.com/benmosher/eslint-plugin-import/pull/1889 [#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878 [#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854 diff --git a/src/rules/order.js b/src/rules/order.js index 1d7d3efd6..fe2376cfe 100644 --- a/src/rules/order.js +++ b/src/rules/order.js @@ -333,9 +333,21 @@ function registerNode(context, importEntry, ranks, imported, excludedImportTypes } } -function isInVariableDeclarator(node) { - return node && - (node.type === 'VariableDeclarator' || isInVariableDeclarator(node.parent)) +function isModuleLevelRequire(node) { + let n = node + // Handle cases like `const baz = require('foo').bar.baz` + // and `const foo = require('foo')()` + while ( + (n.parent.type === 'MemberExpression' && n.parent.object === n) || + (n.parent.type === 'CallExpression' && n.parent.callee === n) + ) { + n = n.parent + } + return ( + n.parent.type === 'VariableDeclarator' && + n.parent.parent.type === 'VariableDeclaration' && + n.parent.parent.parent.type === 'Program' + ) } const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object'] @@ -583,14 +595,6 @@ module.exports = { } } let imported = [] - let level = 0 - - function incrementLevel() { - level++ - } - function decrementLevel() { - level-- - } return { ImportDeclaration: function handleImports(node) { @@ -641,7 +645,7 @@ module.exports = { ) }, CallExpression: function handleRequires(node) { - if (level !== 0 || !isStaticRequire(node) || !isInVariableDeclarator(node.parent)) { + if (!isStaticRequire(node) || !isModuleLevelRequire(node)) { return } const name = node.arguments[0].value @@ -671,16 +675,6 @@ module.exports = { imported = [] }, - FunctionDeclaration: incrementLevel, - FunctionExpression: incrementLevel, - ArrowFunctionExpression: incrementLevel, - BlockStatement: incrementLevel, - ObjectExpression: incrementLevel, - 'FunctionDeclaration:exit': decrementLevel, - 'FunctionExpression:exit': decrementLevel, - 'ArrowFunctionExpression:exit': decrementLevel, - 'BlockStatement:exit': decrementLevel, - 'ObjectExpression:exit': decrementLevel, } }, } diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js index 0c5405823..497911ffb 100644 --- a/tests/src/rules/order.js +++ b/tests/src/rules/order.js @@ -74,7 +74,7 @@ ruleTester.run('order', rule, { var result = add(1, 2); var _ = require('lodash');`, }), - // Ignore requires that are not at the top-level + // Ignore requires that are not at the top-level #1 test({ code: ` var index = require('./'); @@ -86,6 +86,18 @@ ruleTester.run('order', rule, { require('fs'); }`, }), + // Ignore requires that are not at the top-level #2 + test({ + code: ` + const foo = [ + require('./foo'), + require('fs'), + ]`, + }), + // Ignore requires in template literal (#1936) + test({ + code: "const foo = `${require('./a')} ${require('fs')}`", + }), // Ignore unknown/invalid cases test({ code: `