1
+ import { getModuleSpecifier } from "../../compiler/moduleSpecifiers" ;
1
2
import {
2
3
AnyImportOrRequireStatement ,
3
4
append ,
@@ -16,13 +17,13 @@ import {
16
17
concatenate ,
17
18
contains ,
18
19
copyEntries ,
20
+ createModuleSpecifierResolutionHost ,
19
21
createTextRangeFromSpan ,
20
22
Debug ,
21
23
Declaration ,
22
24
DeclarationStatement ,
23
25
Diagnostics ,
24
26
emptyArray ,
25
- ensurePathIsNonModuleName ,
26
27
EnumDeclaration ,
27
28
escapeLeadingUnderscores ,
28
29
Expression ,
@@ -102,9 +103,9 @@ import {
102
103
rangeContainsRange ,
103
104
RefactorContext ,
104
105
RefactorEditInfo ,
105
- removeFileExtension ,
106
106
RequireOrImportCall ,
107
107
RequireVariableStatement ,
108
+ resolvePath ,
108
109
ScriptTarget ,
109
110
skipAlias ,
110
111
some ,
@@ -191,13 +192,12 @@ function doChange(oldFile: SourceFile, program: Program, toMove: ToMove, changes
191
192
192
193
const currentDirectory = getDirectoryPath ( oldFile . fileName ) ;
193
194
const extension = extensionFromPath ( oldFile . fileName ) ;
194
- const newModuleName = makeUniqueModuleName ( getNewModuleName ( usage . oldFileImportsFromNewFile , usage . movedSymbols ) , extension , currentDirectory , host ) ;
195
- const newFileNameWithExtension = newModuleName + extension ;
195
+ const newFileBasename = makeUniqueModuleName ( getNewModuleName ( usage . oldFileImportsFromNewFile , usage . movedSymbols ) , extension , currentDirectory , host ) ;
196
196
197
197
// If previous file was global, this is easy.
198
- changes . createNewFile ( oldFile , combinePaths ( currentDirectory , newFileNameWithExtension ) , getNewStatementsAndRemoveFromOldFile ( oldFile , usage , changes , toMove , program , newModuleName , preferences ) ) ;
198
+ changes . createNewFile ( oldFile , combinePaths ( currentDirectory , newFileBasename + extension ) , getNewStatementsAndRemoveFromOldFile ( oldFile , usage , changes , toMove , program , host , newFileBasename , extension , preferences ) ) ;
199
199
200
- addNewFileToTsconfig ( program , changes , oldFile . fileName , newFileNameWithExtension , hostGetCanonicalFileName ( host ) ) ;
200
+ addNewFileToTsconfig ( program , changes , oldFile . fileName , newFileBasename + extension , hostGetCanonicalFileName ( host ) ) ;
201
201
}
202
202
203
203
interface StatementRange {
@@ -258,7 +258,7 @@ function addNewFileToTsconfig(program: Program, changes: textChanges.ChangeTrack
258
258
}
259
259
260
260
function getNewStatementsAndRemoveFromOldFile (
261
- oldFile : SourceFile , usage : UsageInfo , changes : textChanges . ChangeTracker , toMove : ToMove , program : Program , newModuleName : string , preferences : UserPreferences ,
261
+ oldFile : SourceFile , usage : UsageInfo , changes : textChanges . ChangeTracker , toMove : ToMove , program : Program , host : LanguageServiceHost , newModuleName : string , extension : string , preferences : UserPreferences ,
262
262
) {
263
263
const checker = program . getTypeChecker ( ) ;
264
264
const prologueDirectives = takeWhile ( oldFile . statements , isPrologueDirective ) ;
@@ -269,16 +269,16 @@ function getNewStatementsAndRemoveFromOldFile(
269
269
270
270
const useEsModuleSyntax = ! ! oldFile . externalModuleIndicator ;
271
271
const quotePreference = getQuotePreference ( oldFile , preferences ) ;
272
- const importsFromNewFile = createOldFileImportsFromNewFile ( usage . oldFileImportsFromNewFile , newModuleName , useEsModuleSyntax , quotePreference ) ;
272
+ const importsFromNewFile = createOldFileImportsFromNewFile ( oldFile , usage . oldFileImportsFromNewFile , newModuleName + extension , program , host , useEsModuleSyntax , quotePreference ) ;
273
273
if ( importsFromNewFile ) {
274
274
insertImports ( changes , oldFile , importsFromNewFile , /*blankLineBetween*/ true ) ;
275
275
}
276
276
277
277
deleteUnusedOldImports ( oldFile , toMove . all , changes , usage . unusedImportsFromOldFile , checker ) ;
278
278
deleteMovedStatements ( oldFile , toMove . ranges , changes ) ;
279
- updateImportsInOtherFiles ( changes , program , oldFile , usage . movedSymbols , newModuleName ) ;
279
+ updateImportsInOtherFiles ( changes , program , host , oldFile , usage . movedSymbols , newModuleName , extension ) ;
280
280
281
- const imports = getNewFileImportsAndAddExportInOldFile ( oldFile , usage . oldImportsNeededByNewFile , usage . newFileImportsFromOldFile , changes , checker , useEsModuleSyntax , quotePreference ) ;
281
+ const imports = getNewFileImportsAndAddExportInOldFile ( oldFile , usage . oldImportsNeededByNewFile , usage . newFileImportsFromOldFile , changes , checker , program , host , useEsModuleSyntax , quotePreference ) ;
282
282
const body = addExports ( oldFile , toMove . all , usage . oldFileImportsFromNewFile , useEsModuleSyntax ) ;
283
283
if ( imports . length && body . length ) {
284
284
return [
@@ -309,7 +309,9 @@ function deleteUnusedOldImports(oldFile: SourceFile, toMove: readonly Statement[
309
309
}
310
310
}
311
311
312
- function updateImportsInOtherFiles ( changes : textChanges . ChangeTracker , program : Program , oldFile : SourceFile , movedSymbols : ReadonlySymbolSet , newModuleName : string ) : void {
312
+ function updateImportsInOtherFiles (
313
+ changes : textChanges . ChangeTracker , program : Program , host : LanguageServiceHost , oldFile : SourceFile , movedSymbols : ReadonlySymbolSet , newModuleName : string , extension : string
314
+ ) : void {
313
315
const checker = program . getTypeChecker ( ) ;
314
316
for ( const sourceFile of program . getSourceFiles ( ) ) {
315
317
if ( sourceFile === oldFile ) continue ;
@@ -324,7 +326,9 @@ function updateImportsInOtherFiles(changes: textChanges.ChangeTracker, program:
324
326
return ! ! symbol && movedSymbols . has ( symbol ) ;
325
327
} ;
326
328
deleteUnusedImports ( sourceFile , importNode , changes , shouldMove ) ; // These will be changed to imports from the new file
327
- const newModuleSpecifier = combinePaths ( getDirectoryPath ( moduleSpecifierFromImport ( importNode ) . text ) , newModuleName ) ;
329
+
330
+ const pathToNewFileWithExtension = resolvePath ( getDirectoryPath ( oldFile . path ) , newModuleName + extension ) ;
331
+ const newModuleSpecifier = getModuleSpecifier ( program . getCompilerOptions ( ) , sourceFile , sourceFile . path , pathToNewFileWithExtension , createModuleSpecifierResolutionHost ( program , host ) ) ;
328
332
const newImportDeclaration = filterImport ( importNode , factory . createStringLiteral ( newModuleSpecifier ) , shouldMove ) ;
329
333
if ( newImportDeclaration ) changes . insertNodeAfter ( sourceFile , statement , newImportDeclaration ) ;
330
334
@@ -431,7 +435,15 @@ type SupportedImportStatement =
431
435
| ImportEqualsDeclaration
432
436
| VariableStatement ;
433
437
434
- function createOldFileImportsFromNewFile ( newFileNeedExport : ReadonlySymbolSet , newFileNameWithExtension : string , useEs6Imports : boolean , quotePreference : QuotePreference ) : AnyImportOrRequireStatement | undefined {
438
+ function createOldFileImportsFromNewFile (
439
+ sourceFile : SourceFile ,
440
+ newFileNeedExport : ReadonlySymbolSet ,
441
+ newFileNameWithExtension : string ,
442
+ program : Program ,
443
+ host : LanguageServiceHost ,
444
+ useEs6Imports : boolean ,
445
+ quotePreference : QuotePreference
446
+ ) : AnyImportOrRequireStatement | undefined {
435
447
let defaultImport : Identifier | undefined ;
436
448
const imports : string [ ] = [ ] ;
437
449
newFileNeedExport . forEach ( symbol => {
@@ -442,20 +454,31 @@ function createOldFileImportsFromNewFile(newFileNeedExport: ReadonlySymbolSet, n
442
454
imports . push ( symbol . name ) ;
443
455
}
444
456
} ) ;
445
- return makeImportOrRequire ( defaultImport , imports , newFileNameWithExtension , useEs6Imports , quotePreference ) ;
457
+ return makeImportOrRequire ( sourceFile , defaultImport , imports , newFileNameWithExtension , program , host , useEs6Imports , quotePreference ) ;
446
458
}
447
459
448
- function makeImportOrRequire ( defaultImport : Identifier | undefined , imports : readonly string [ ] , path : string , useEs6Imports : boolean , quotePreference : QuotePreference ) : AnyImportOrRequireStatement | undefined {
449
- path = ensurePathIsNonModuleName ( path ) ;
460
+ function makeImportOrRequire (
461
+ sourceFile : SourceFile ,
462
+ defaultImport : Identifier | undefined ,
463
+ imports : readonly string [ ] ,
464
+ newFileNameWithExtension : string ,
465
+ program : Program ,
466
+ host : LanguageServiceHost ,
467
+ useEs6Imports : boolean ,
468
+ quotePreference : QuotePreference
469
+ ) : AnyImportOrRequireStatement | undefined {
470
+ const pathToNewFile = resolvePath ( getDirectoryPath ( sourceFile . path ) , newFileNameWithExtension ) ;
471
+ const pathToNewFileWithCorrectExtension = getModuleSpecifier ( program . getCompilerOptions ( ) , sourceFile , sourceFile . path , pathToNewFile , createModuleSpecifierResolutionHost ( program , host ) ) ;
472
+
450
473
if ( useEs6Imports ) {
451
474
const specifiers = imports . map ( i => factory . createImportSpecifier ( /*isTypeOnly*/ false , /*propertyName*/ undefined , factory . createIdentifier ( i ) ) ) ;
452
- return makeImportIfNecessary ( defaultImport , specifiers , path , quotePreference ) ;
475
+ return makeImportIfNecessary ( defaultImport , specifiers , pathToNewFileWithCorrectExtension , quotePreference ) ;
453
476
}
454
477
else {
455
478
Debug . assert ( ! defaultImport , "No default import should exist" ) ; // If there's a default export, it should have been an es6 module.
456
479
const bindingElements = imports . map ( i => factory . createBindingElement ( /*dotDotDotToken*/ undefined , /*propertyName*/ undefined , i ) ) ;
457
480
return bindingElements . length
458
- ? makeVariableStatement ( factory . createObjectBindingPattern ( bindingElements ) , /*type*/ undefined , createRequireCall ( factory . createStringLiteral ( path ) ) ) as RequireVariableStatement
481
+ ? makeVariableStatement ( factory . createObjectBindingPattern ( bindingElements ) , /*type*/ undefined , createRequireCall ( factory . createStringLiteral ( pathToNewFileWithCorrectExtension ) ) ) as RequireVariableStatement
459
482
: undefined ;
460
483
}
461
484
}
@@ -564,6 +587,8 @@ function getNewFileImportsAndAddExportInOldFile(
564
587
newFileImportsFromOldFile : ReadonlySymbolSet ,
565
588
changes : textChanges . ChangeTracker ,
566
589
checker : TypeChecker ,
590
+ program : Program ,
591
+ host : LanguageServiceHost ,
567
592
useEsModuleSyntax : boolean ,
568
593
quotePreference : QuotePreference ,
569
594
) : readonly SupportedImportStatement [ ] {
@@ -600,7 +625,7 @@ function getNewFileImportsAndAddExportInOldFile(
600
625
}
601
626
} ) ;
602
627
603
- append ( copiedOldImports , makeImportOrRequire ( oldFileDefault , oldFileNamedImports , removeFileExtension ( getBaseFileName ( oldFile . fileName ) ) , useEsModuleSyntax , quotePreference ) ) ;
628
+ append ( copiedOldImports , makeImportOrRequire ( oldFile , oldFileDefault , oldFileNamedImports , getBaseFileName ( oldFile . fileName ) , program , host , useEsModuleSyntax , quotePreference ) ) ;
604
629
return copiedOldImports ;
605
630
}
606
631
0 commit comments