1+ import { getModuleSpecifier } from "../../compiler/moduleSpecifiers" ;
12import {
23 AnyImportOrRequireStatement ,
34 append ,
@@ -16,13 +17,13 @@ import {
1617 concatenate ,
1718 contains ,
1819 copyEntries ,
20+ createModuleSpecifierResolutionHost ,
1921 createTextRangeFromSpan ,
2022 Debug ,
2123 Declaration ,
2224 DeclarationStatement ,
2325 Diagnostics ,
2426 emptyArray ,
25- ensurePathIsNonModuleName ,
2627 EnumDeclaration ,
2728 escapeLeadingUnderscores ,
2829 Expression ,
@@ -102,9 +103,9 @@ import {
102103 rangeContainsRange ,
103104 RefactorContext ,
104105 RefactorEditInfo ,
105- removeFileExtension ,
106106 RequireOrImportCall ,
107107 RequireVariableStatement ,
108+ resolvePath ,
108109 ScriptTarget ,
109110 skipAlias ,
110111 some ,
@@ -191,13 +192,12 @@ function doChange(oldFile: SourceFile, program: Program, toMove: ToMove, changes
191192
192193 const currentDirectory = getDirectoryPath ( oldFile . fileName ) ;
193194 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 ) ;
196196
197197 // 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 ) ) ;
199199
200- addNewFileToTsconfig ( program , changes , oldFile . fileName , newFileNameWithExtension , hostGetCanonicalFileName ( host ) ) ;
200+ addNewFileToTsconfig ( program , changes , oldFile . fileName , newFileBasename + extension , hostGetCanonicalFileName ( host ) ) ;
201201}
202202
203203interface StatementRange {
@@ -258,7 +258,7 @@ function addNewFileToTsconfig(program: Program, changes: textChanges.ChangeTrack
258258}
259259
260260function 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 ,
262262) {
263263 const checker = program . getTypeChecker ( ) ;
264264 const prologueDirectives = takeWhile ( oldFile . statements , isPrologueDirective ) ;
@@ -269,16 +269,16 @@ function getNewStatementsAndRemoveFromOldFile(
269269
270270 const useEsModuleSyntax = ! ! oldFile . externalModuleIndicator ;
271271 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 ) ;
273273 if ( importsFromNewFile ) {
274274 insertImports ( changes , oldFile , importsFromNewFile , /*blankLineBetween*/ true ) ;
275275 }
276276
277277 deleteUnusedOldImports ( oldFile , toMove . all , changes , usage . unusedImportsFromOldFile , checker ) ;
278278 deleteMovedStatements ( oldFile , toMove . ranges , changes ) ;
279- updateImportsInOtherFiles ( changes , program , oldFile , usage . movedSymbols , newModuleName ) ;
279+ updateImportsInOtherFiles ( changes , program , host , oldFile , usage . movedSymbols , newModuleName , extension ) ;
280280
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 ) ;
282282 const body = addExports ( oldFile , toMove . all , usage . oldFileImportsFromNewFile , useEsModuleSyntax ) ;
283283 if ( imports . length && body . length ) {
284284 return [
@@ -309,7 +309,9 @@ function deleteUnusedOldImports(oldFile: SourceFile, toMove: readonly Statement[
309309 }
310310}
311311
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 {
313315 const checker = program . getTypeChecker ( ) ;
314316 for ( const sourceFile of program . getSourceFiles ( ) ) {
315317 if ( sourceFile === oldFile ) continue ;
@@ -324,7 +326,9 @@ function updateImportsInOtherFiles(changes: textChanges.ChangeTracker, program:
324326 return ! ! symbol && movedSymbols . has ( symbol ) ;
325327 } ;
326328 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 ) ) ;
328332 const newImportDeclaration = filterImport ( importNode , factory . createStringLiteral ( newModuleSpecifier ) , shouldMove ) ;
329333 if ( newImportDeclaration ) changes . insertNodeAfter ( sourceFile , statement , newImportDeclaration ) ;
330334
@@ -431,7 +435,15 @@ type SupportedImportStatement =
431435 | ImportEqualsDeclaration
432436 | VariableStatement ;
433437
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 {
435447 let defaultImport : Identifier | undefined ;
436448 const imports : string [ ] = [ ] ;
437449 newFileNeedExport . forEach ( symbol => {
@@ -442,20 +454,31 @@ function createOldFileImportsFromNewFile(newFileNeedExport: ReadonlySymbolSet, n
442454 imports . push ( symbol . name ) ;
443455 }
444456 } ) ;
445- return makeImportOrRequire ( defaultImport , imports , newFileNameWithExtension , useEs6Imports , quotePreference ) ;
457+ return makeImportOrRequire ( sourceFile , defaultImport , imports , newFileNameWithExtension , program , host , useEs6Imports , quotePreference ) ;
446458}
447459
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+
450473 if ( useEs6Imports ) {
451474 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 ) ;
453476 }
454477 else {
455478 Debug . assert ( ! defaultImport , "No default import should exist" ) ; // If there's a default export, it should have been an es6 module.
456479 const bindingElements = imports . map ( i => factory . createBindingElement ( /*dotDotDotToken*/ undefined , /*propertyName*/ undefined , i ) ) ;
457480 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
459482 : undefined ;
460483 }
461484}
@@ -564,6 +587,8 @@ function getNewFileImportsAndAddExportInOldFile(
564587 newFileImportsFromOldFile : ReadonlySymbolSet ,
565588 changes : textChanges . ChangeTracker ,
566589 checker : TypeChecker ,
590+ program : Program ,
591+ host : LanguageServiceHost ,
567592 useEsModuleSyntax : boolean ,
568593 quotePreference : QuotePreference ,
569594) : readonly SupportedImportStatement [ ] {
@@ -600,7 +625,7 @@ function getNewFileImportsAndAddExportInOldFile(
600625 }
601626 } ) ;
602627
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 ) ) ;
604629 return copiedOldImports ;
605630}
606631
0 commit comments