11import { Rule , AST } from "eslint"
2- import { ImportDeclaration } from "estree"
2+ import * as ESTree from "estree"
33import { isResolved } from "../resolver.js"
44import {
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
7676function 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