diff --git a/CHANGELOG.md b/CHANGELOG.md index f8cf89d9a..821d943ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311]) - [`no-restricted-paths`]: fix an error message ([#2466], thanks [@AdriAt360]) - [`no-restricted-paths`]: use `Minimatch.match` instead of `minimatch` to comply with Windows Native paths ([#2466], thanks [@AdriAt360]) +- [`order`]: require with member expression could not be fixed if alphabetize.order was used ([#2490], thanks [@msvab]) ### Changed - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim]) @@ -994,6 +995,7 @@ for info on changes for earlier releases. [`memo-parser`]: ./memo-parser/README.md +[#2490]: https://github.com/import-js/eslint-plugin-import/pull/2490 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466 [#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440 [#2427]: https://github.com/import-js/eslint-plugin-import/pull/2427 @@ -1638,6 +1640,7 @@ for info on changes for earlier releases. [@MikeyBeLike]: https://github.com/MikeyBeLike [@mplewis]: https://github.com/mplewis [@mrmckeb]: https://github.com/mrmckeb +[@msvab]: https://github.com/msvab [@mx-bernhard]: https://github.com/mx-bernhard [@nickofthyme]: https://github.com/nickofthyme [@nicolashenry]: https://github.com/nicolashenry @@ -1645,8 +1648,8 @@ for info on changes for earlier releases. [@ntdb]: https://github.com/ntdb [@nwalters512]: https://github.com/nwalters512 [@ombene]: https://github.com/ombene -[@OutdatedVersion]: https://github.com/OutdatedVersion [@ota-meshi]: https://github.com/ota-meshi +[@OutdatedVersion]: https://github.com/OutdatedVersion [@panrafal]: https://github.com/panrafal [@paztis]: https://github.com/paztis [@pcorpet]: https://github.com/pcorpet diff --git a/src/rules/order.js b/src/rules/order.js index df35db065..3f033eb82 100644 --- a/src/rules/order.js +++ b/src/rules/order.js @@ -129,7 +129,17 @@ function findStartOfLineWithComments(sourceCode, node) { return result; } -function isPlainRequireModule(node) { +function isRequireExpression(expr) { + return expr != null && + expr.type === 'CallExpression' && + expr.callee != null && + expr.callee.name === 'require' && + expr.arguments != null && + expr.arguments.length === 1 && + expr.arguments[0].type === 'Literal'; +} + +function isSupportedRequireModule(node) { if (node.type !== 'VariableDeclaration') { return false; } @@ -137,16 +147,17 @@ function isPlainRequireModule(node) { return false; } const decl = node.declarations[0]; - const result = decl.id && + const isPlainRequire = decl.id && + (decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern') && + isRequireExpression(decl.init); + const isRequireWithMemberExpression = decl.id && (decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern') && decl.init != null && decl.init.type === 'CallExpression' && decl.init.callee != null && - decl.init.callee.name === 'require' && - decl.init.arguments != null && - decl.init.arguments.length === 1 && - decl.init.arguments[0].type === 'Literal'; - return result; + decl.init.callee.type === 'MemberExpression' && + isRequireExpression(decl.init.callee.object); + return isPlainRequire || isRequireWithMemberExpression; } function isPlainImportModule(node) { @@ -158,7 +169,7 @@ function isPlainImportEquals(node) { } function canCrossNodeWhileReorder(node) { - return isPlainRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node); + return isSupportedRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node); } function canReorderItems(firstNode, secondNode) { @@ -276,7 +287,7 @@ function getSorter(ascending) { result = a < b ? -1 : 1; } } - + return result * multiplier; }; } diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js index f5c3bb393..e8a5143c5 100644 --- a/tests/src/rules/order.js +++ b/tests/src/rules/order.js @@ -896,13 +896,13 @@ ruleTester.run('order', rule, { import express from 'express'; import service from '@/api/service'; - + import fooParent from '../foo'; - + import fooSibling from './foo'; - + import index from './'; - + import internalDoesNotExistSoIsUnknown from '@/does-not-exist'; `, options: [ @@ -2289,7 +2289,7 @@ ruleTester.run('order', rule, { import b from "foo-bar"; `, errors: [{ - message: '`foo-bar` import should occur after import of `foo/barfoo`', + message: '`foo-bar` import should occur after import of `foo/barfoo`', }], }), // Option alphabetize {order: 'asc': caseInsensitive: true} @@ -2336,6 +2336,23 @@ ruleTester.run('order', rule, { message: '`foo` import should occur before import of `Bar`', }], }), + // Option alphabetize {order: 'asc'} and require with member expression + test({ + code: ` + const b = require('./b').get(); + const a = require('./a'); + `, + output: ` + const a = require('./a'); + const b = require('./b').get(); + `, + options: [{ + alphabetize: { order: 'asc' }, + }], + errors: [{ + message: '`./a` import should occur before import of `./b`', + }], + }), // Alphabetize with parent paths test({ code: `