Skip to content

Commit 62b554b

Browse files
manuthljharb
authored andcommitted
[New] order: Add support for TypeScript's "import equals"-expressions
1 parent 2e72af5 commit 62b554b

File tree

4 files changed

+98
-22
lines changed

4 files changed

+98
-22
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
99
### Added
1010
- [`import/default`]: support default export in TSExportAssignment ([#1528], thanks [@joaovieira])
1111
- [`no-cycle`]: add `ignoreExternal` option ([#1681], thanks [@sveyret])
12+
- [`order`]: Add support for TypeScript's "import equals"-expressions ([#1785], thanks [@manuth])
1213

1314
### Fixed
1415
- [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
@@ -678,6 +679,7 @@ for info on changes for earlier releases.
678679
[`memo-parser`]: ./memo-parser/README.md
679680

680681
[#1788]: https://github.com/benmosher/eslint-plugin-import/pull/1788
682+
[#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
681683
[#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
682684
[#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
683685
[#1724]: https://github.com/benmosher/eslint-plugin-import/pull/1724
@@ -1162,3 +1164,4 @@ for info on changes for earlier releases.
11621164
[@atos1990]: https://github.com/atos1990
11631165
[@Hypnosphi]: https://github.com/Hypnosphi
11641166
[@nickofthyme]: https://github.com/nickofthyme
1167+
[@manuth]: https://github.com/manuth

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
"watch": "npm run tests-only -- -- --watch",
2626
"pretest": "linklocal",
2727
"posttest": "eslint .",
28-
"mocha": "nyc -s mocha",
29-
"tests-only": "cross-env BABEL_ENV=test npm run mocha tests/src",
28+
"mocha": "cross-env BABEL_ENV=test nyc -s mocha",
29+
"tests-only": "npm run mocha tests/src",
3030
"test": "npm run tests-only",
3131
"test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
3232
"test-all": "npm test && for resolver in ./resolvers/*; do cd $resolver && npm test && cd ../..; done",

src/rules/order.js

+35-20
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,12 @@ function isPlainImportModule(node) {
157157
return node.type === 'ImportDeclaration' && node.specifiers != null && node.specifiers.length > 0
158158
}
159159

160+
function isPlainImportEquals(node) {
161+
return node.type === 'TSImportEqualsDeclaration' && node.moduleReference.expression
162+
}
163+
160164
function canCrossNodeWhileReorder(node) {
161-
return isPlainRequireModule(node) || isPlainImportModule(node)
165+
return isPlainRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node)
162166
}
163167

164168
function canReorderItems(firstNode, secondNode) {
@@ -243,28 +247,22 @@ function makeOutOfOrderReport(context, imported) {
243247
reportOutOfOrder(context, imported, outOfOrder, 'before')
244248
}
245249

246-
function importsSorterAsc(importA, importB) {
247-
if (importA < importB) {
248-
return -1
249-
}
250-
251-
if (importA > importB) {
252-
return 1
253-
}
250+
function getSorter(ascending) {
251+
let multiplier = (ascending ? 1 : -1)
254252

255-
return 0
256-
}
253+
return function importsSorter(importA, importB) {
254+
let result
257255

258-
function importsSorterDesc(importA, importB) {
259-
if (importA < importB) {
260-
return 1
261-
}
256+
if ((importA < importB) || importB === null) {
257+
result = -1
258+
} else if ((importA > importB) || importA === null) {
259+
result = 1
260+
} else {
261+
result = 0
262+
}
262263

263-
if (importA > importB) {
264-
return -1
264+
return result * multiplier
265265
}
266-
267-
return 0
268266
}
269267

270268
function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
@@ -278,7 +276,7 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
278276

279277
const groupRanks = Object.keys(groupedByRanks)
280278

281-
const sorterFn = alphabetizeOptions.order === 'asc' ? importsSorterAsc : importsSorterDesc
279+
const sorterFn = getSorter(alphabetizeOptions.order === 'asc')
282280
const comparator = alphabetizeOptions.caseInsensitive ? (a, b) => sorterFn(String(a).toLowerCase(), String(b).toLowerCase()) : (a, b) => sorterFn(a, b)
283281
// sort imports locally within their group
284282
groupRanks.forEach(function(groupRank) {
@@ -609,6 +607,23 @@ module.exports = {
609607
)
610608
}
611609
},
610+
TSImportEqualsDeclaration: function handleImports(node) {
611+
let name
612+
if (node.moduleReference.type === 'TSExternalModuleReference') {
613+
name = node.moduleReference.expression.value
614+
} else {
615+
name = null
616+
}
617+
registerNode(
618+
context,
619+
node,
620+
name,
621+
'import',
622+
ranks,
623+
imported,
624+
pathGroupsExcludedImportTypes
625+
)
626+
},
612627
CallExpression: function handleRequires(node) {
613628
if (level !== 0 || !isStaticRequire(node) || !isInVariableDeclarator(node.parent)) {
614629
return

tests/src/rules/order.js

+58
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,22 @@ ruleTester.run('order', rule, {
167167
var index = require('./');
168168
`,
169169
}),
170+
// Export equals expressions should be on top alongside with ordinary import-statements.
171+
...getTSParsers().map(parser => (
172+
test({
173+
code: `
174+
import async, {foo1} from 'async';
175+
import relParent2, {foo2} from '../foo/bar';
176+
import sibling, {foo3} from './foo';
177+
var fs = require('fs');
178+
var util = require("util");
179+
var relParent1 = require('../foo');
180+
var relParent3 = require('../');
181+
var index = require('./');
182+
`,
183+
parser,
184+
})
185+
)),
170186
// Adding unknown import types (e.g. using a resolver alias via babel) to the groups.
171187
test({
172188
code: `
@@ -1142,6 +1158,24 @@ ruleTester.run('order', rule, {
11421158
message: '`fs` import should occur after import of `../foo/bar`',
11431159
}],
11441160
}),
1161+
...getTSParsers().map(parser => (
1162+
test({
1163+
code: `
1164+
var fs = require('fs');
1165+
import async, {foo1} from 'async';
1166+
import bar = require("../foo/bar");
1167+
`,
1168+
output: `
1169+
import async, {foo1} from 'async';
1170+
import bar = require("../foo/bar");
1171+
var fs = require('fs');
1172+
`,
1173+
parser,
1174+
errors: [{
1175+
message: '`fs` import should occur after import of `../foo/bar`',
1176+
}],
1177+
})
1178+
)),
11451179
// Default order using import with custom import alias
11461180
test({
11471181
code: `
@@ -1913,6 +1947,30 @@ ruleTester.run('order', rule, {
19131947
message: '`Bar` import should occur before import of `bar`',
19141948
}],
19151949
}),
1950+
...getTSParsers().map(parser => (
1951+
test({
1952+
code: `
1953+
import sync = require('sync');
1954+
import async, {foo1} from 'async';
1955+
1956+
import index from './';
1957+
`,
1958+
output: `
1959+
import async, {foo1} from 'async';
1960+
import sync = require('sync');
1961+
1962+
import index from './';
1963+
`,
1964+
options: [{
1965+
groups: ['external', 'index'],
1966+
alphabetize: {order: 'asc'},
1967+
}],
1968+
parser,
1969+
errors: [{
1970+
message: '`async` import should occur before import of `sync`',
1971+
}],
1972+
})
1973+
)),
19161974
// Option alphabetize: {order: 'desc'}
19171975
test({
19181976
code: `

0 commit comments

Comments
 (0)