@@ -13,7 +13,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
13
13
} ,
14
14
getEditsForAction ( context , actionName ) : RefactorEditInfo {
15
15
Debug . assert ( actionName === actionNameNamespaceToNamed || actionName === actionNameNamedToNamespace ) ;
16
- const edits = textChanges . ChangeTracker . with ( context , t => doChange ( context . file , context . program . getTypeChecker ( ) , t , Debug . assertDefined ( getImportToConvert ( context ) ) ) ) ;
16
+ const edits = textChanges . ChangeTracker . with ( context , t => doChange ( context . file , context . program , t , Debug . assertDefined ( getImportToConvert ( context ) ) ) ) ;
17
17
return { edits, renameFilename : undefined , renameLocation : undefined } ;
18
18
}
19
19
} ) ;
@@ -29,30 +29,27 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
29
29
return importClause && importClause . namedBindings ;
30
30
}
31
31
32
- function doChange ( sourceFile : SourceFile , checker : TypeChecker , changes : textChanges . ChangeTracker , toConvert : NamedImportBindings ) : void {
32
+ function doChange ( sourceFile : SourceFile , program : Program , changes : textChanges . ChangeTracker , toConvert : NamedImportBindings ) : void {
33
33
const usedIdentifiers = createMap < true > ( ) ;
34
34
forEachFreeIdentifier ( sourceFile , id => usedIdentifiers . set ( id . text , true ) ) ;
35
+ const checker = program . getTypeChecker ( ) ;
35
36
36
37
if ( toConvert . kind === SyntaxKind . NamespaceImport ) {
37
- doChangeNamespaceToNamed ( sourceFile , checker , changes , toConvert , usedIdentifiers ) ;
38
+ doChangeNamespaceToNamed ( sourceFile , checker , changes , toConvert , usedIdentifiers , getAllowSyntheticDefaultImports ( program . getCompilerOptions ( ) ) ) ;
38
39
}
39
40
else {
40
41
doChangeNamedToNamespace ( sourceFile , checker , changes , toConvert , usedIdentifiers ) ;
41
42
}
42
43
}
43
44
44
- function doChangeNamespaceToNamed ( sourceFile : SourceFile , checker : TypeChecker , changes : textChanges . ChangeTracker , toConvert : NamespaceImport , usedIdentifiers : ReadonlyMap < true > ) : void {
45
- const namespaceSymbol = checker . getSymbolAtLocation ( toConvert . name ) ! ;
46
-
45
+ function doChangeNamespaceToNamed ( sourceFile : SourceFile , checker : TypeChecker , changes : textChanges . ChangeTracker , toConvert : NamespaceImport , usedIdentifiers : ReadonlyMap < true > , allowSyntheticDefaultImports : boolean ) : void {
47
46
// We may need to change `mod.x` to `_x` to avoid a name conflict.
48
47
const exportNameToImportName = createMap < string > ( ) ;
49
- let usedAsNamespace = false ;
50
-
51
- forEachFreeIdentifier ( sourceFile , id => {
52
- if ( id === toConvert . name || checker . getSymbolAtLocation ( id ) !== namespaceSymbol ) return ;
48
+ let usedAsNamespaceOrDefault = false ;
53
49
50
+ FindAllReferences . Core . eachSymbolReferenceInFile ( toConvert . name , checker , sourceFile , id => {
54
51
if ( ! isPropertyAccessExpression ( id . parent ) ) {
55
- usedAsNamespace = true ;
52
+ usedAsNamespaceOrDefault = true ;
56
53
}
57
54
else {
58
55
const parent = cast ( id . parent , isPropertyAccessExpression ) ;
@@ -70,14 +67,16 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
70
67
exportNameToImportName . forEach ( ( name , propertyName ) => {
71
68
elements . push ( createImportSpecifier ( name === propertyName ? undefined : createIdentifier ( propertyName ) , createIdentifier ( name ) ) ) ;
72
69
} ) ;
73
- const namedImports = createNamedImports ( elements ) ;
70
+ const makeImportDeclaration = ( defaultImportName : Identifier | undefined ) =>
71
+ createImportDeclaration ( /*decorators*/ undefined , /*modifiers*/ undefined ,
72
+ createImportClause ( defaultImportName , elements . length ? createNamedImports ( elements ) : undefined ) ,
73
+ toConvert . parent . parent . moduleSpecifier ) ;
74
74
75
- if ( usedAsNamespace ) {
76
- changes . insertNodeAfter ( sourceFile , toConvert . parent . parent ,
77
- createImportDeclaration ( /*decorators*/ undefined , /*modifiers*/ undefined , createImportClause ( /*name*/ undefined , namedImports ) , toConvert . parent . parent . moduleSpecifier ) ) ;
75
+ if ( usedAsNamespaceOrDefault && ! allowSyntheticDefaultImports ) {
76
+ changes . insertNodeAfter ( sourceFile , toConvert . parent . parent , makeImportDeclaration ( /*defaultImportName*/ undefined ) ) ;
78
77
}
79
78
else {
80
- changes . replaceNode ( sourceFile , toConvert , namedImports ) ;
79
+ changes . replaceNode ( sourceFile , toConvert . parent . parent , makeImportDeclaration ( usedAsNamespaceOrDefault ? createIdentifier ( toConvert . name . text ) : undefined ) ) ;
81
80
}
82
81
}
83
82
@@ -88,20 +87,12 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
88
87
89
88
changes . replaceNode ( sourceFile , toConvert , createNamespaceImport ( createIdentifier ( namespaceImportName ) ) ) ;
90
89
91
- const nameToPropertyName = createMap < string > ( ) ;
92
90
for ( const element of toConvert . elements ) {
93
- if ( element . propertyName ) {
94
- nameToPropertyName . set ( element . name . text , element . propertyName . text ) ;
95
- }
91
+ const propertyName = ( element . propertyName || element . name ) . text ;
92
+ FindAllReferences . Core . eachSymbolReferenceInFile ( element . name , checker , sourceFile , id => {
93
+ changes . replaceNode ( sourceFile , id , createPropertyAccess ( createIdentifier ( namespaceImportName ) , propertyName ) ) ;
94
+ } ) ;
96
95
}
97
-
98
- const importedSymbols = toConvert . elements . map ( e => checker . getSymbolAtLocation ( e . name ) ! ) ;
99
-
100
- forEachFreeIdentifier ( sourceFile , id => {
101
- if ( ! toConvert . elements . some ( e => e . name === id ) && contains ( importedSymbols , checker . getSymbolAtLocation ( id ) ) ) {
102
- changes . replaceNode ( sourceFile , id , createPropertyAccess ( createIdentifier ( namespaceImportName ) , nameToPropertyName . get ( id . text ) || id . text ) ) ;
103
- }
104
- } ) ;
105
96
}
106
97
107
98
function generateName ( name : string , usedIdentifiers : ReadonlyMap < true > ) : string {
0 commit comments