1
1
import { Rule , AST } from "eslint"
2
- import { ImportDeclaration } from "estree"
2
+ import * as ESTree from "estree"
3
3
import { isResolved } from "../resolver.js"
4
4
import {
5
5
docsURL ,
@@ -32,7 +32,7 @@ interface Options extends SorterOptions {
32
32
typeOrder ?: TypeOrder
33
33
}
34
34
35
- const getSortValue = ( node : ImportDeclaration ) =>
35
+ const getSortValue = ( node : ESTree . ImportDeclaration ) =>
36
36
node . type === "ImportDeclaration"
37
37
? getName ( node . source )
38
38
: getName ( ( node as any ) . moduleReference . expression )
@@ -42,7 +42,7 @@ const getSortValue = (node: ImportDeclaration) =>
42
42
* rule options. If no sort groups are configured (default), the order returned
43
43
* is always 0.
44
44
*/
45
- function getSortGroup ( sortGroups : SortGroup [ ] , node : ImportDeclaration ) {
45
+ function getSortGroup ( sortGroups : SortGroup [ ] , node : ESTree . ImportDeclaration ) {
46
46
const source = getSortValue ( node )
47
47
48
48
for ( const { regex, type, order } of sortGroups ) {
@@ -75,7 +75,7 @@ function getSortGroup(sortGroups: SortGroup[], node: ImportDeclaration) {
75
75
76
76
function getImportKindWeight (
77
77
options : Options | undefined ,
78
- node : ImportDeclaration
78
+ node : ESTree . ImportDeclaration
79
79
) {
80
80
const typeOrder = options ?. typeOrder ?? "preserve"
81
81
const kind = ( node as { importKind ?: ImportOrExportKind } ) . importKind
@@ -106,6 +106,22 @@ export default {
106
106
return
107
107
}
108
108
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
+
109
125
const sorted = nodes . slice ( ) . sort (
110
126
( a , b ) =>
111
127
// First sort by sort group
@@ -121,7 +137,7 @@ export default {
121
137
// When sorting, the comments for the first node are not copied as
122
138
// we cannot determine if they are comments for the entire file or
123
139
// just the first import.
124
- const isFirst = ( node : ImportDeclaration ) => node === nodes [ 0 ]
140
+ const isFirst = ( node : ESTree . ImportDeclaration ) => node === nodes [ 0 ]
125
141
126
142
context . report ( {
127
143
node : firstUnsortedNode ,
@@ -224,6 +240,8 @@ export default {
224
240
url : docsURL ( "imports" ) ,
225
241
} ,
226
242
messages : {
243
+ codeBetweenImports :
244
+ "Unexpected code between imports. Sorting will be skipped." ,
227
245
incorrectSeparator :
228
246
"Expected `{{expected}}` to separate import groups but found `{{actual}}`." ,
229
247
extraNewlines : "Unexpected {{newlines}} between imports." ,
0 commit comments