@@ -13,46 +13,55 @@ namespace ts.OrganizeImports {
13
13
host : LanguageServiceHost ,
14
14
program : Program ) {
15
15
16
- // TODO (https://github.com/Microsoft/TypeScript/issues/10020): sort *within* ambient modules (find using isAmbientModule)
16
+ const changeTracker = textChanges . ChangeTracker . fromContext ( { host , formatContext } ) ;
17
17
18
18
// All of the old ImportDeclarations in the file, in syntactic order.
19
- const oldImportDecls = sourceFile . statements . filter ( isImportDeclaration ) ;
19
+ const topLevelImportDecls = sourceFile . statements . filter ( isImportDeclaration ) ;
20
+ organizeImportsWorker ( topLevelImportDecls ) ;
20
21
21
- if ( oldImportDecls . length === 0 ) {
22
- return [ ] ;
22
+ for ( const ambientModule of sourceFile . statements . filter ( isAmbientModule ) ) {
23
+ const ambientModuleBody = getModuleBlock ( ambientModule as ModuleDeclaration ) ;
24
+ const ambientModuleImportDecls = ambientModuleBody . statements . filter ( isImportDeclaration ) ;
25
+ organizeImportsWorker ( ambientModuleImportDecls ) ;
23
26
}
24
27
25
- const oldImportGroups = group ( oldImportDecls , importDecl => getExternalModuleName ( importDecl . moduleSpecifier ) ) ;
28
+ return changeTracker . getChanges ( ) ;
26
29
27
- const sortedImportGroups = stableSort ( oldImportGroups , ( group1 , group2 ) =>
28
- compareModuleSpecifiers ( group1 [ 0 ] . moduleSpecifier , group2 [ 0 ] . moduleSpecifier ) ) ;
30
+ function organizeImportsWorker ( oldImportDecls : ReadonlyArray < ImportDeclaration > ) {
31
+ if ( length ( oldImportDecls ) === 0 ) {
32
+ return ;
33
+ }
29
34
30
- const newImportDecls = flatMap ( sortedImportGroups , importGroup =>
31
- getExternalModuleName ( importGroup [ 0 ] . moduleSpecifier )
32
- ? coalesceImports ( removeUnusedImports ( importGroup , sourceFile , program ) )
33
- : importGroup ) ;
35
+ const oldImportGroups = group ( oldImportDecls , importDecl => getExternalModuleName ( importDecl . moduleSpecifier ) ) ;
36
+ const sortedImportGroups = stableSort ( oldImportGroups , ( group1 , group2 ) => compareModuleSpecifiers ( group1 [ 0 ] . moduleSpecifier , group2 [ 0 ] . moduleSpecifier ) ) ;
37
+ const newImportDecls = flatMap ( sortedImportGroups , importGroup =>
38
+ getExternalModuleName ( importGroup [ 0 ] . moduleSpecifier )
39
+ ? coalesceImports ( removeUnusedImports ( importGroup , sourceFile , program ) )
40
+ : importGroup ) ;
34
41
35
- const changeTracker = textChanges . ChangeTracker . fromContext ( { host, formatContext } ) ;
36
-
37
- // Delete or replace the first import.
38
- if ( newImportDecls . length === 0 ) {
39
- changeTracker . deleteNode ( sourceFile , oldImportDecls [ 0 ] ) ;
40
- }
41
- else {
42
- // Note: Delete the surrounding trivia because it will have been retained in newImportDecls.
43
- changeTracker . replaceNodeWithNodes ( sourceFile , oldImportDecls [ 0 ] , newImportDecls , {
44
- useNonAdjustedStartPosition : false ,
45
- useNonAdjustedEndPosition : false ,
46
- suffix : getNewLineOrDefaultFromHost ( host , formatContext . options ) ,
47
- } ) ;
48
- }
42
+ // Delete or replace the first import.
43
+ if ( newImportDecls . length === 0 ) {
44
+ changeTracker . deleteNode ( sourceFile , oldImportDecls [ 0 ] ) ;
45
+ }
46
+ else {
47
+ // Note: Delete the surrounding trivia because it will have been retained in newImportDecls.
48
+ changeTracker . replaceNodeWithNodes ( sourceFile , oldImportDecls [ 0 ] , newImportDecls , {
49
+ useNonAdjustedStartPosition : false ,
50
+ useNonAdjustedEndPosition : false ,
51
+ suffix : getNewLineOrDefaultFromHost ( host , formatContext . options ) ,
52
+ } ) ;
53
+ }
49
54
50
- // Delete any subsequent imports.
51
- for ( let i = 1 ; i < oldImportDecls . length ; i ++ ) {
52
- changeTracker . deleteNode ( sourceFile , oldImportDecls [ i ] ) ;
55
+ // Delete any subsequent imports.
56
+ for ( let i = 1 ; i < oldImportDecls . length ; i ++ ) {
57
+ changeTracker . deleteNode ( sourceFile , oldImportDecls [ i ] ) ;
58
+ }
53
59
}
60
+ }
54
61
55
- return changeTracker . getChanges ( ) ;
62
+ function getModuleBlock ( moduleDecl : ModuleDeclaration ) : ModuleBlock | undefined {
63
+ const body = moduleDecl . body ;
64
+ return body && ! isIdentifier ( body ) && ( isModuleBlock ( body ) ? body : getModuleBlock ( body ) ) ;
56
65
}
57
66
58
67
function removeUnusedImports ( oldImports : ReadonlyArray < ImportDeclaration > , sourceFile : SourceFile , program : Program ) {
0 commit comments