@@ -15,16 +15,15 @@ namespace ts.OrganizeImports {
1515 preferences : UserPreferences ,
1616 skipDestructiveCodeActions ?: boolean
1717 ) {
18-
1918 const changeTracker = textChanges . ChangeTracker . fromContext ( { host, formatContext, preferences } ) ;
2019
2120 const coalesceAndOrganizeImports = ( importGroup : readonly ImportDeclaration [ ] ) => stableSort (
2221 coalesceImports ( removeUnusedImports ( importGroup , sourceFile , program , skipDestructiveCodeActions ) ) ,
2322 ( s1 , s2 ) => compareImportsOrRequireStatements ( s1 , s2 ) ) ;
2423
2524 // All of the old ImportDeclarations in the file, in syntactic order.
26- const topLevelImportDecls = sourceFile . statements . filter ( isImportDeclaration ) ;
27- organizeImportsWorker ( topLevelImportDecls , coalesceAndOrganizeImports ) ;
25+ const topLevelImportGroupDecls = groupImportsByNewlineContiguous ( sourceFile . statements . filter ( isImportDeclaration ) , host , formatContext ) ;
26+ topLevelImportGroupDecls . forEach ( topLevelImportGroupDecl => organizeImportsWorker ( topLevelImportGroupDecl , coalesceAndOrganizeImports ) ) ;
2827
2928 // All of the old ExportDeclarations in the file, in syntactic order.
3029 const topLevelExportDecls = sourceFile . statements . filter ( isExportDeclaration ) ;
@@ -33,8 +32,8 @@ namespace ts.OrganizeImports {
3332 for ( const ambientModule of sourceFile . statements . filter ( isAmbientModule ) ) {
3433 if ( ! ambientModule . body ) continue ;
3534
36- const ambientModuleImportDecls = ambientModule . body . statements . filter ( isImportDeclaration ) ;
37- organizeImportsWorker ( ambientModuleImportDecls , coalesceAndOrganizeImports ) ;
35+ const ambientModuleImportGroupDecls = groupImportsByNewlineContiguous ( ambientModule . body . statements . filter ( isImportDeclaration ) , host , formatContext ) ;
36+ ambientModuleImportGroupDecls . forEach ( ambientModuleImportGroupDecl => organizeImportsWorker ( ambientModuleImportGroupDecl , coalesceAndOrganizeImports ) ) ;
3837
3938 const ambientModuleExportDecls = ambientModule . body . statements . filter ( isExportDeclaration ) ;
4039 organizeImportsWorker ( ambientModuleExportDecls , coalesceExports ) ;
@@ -88,6 +87,31 @@ namespace ts.OrganizeImports {
8887 }
8988 }
9089
90+ function groupImportsByNewlineContiguous ( importDecls : ImportDeclaration [ ] , host : LanguageServiceHost , formatContext : formatting . FormatContext ) : ImportDeclaration [ ] [ ] {
91+ const groupImports : ImportDeclaration [ ] [ ] = [ ] ;
92+ const newLine = getNewLineOrDefaultFromHost ( host , formatContext . options ) ;
93+ const prefixCond = `${ newLine } ${ newLine } ` ;
94+
95+ for ( let importIndex = 0 , groupIndex = 0 , length = importDecls . length ; importIndex < length ; ++ importIndex ) {
96+ const topLevelImportDecl = importDecls [ importIndex ] ;
97+ const leadingText = topLevelImportDecl . getFullText ( ) . substring (
98+ 0 ,
99+ topLevelImportDecl . getStart ( ) - topLevelImportDecl . getFullStart ( ) ) ;
100+
101+ if ( startsWith ( leadingText , prefixCond ) ) {
102+ groupIndex ++ ;
103+ }
104+
105+ if ( ! groupImports [ groupIndex ] ) {
106+ groupImports [ groupIndex ] = [ ] ;
107+ }
108+
109+ groupImports [ groupIndex ] . push ( topLevelImportDecl ) ;
110+ }
111+
112+ return groupImports ;
113+ }
114+
91115 function removeUnusedImports ( oldImports : readonly ImportDeclaration [ ] , sourceFile : SourceFile , program : Program , skipDestructiveCodeActions : boolean | undefined ) {
92116 // As a precaution, consider unused import detection to be destructive (GH #43051)
93117 if ( skipDestructiveCodeActions ) {
0 commit comments