Skip to content

Commit b835ea6

Browse files
committed
feat(imports): Don't attempt to sort when there is code between imports
Fixes #53
1 parent 9b2b552 commit b835ea6

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

src/__tests__/imports.spec.ts

+16
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,22 @@ createRuleTester().run("sort/imports", rule, {
804804
},
805805
],
806806
},
807+
808+
{
809+
name: "Does not sort when there is code between imports",
810+
errors: [{ messageId: "codeBetweenImports" }],
811+
code: dedent`
812+
import b from 'b'
813+
const foo = 'foo'
814+
const bar = 'bar'
815+
import a from 'a'
816+
817+
import e from 'e'
818+
const baz = 'baz'
819+
import d from 'd'
820+
import c from 'c'
821+
`,
822+
},
807823
],
808824
})
809825

src/rules/imports.ts

+23-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Rule, AST } from "eslint"
2-
import { ImportDeclaration } from "estree"
2+
import * as ESTree from "estree"
33
import { isResolved } from "../resolver.js"
44
import {
55
docsURL,
@@ -32,7 +32,7 @@ interface Options extends SorterOptions {
3232
typeOrder?: TypeOrder
3333
}
3434

35-
const getSortValue = (node: ImportDeclaration) =>
35+
const getSortValue = (node: ESTree.ImportDeclaration) =>
3636
node.type === "ImportDeclaration"
3737
? getName(node.source)
3838
: getName((node as any).moduleReference.expression)
@@ -42,7 +42,7 @@ const getSortValue = (node: ImportDeclaration) =>
4242
* rule options. If no sort groups are configured (default), the order returned
4343
* is always 0.
4444
*/
45-
function getSortGroup(sortGroups: SortGroup[], node: ImportDeclaration) {
45+
function getSortGroup(sortGroups: SortGroup[], node: ESTree.ImportDeclaration) {
4646
const source = getSortValue(node)
4747

4848
for (const { regex, type, order } of sortGroups) {
@@ -75,7 +75,7 @@ function getSortGroup(sortGroups: SortGroup[], node: ImportDeclaration) {
7575

7676
function getImportKindWeight(
7777
options: Options | undefined,
78-
node: ImportDeclaration
78+
node: ESTree.ImportDeclaration
7979
) {
8080
const typeOrder = options?.typeOrder ?? "preserve"
8181
const kind = (node as { importKind?: ImportOrExportKind }).importKind
@@ -106,6 +106,22 @@ export default {
106106
return
107107
}
108108

109+
// Ensure there is no code between imports. If there is, we'll bail
110+
// out and not try to sort. Ideally we would move the code after the
111+
// imports but it's not worth the complexity for such a niche case.
112+
//
113+
// Checking for this case is pretty simple, we just check if the
114+
// distance between the first and last import is the same as the
115+
// total number of import nodes.
116+
const startNodeIndex = program.body.indexOf(nodes[0])
117+
const endNodeIndex = program.body.indexOf(nodes.at(-1)!)
118+
if (endNodeIndex - startNodeIndex !== nodes.length - 1) {
119+
return context.report({
120+
node: program,
121+
messageId: "codeBetweenImports",
122+
})
123+
}
124+
109125
const sorted = nodes.slice().sort(
110126
(a, b) =>
111127
// First sort by sort group
@@ -121,7 +137,7 @@ export default {
121137
// When sorting, the comments for the first node are not copied as
122138
// we cannot determine if they are comments for the entire file or
123139
// just the first import.
124-
const isFirst = (node: ImportDeclaration) => node === nodes[0]
140+
const isFirst = (node: ESTree.ImportDeclaration) => node === nodes[0]
125141

126142
context.report({
127143
node: firstUnsortedNode,
@@ -224,6 +240,8 @@ export default {
224240
url: docsURL("imports"),
225241
},
226242
messages: {
243+
codeBetweenImports:
244+
"Unexpected code between imports. Sorting will be skipped.",
227245
incorrectSeparator:
228246
"Expected `{{expected}}` to separate import groups but found `{{actual}}`.",
229247
extraNewlines: "Unexpected {{newlines}} between imports.",

0 commit comments

Comments
 (0)