@@ -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 topLevelGroupImportDecls = groupImportsByNewlines ( sourceFile . statements . filter ( isImportDeclaration ) , host , formatContext ) ;
26+ topLevelGroupImportDecls . forEach ( topLevelGroupImportDecl => organizeImportsWorker ( topLevelGroupImportDecl , 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 ambientModuleGroupImportDecls = groupImportsByNewlines ( ambientModule . body . statements . filter ( isImportDeclaration ) , host , formatContext ) ;
36+ ambientModuleGroupImportDecls . forEach ( ambientModuleGroupImportDecl => organizeImportsWorker ( ambientModuleGroupImportDecl , coalesceAndOrganizeImports ) ) ;
3837
3938 const ambientModuleExportDecls = ambientModule . body . statements . filter ( isExportDeclaration ) ;
4039 organizeImportsWorker ( ambientModuleExportDecls , coalesceExports ) ;
@@ -88,6 +87,24 @@ namespace ts.OrganizeImports {
8887 }
8988 }
9089
90+ function groupImportsByNewlines ( 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+ for ( let index = 0 , groupIndex = 0 , length = importDecls . length ; index < length ; ++ index ) {
95+ const topLevelImportDecl = importDecls [ index ] ;
96+ const leadingText = topLevelImportDecl . getFullText ( ) . substring ( 0 , topLevelImportDecl . getStart ( ) - topLevelImportDecl . getFullStart ( ) ) ;
97+ if ( startsWith ( leadingText , prefixCond ) ) {
98+ groupIndex ++ ;
99+ }
100+ if ( ! groupImports [ groupIndex ] ) {
101+ groupImports [ groupIndex ] = [ ] ;
102+ }
103+ groupImports [ groupIndex ] . push ( topLevelImportDecl ) ;
104+ }
105+ return groupImports ;
106+ }
107+
91108 function removeUnusedImports ( oldImports : readonly ImportDeclaration [ ] , sourceFile : SourceFile , program : Program , skipDestructiveCodeActions : boolean | undefined ) {
92109 // As a precaution, consider unused import detection to be destructive (GH #43051)
93110 if ( skipDestructiveCodeActions ) {
0 commit comments