@@ -96,18 +96,29 @@ export function organizeImports(
9696 // All of the old ImportDeclarations in the file, in syntactic order.
9797 const topLevelImportGroupDecls = groupByNewlineContiguous ( sourceFile , sourceFile . statements . filter ( isImportDeclaration ) ) ;
9898
99- const DefaultComparer = getOrganizeImportsComparer ( preferences , /*ignoreCase*/ true ) ;
99+ const DefaultComparer = getOrganizeImportsComparer ( preferences , /*ignoreCase*/ typeof preferences . organizeImportsIgnoreCase === "boolean" ? preferences . organizeImportsIgnoreCase : true ) ;
100100
101- let detectedModuleCaseComparer = DefaultComparer ;
102- let detectedNamedImportCaseComparer = ( s1 , s2 ) => compareImportOrExportSpecifiers ( s1 , s2 , DefaultComparer , { organizeImportsTypeOrder : "last" } ) ;
103- let detectedTypeOrder : typeof preferences . organizeImportsTypeOrder = "last" ;
101+ // if case sensitivity is specified (true/false), then use the same setting for both.
102+ let detectedModuleCaseComparer : Comparer < string > | undefined = typeof preferences . organizeImportsIgnoreCase === "boolean" ? DefaultComparer : undefined ;
103+ let detectedNamedImportCaseComparer : Comparer < string > | undefined = detectedModuleCaseComparer ;
104+
105+ let detectedTypeOrder : typeof preferences . organizeImportsTypeOrder = preferences . organizeImportsTypeOrder ;
106+
107+ if ( ! detectedModuleCaseComparer || ! detectedNamedImportCaseComparer || ! detectedTypeOrder ) {
108+ const { moduleSpecifierComparer, namedImportComparer, typeOrder } = getDetectionByDiff ( topLevelImportGroupDecls , preferences )
109+
110+ detectedModuleCaseComparer = detectedModuleCaseComparer ?? moduleSpecifierComparer ?? DefaultComparer ;
111+ detectedNamedImportCaseComparer = detectedNamedImportCaseComparer ?? namedImportComparer ?? DefaultComparer ;
112+ detectedTypeOrder = detectedTypeOrder ?? typeOrder ;
113+ // TODO return unset comparer
114+ }
104115
105116 topLevelImportGroupDecls . forEach ( importGroupDecl => organizeImportsWorker ( importGroupDecl ) ) ;
106117
107118 // Exports are always used
108119 if ( mode !== OrganizeImportsMode . RemoveUnused ) {
109120 // All of the old ExportDeclarations in the file, in syntactic order.
110- getTopLevelExportGroups ( sourceFile ) . forEach ( exportGroupDecl => organizeExportsWorker ( exportGroupDecl ) ) ;
121+ getTopLevelExportGroups ( sourceFile ) . forEach ( exportGroupDecl => organizeExportsWorker ( exportGroupDecl , detectedNamedImportCaseComparer ) ) ;
111122 }
112123
113124 for ( const ambientModule of sourceFile . statements . filter ( isAmbientModule ) ) {
@@ -119,7 +130,7 @@ export function organizeImports(
119130 // Exports are always used
120131 if ( mode !== OrganizeImportsMode . RemoveUnused ) {
121132 const ambientModuleExportDecls = ambientModule . body . statements . filter ( isExportDeclaration ) ;
122- organizeExportsWorker ( ambientModuleExportDecls ) ;
133+ organizeExportsWorker ( ambientModuleExportDecls , detectedNamedImportCaseComparer ) ;
123134 }
124135 }
125136
@@ -144,7 +155,7 @@ export function organizeImports(
144155 ? group ( oldImportDecls , importDecl => getExternalModuleName ( importDecl . moduleSpecifier ) ! )
145156 : [ oldImportDecls ] ;
146157 const sortedImportGroups = shouldSort
147- ? stableSort ( oldImportGroups , ( group1 , group2 ) => compareModuleSpecifiersWorker ( group1 [ 0 ] . moduleSpecifier , group2 [ 0 ] . moduleSpecifier , detectedModuleCaseComparer ) )
158+ ? stableSort ( oldImportGroups , ( group1 , group2 ) => compareModuleSpecifiersWorker ( group1 [ 0 ] . moduleSpecifier , group2 [ 0 ] . moduleSpecifier , detectedModuleCaseComparer ?? DefaultComparer ) )
148159 : oldImportGroups ;
149160 const newImportDecls = flatMap ( sortedImportGroups , importGroup =>
150161 getExternalModuleName ( importGroup [ 0 ] . moduleSpecifier ) || importGroup [ 0 ] . moduleSpecifier === undefined
@@ -175,30 +186,22 @@ export function organizeImports(
175186 }
176187 }
177188
178- function organizeImportsWorker ( oldImportDecls : readonly ImportDeclaration [ ] , comparer ?: Comparer < string > ) {
179- if ( ! comparer ) {
180- const { moduleSpecifierComparer, namedImportComparer, typeOrder } = getDetectionByDiff ( topLevelImportGroupDecls , preferences )
181-
182- detectedModuleCaseComparer = moduleSpecifierComparer ?? detectedModuleCaseComparer ;
183- detectedNamedImportCaseComparer = namedImportComparer ?? detectedNamedImportCaseComparer ;
184- detectedTypeOrder = typeOrder ?? detectedTypeOrder ;
185- // TODO return unset comparer
186- }
187-
189+ function organizeImportsWorker ( oldImportDecls : readonly ImportDeclaration [ ] ) {
190+ const specifierComparer = getOrganizeImportsSpecifierComparer ( { organizeImportsTypeOrder : detectedTypeOrder ?? preferences . organizeImportsTypeOrder } , detectedNamedImportCaseComparer ) ;
188191 const processImportsOfSameModuleSpecifier = ( importGroup : readonly ImportDeclaration [ ] ) => {
189192 if ( shouldRemove ) importGroup = removeUnusedImports ( importGroup , sourceFile , program ) ;
190- if ( shouldCombine ) importGroup = coalesceImportsWorker ( importGroup , detectedNamedImportCaseComparer , sourceFile , { organizeImportsTypeOrder : detectedTypeOrder } ) ;
191- if ( shouldSort ) importGroup = stableSort ( importGroup , ( s1 , s2 ) => compareImportsOrRequireStatements ( s1 , s2 , detectedModuleCaseComparer ) ) ;
193+ if ( shouldCombine ) importGroup = coalesceImportsWorker ( importGroup , detectedModuleCaseComparer ?? DefaultComparer , specifierComparer , sourceFile ) ;
194+ if ( shouldSort ) importGroup = stableSort ( importGroup , ( s1 , s2 ) => compareImportsOrRequireStatements ( s1 , s2 , detectedModuleCaseComparer ?? DefaultComparer ) ) ;
192195 return importGroup ;
193196 } ;
194197
195198 organizeDeclsWorker ( oldImportDecls , processImportsOfSameModuleSpecifier ) ;
196199 // return { moduleSpecifierComparer, namedImportComparer, typeOrder };
197200 }
198201
199- function organizeExportsWorker ( oldExportDecls : readonly ExportDeclaration [ ] , comparer ?: Comparer < string > ) {
200- const useComparer = comparer ?? DefaultComparer ;
201- organizeDeclsWorker ( oldExportDecls , group => coalesceExportsWorker ( group , useComparer , { organizeImportsTypeOrder : detectedTypeOrder ?? preferences . organizeImportsTypeOrder } ) )
202+ function organizeExportsWorker ( oldExportDecls : readonly ExportDeclaration [ ] , specifierCaseComparer ?: Comparer < string > ) {
203+ const useComparer = getOrganizeImportsSpecifierComparer ( preferences , specifierCaseComparer ) ;
204+ organizeDeclsWorker ( oldExportDecls , group => coalesceExportsWorker ( group , useComparer ) )
202205 }
203206}
204207
@@ -341,10 +344,11 @@ function getExternalModuleName(specifier: Expression | undefined) {
341344 */
342345export function coalesceImports ( importGroup : readonly ImportDeclaration [ ] , ignoreCase : boolean , sourceFile ?: SourceFile , preferences ?: UserPreferences ) : readonly ImportDeclaration [ ] {
343346 const comparer = getOrganizeImportsOrdinalStringComparer ( ignoreCase ) ;
344- return coalesceImportsWorker ( importGroup , comparer , sourceFile , preferences ) ;
347+ const specifierComparer = getOrganizeImportsSpecifierComparer ( { organizeImportsTypeOrder : preferences ?. organizeImportsTypeOrder } , comparer ) ;
348+ return coalesceImportsWorker ( importGroup , comparer , specifierComparer , sourceFile ) ;
345349}
346350
347- function coalesceImportsWorker ( importGroup : readonly ImportDeclaration [ ] , comparer : Comparer < string > , sourceFile ?: SourceFile , preferences ?: UserPreferences ) : readonly ImportDeclaration [ ] {
351+ function coalesceImportsWorker ( importGroup : readonly ImportDeclaration [ ] , comparer : Comparer < string > , specifierComparer : Comparer < ImportSpecifier > , sourceFile ?: SourceFile ) : readonly ImportDeclaration [ ] {
348352 if ( importGroup . length === 0 ) {
349353 return importGroup ;
350354 }
@@ -417,7 +421,7 @@ function coalesceImportsWorker(importGroup: readonly ImportDeclaration[], compar
417421 newImportSpecifiers . push ( ...getNewImportSpecifiers ( namedImports ) ) ;
418422
419423 const sortedImportSpecifiers = factory . createNodeArray (
420- sortSpecifiers ( newImportSpecifiers , comparer , preferences ) ,
424+ sortSpecifiers ( newImportSpecifiers , specifierComparer ) ,
421425 firstNamedImport ?. importClause . namedBindings . elements . hasTrailingComma ,
422426 ) ;
423427
@@ -536,11 +540,12 @@ function getCategorizedImports(importGroup: readonly ImportDeclaration[]) {
536540 * @internal
537541 */
538542export function coalesceExports ( exportGroup : readonly ExportDeclaration [ ] , ignoreCase : boolean , preferences ?: UserPreferences ) {
539- const comparer = getOrganizeImportsOrdinalStringComparer ( ignoreCase ) ;
540- return coalesceExportsWorker ( exportGroup , comparer , preferences ) ;
543+ const comparer = ( s1 : ExportSpecifier , s2 : ExportSpecifier ) =>
544+ compareImportOrExportSpecifiers ( s1 , s2 , getOrganizeImportsOrdinalStringComparer ( ignoreCase ) , { organizeImportsTypeOrder : preferences ?. organizeImportsTypeOrder ?? "last" } ) ;
545+ return coalesceExportsWorker ( exportGroup , comparer ) ;
541546}
542547
543- function coalesceExportsWorker ( exportGroup : readonly ExportDeclaration [ ] , comparer : Comparer < string > , preferences ?: UserPreferences ) {
548+ function coalesceExportsWorker ( exportGroup : readonly ExportDeclaration [ ] , specifierComparer : Comparer < ExportSpecifier > ) {
544549 if ( exportGroup . length === 0 ) {
545550 return exportGroup ;
546551 }
@@ -559,7 +564,7 @@ function coalesceExportsWorker(exportGroup: readonly ExportDeclaration[], compar
559564 const newExportSpecifiers : ExportSpecifier [ ] = [ ] ;
560565 newExportSpecifiers . push ( ...flatMap ( exportGroup , i => i . exportClause && isNamedExports ( i . exportClause ) ? i . exportClause . elements : emptyArray ) ) ;
561566
562- const sortedExportSpecifiers = sortSpecifiers ( newExportSpecifiers , comparer , preferences ) ;
567+ const sortedExportSpecifiers = sortSpecifiers ( newExportSpecifiers , specifierComparer ) ;
563568
564569 const exportDecl = exportGroup [ 0 ] ;
565570 coalescedExports . push (
@@ -626,8 +631,8 @@ function updateImportDeclarationAndClause(
626631 ) ;
627632}
628633
629- function sortSpecifiers < T extends ImportOrExportSpecifier > ( specifiers : readonly T [ ] , comparer : Comparer < string > , preferences ?: UserPreferences ) : readonly T [ ] {
630- return stableSort ( specifiers , ( s1 , s2 ) => compareImportOrExportSpecifiers ( s1 , s2 , comparer , preferences ) ) ;
634+ function sortSpecifiers < T extends ImportOrExportSpecifier > ( specifiers : readonly T [ ] , specifierComparer : Comparer < T > ) : readonly T [ ] {
635+ return stableSort ( specifiers , specifierComparer ) ;
631636}
632637
633638/** @internal */
@@ -642,6 +647,11 @@ export function compareImportOrExportSpecifiers<T extends ImportOrExportSpecifie
642647 }
643648}
644649
650+ function getOrganizeImportsSpecifierComparer < T extends ImportOrExportSpecifier > ( preferences : UserPreferences , comparer ?: Comparer < string > ) : Comparer < T > {
651+ const stringComparer = comparer ?? getOrganizeImportsOrdinalStringComparer ( ! ! preferences . organizeImportsIgnoreCase ) ;
652+ return ( s1 , s2 ) => compareImportOrExportSpecifiers ( s1 , s2 , stringComparer , preferences ) ;
653+ }
654+
645655/**
646656 * Exported for testing
647657 *
@@ -963,21 +973,24 @@ export function getDetectionByDiff(importDeclsByGroup: ImportDeclaration[][], pr
963973 moduleSpecifierComparer : Comparer < string > ;
964974 namedImportComparer ?: Comparer < string > ;
965975 typeOrder ?: "first" | "last" | "inline" ;
966- } = { moduleSpecifierComparer : getOrganizeImportsComparer ( preferences , typeof preferences . organizeImportsIgnoreCase === "boolean" ? preferences . organizeImportsIgnoreCase : true ) } ;
976+ } = {
977+ moduleSpecifierComparer : getOrganizeImportsComparer ( preferences , typeof preferences . organizeImportsIgnoreCase === "boolean" ? preferences . organizeImportsIgnoreCase : true ) ,
978+ typeOrder : preferences . organizeImportsTypeOrder ,
979+ } ;
967980
968- let comparers : Comparer < string > [ ] ;
981+ let comparersToTest : Comparer < string > [ ] ;
969982 if ( typeof preferences . organizeImportsIgnoreCase === "boolean" ) {
970983 // both moduleSpecifier and namedImport comparer to the correct case-sensitivity.
971984 // does not yet exit because we still need to detect for type order
972985 comparer . moduleSpecifierComparer = getOrganizeImportsComparer ( preferences , preferences . organizeImportsIgnoreCase ) ;
973986 comparer . namedImportComparer = comparer . moduleSpecifierComparer ;
974- comparers = [ comparer . moduleSpecifierComparer ] ;
987+ comparersToTest = [ comparer . moduleSpecifierComparer ] ;
975988 }
976989 else {
977990 // otherwise, we must test for both case-sensitivity and later, type order
978991 const CASE_INSENSITIVE_COMPARER = getOrganizeImportsComparer ( preferences , /*ignoreCase*/ true ) ;
979992 const CASE_SENSITIVE_COMPARER = getOrganizeImportsComparer ( preferences , /*ignoreCase*/ false ) ;
980- comparers = [ CASE_INSENSITIVE_COMPARER , CASE_SENSITIVE_COMPARER ] ;
993+ comparersToTest = [ CASE_INSENSITIVE_COMPARER , CASE_SENSITIVE_COMPARER ] ;
981994
982995 getModuleSpecifierNames ( importDeclsByGroup , comparer , detectCaseSensitivityBySort ) ;
983996 }
@@ -1018,7 +1031,7 @@ export function getDetectionByDiff(importDeclsByGroup: ImportDeclaration[][], pr
10181031
10191032 const { namedImportComparer, typeOrder } = detectNamedImportOrganizationBySort ( namedImportsByDecl ) ;
10201033 comparer . namedImportComparer = namedImportComparer ;
1021- comparer . typeOrder = typeOrder ;
1034+ comparer . typeOrder = comparer . typeOrder ?? typeOrder ;
10221035
10231036 return comparer ;
10241037
@@ -1037,7 +1050,7 @@ export function getDetectionByDiff(importDeclsByGroup: ImportDeclaration[][], pr
10371050 let bestComparer ;
10381051 let bestDiff = Infinity ;
10391052
1040- for ( const curComparer of comparers ) {
1053+ for ( const curComparer of comparersToTest ) {
10411054 let diffOfCurrentComparer = 0 ;
10421055
10431056 for ( const listToSort of originalGroups ) {
@@ -1053,7 +1066,7 @@ export function getDetectionByDiff(importDeclsByGroup: ImportDeclaration[][], pr
10531066 bestComparer = curComparer ;
10541067 }
10551068 }
1056- return bestComparer ?? comparers [ 0 ] ;
1069+ return bestComparer ?? comparersToTest [ 0 ] ;
10571070 }
10581071
10591072 // interface NamedImportByDecl {
@@ -1080,9 +1093,9 @@ export function getDetectionByDiff(importDeclsByGroup: ImportDeclaration[][], pr
10801093 type TypeOrder = "first" | "last" | "inline" ;
10811094
10821095 const bestDiff = { first : Infinity , last : Infinity , inline : Infinity } ;
1083- const bestComparer = { first : comparers [ 0 ] , last : comparers [ 0 ] , inline : comparers [ 0 ] } ;
1096+ const bestComparer = { first : comparersToTest [ 0 ] , last : comparersToTest [ 0 ] , inline : comparersToTest [ 0 ] } ;
10841097
1085- for ( const curComparer of comparers ) {
1098+ for ( const curComparer of comparersToTest ) {
10861099 const currDiff = { first : 0 , last : 0 , inline : 0 } ;
10871100
10881101 for ( const importDecl of originalGroups ) {
0 commit comments