@@ -679,51 +679,62 @@ namespace ts {
679679 * @param {boolean } onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary
680680 * in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
681681 */
682- function loadModuleFromFile ( candidate : string , extensions : string [ ] , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , state : ModuleResolutionState ) : string {
683- // First try to keep/add an extension: importing "./foo.ts" can be matched by a file "./foo.ts", and "./foo" by "./foo.d.ts"
684- const resolvedByAddingOrKeepingExtension = loadModuleFromFileWorker ( candidate , extensions , failedLookupLocation , onlyRecordFailures , state ) ;
685- if ( resolvedByAddingOrKeepingExtension ) {
686- return resolvedByAddingOrKeepingExtension ;
682+ function loadModuleFromFile ( candidate : string , extensions : string [ ] , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , state : ModuleResolutionState ) : string | undefined {
683+ // If the candidate already has an extension load that or quit.
684+ if ( hasTypeScriptFileExtension ( candidate ) ) {
685+ // Don't allow `.ts` to appear at the end
686+ if ( ! fileExtensionIs ( candidate , ".d.ts" ) ) {
687+ return undefined ;
688+ }
689+ return tryFile ( candidate , failedLookupLocation , onlyRecordFailures , state ) ;
687690 }
688- // Then try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one, e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
691+
692+ // Next, try adding an extension.
693+ // We don't allow an import of "foo.ts" to be matched by "foo.ts.ts", but we do allow "foo.js" to be matched by "foo.js.ts".
694+ const resolvedByAddingExtension = tryAddingExtensions ( candidate , extensions , failedLookupLocation , onlyRecordFailures , state ) ;
695+ if ( resolvedByAddingExtension ) {
696+ return resolvedByAddingExtension ;
697+ }
698+
699+ // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one;
700+ // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
689701 if ( hasJavaScriptFileExtension ( candidate ) ) {
690702 const extensionless = removeFileExtension ( candidate ) ;
691703 if ( state . traceEnabled ) {
692704 const extension = candidate . substring ( extensionless . length ) ;
693705 trace ( state . host , Diagnostics . File_name_0_has_a_1_extension_stripping_it , candidate , extension ) ;
694706 }
695- return loadModuleFromFileWorker ( extensionless , extensions , failedLookupLocation , onlyRecordFailures , state ) ;
707+ return tryAddingExtensions ( extensionless , extensions , failedLookupLocation , onlyRecordFailures , state ) ;
696708 }
697709 }
698710
699- function loadModuleFromFileWorker ( candidate : string , extensions : string [ ] , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , state : ModuleResolutionState ) : string {
711+ /** Try to return an existing file that adds one of the `extensions` to `candidate`. */
712+ function tryAddingExtensions ( candidate : string , extensions : string [ ] , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , state : ModuleResolutionState ) : string | undefined {
700713 if ( ! onlyRecordFailures ) {
701714 // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing
702715 const directory = getDirectoryPath ( candidate ) ;
703716 if ( directory ) {
704717 onlyRecordFailures = ! directoryProbablyExists ( directory , state . host ) ;
705718 }
706719 }
707- return forEach ( extensions , tryLoad ) ;
720+ return forEach ( extensions , ext =>
721+ ! ( state . skipTsx && isJsxOrTsxExtension ( ext ) ) && tryFile ( candidate + ext , failedLookupLocation , onlyRecordFailures , state ) ) ;
722+ }
708723
709- function tryLoad ( ext : string ) : string {
710- if ( state . skipTsx && isJsxOrTsxExtension ( ext ) ) {
711- return undefined ;
712- }
713- const fileName = fileExtensionIs ( candidate , ext ) ? candidate : candidate + ext ;
714- if ( ! onlyRecordFailures && state . host . fileExists ( fileName ) ) {
715- if ( state . traceEnabled ) {
716- trace ( state . host , Diagnostics . File_0_exist_use_it_as_a_name_resolution_result , fileName ) ;
717- }
718- return fileName ;
724+ /** Return the file if it exists. */
725+ function tryFile ( fileName : string , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , state : ModuleResolutionState ) : string | undefined {
726+ if ( ! onlyRecordFailures && state . host . fileExists ( fileName ) ) {
727+ if ( state . traceEnabled ) {
728+ trace ( state . host , Diagnostics . File_0_exist_use_it_as_a_name_resolution_result , fileName ) ;
719729 }
720- else {
721- if ( state . traceEnabled ) {
722- trace ( state . host , Diagnostics . File_0_does_not_exist , fileName ) ;
723- }
724- failedLookupLocation . push ( fileName ) ;
725- return undefined ;
730+ return fileName ;
731+ }
732+ else {
733+ if ( state . traceEnabled ) {
734+ trace ( state . host , Diagnostics . File_0_does_not_exist , fileName ) ;
726735 }
736+ failedLookupLocation . push ( fileName ) ;
737+ return undefined ;
727738 }
728739 }
729740
0 commit comments