@@ -989,22 +989,60 @@ namespace ts {
989989
990990 return program ;
991991
992- function resolveModuleNamesWorker ( moduleNames : string [ ] , containingFile : string , reusedNames ?: string [ ] , redirectedReference ?: ResolvedProjectReference ) {
992+ function resolveModuleNamesWorker ( moduleNames : string [ ] , containingFile : SourceFile , reusedNames : string [ ] | undefined ) : readonly ResolvedModuleFull [ ] {
993+ if ( ! moduleNames . length ) return emptyArray ;
994+ const containingFileName = getNormalizedAbsolutePath ( containingFile . originalFileName , currentDirectory ) ;
995+ const redirectedReference = getRedirectReferenceForResolution ( containingFile ) ;
993996 performance . mark ( "beforeResolveModule" ) ;
994- const result = actualResolveModuleNamesWorker ( moduleNames , containingFile , reusedNames , redirectedReference ) ;
997+ const result = actualResolveModuleNamesWorker ( moduleNames , containingFileName , reusedNames , redirectedReference ) ;
995998 performance . mark ( "afterResolveModule" ) ;
996999 performance . measure ( "ResolveModule" , "beforeResolveModule" , "afterResolveModule" ) ;
9971000 return result ;
9981001 }
9991002
1000- function resolveTypeReferenceDirectiveNamesWorker ( typeDirectiveNames : string [ ] , containingFile : string , redirectedReference ?: ResolvedProjectReference ) {
1003+ function resolveTypeReferenceDirectiveNamesWorker ( typeDirectiveNames : string [ ] , containingFile : string | SourceFile ) : readonly ( ResolvedTypeReferenceDirective | undefined ) [ ] {
1004+ if ( ! typeDirectiveNames . length ) return [ ] ;
10011005 performance . mark ( "beforeResolveTypeReference" ) ;
1002- const result = actualResolveTypeReferenceDirectiveNamesWorker ( typeDirectiveNames , containingFile , redirectedReference ) ;
1006+ const containingFileName = ! isString ( containingFile ) ? getNormalizedAbsolutePath ( containingFile . originalFileName , currentDirectory ) : containingFile ;
1007+ const redirectedReference = ! isString ( containingFile ) ? getRedirectReferenceForResolution ( containingFile ) : undefined ;
1008+ const result = actualResolveTypeReferenceDirectiveNamesWorker ( typeDirectiveNames , containingFileName , redirectedReference ) ;
10031009 performance . mark ( "afterResolveTypeReference" ) ;
10041010 performance . measure ( "ResolveTypeReference" , "beforeResolveTypeReference" , "afterResolveTypeReference" ) ;
10051011 return result ;
10061012 }
10071013
1014+ function getRedirectReferenceForResolution ( file : SourceFile ) {
1015+ const redirect = getResolvedProjectReferenceToRedirect ( file . originalFileName ) ;
1016+ if ( redirect || ! fileExtensionIs ( file . originalFileName , Extension . Dts ) ) return redirect ;
1017+
1018+ // The originalFileName could not be actual source file name if file found was d.ts from referecned project
1019+ // So in this case try to look up if this is output from referenced project, if it is use the redirected project in that case
1020+ const resultFromDts = getRedirectReferenceForResolutionFromSourceOfProject ( file . originalFileName , file . path ) ;
1021+ if ( resultFromDts ) return resultFromDts ;
1022+
1023+ // If preserveSymlinks is true, module resolution wont jump the symlink
1024+ // but the resolved real path may be the .d.ts from project reference
1025+ // Note:: Currently we try the real path only if the
1026+ // file is from node_modules to avoid having to run real path on all file paths
1027+ if ( ! host . realpath || ! options . preserveSymlinks || ! stringContains ( file . originalFileName , nodeModulesPathPart ) ) return undefined ;
1028+ const realDeclarationFileName = host . realpath ( file . originalFileName ) ;
1029+ const realDeclarationPath = toPath ( realDeclarationFileName ) ;
1030+ return realDeclarationPath === file . path ? undefined : getRedirectReferenceForResolutionFromSourceOfProject ( realDeclarationFileName , realDeclarationPath ) ;
1031+ }
1032+
1033+ function getRedirectReferenceForResolutionFromSourceOfProject ( fileName : string , filePath : Path ) {
1034+ const source = getSourceOfProjectReferenceRedirect ( fileName ) ;
1035+ if ( isString ( source ) ) return getResolvedProjectReferenceToRedirect ( source ) ;
1036+ if ( ! source ) return undefined ;
1037+ // Output of .d.ts file so return resolved ref that matches the out file name
1038+ return forEachResolvedProjectReference ( resolvedRef => {
1039+ if ( ! resolvedRef ) return undefined ;
1040+ const out = outFile ( resolvedRef . commandLine . options ) ;
1041+ if ( ! out ) return undefined ;
1042+ return toPath ( out ) === filePath ? resolvedRef : undefined ;
1043+ } ) ;
1044+ }
1045+
10081046 function compareDefaultLibFiles ( a : SourceFile , b : SourceFile ) {
10091047 return compareValues ( getDefaultLibFilePriority ( a ) , getDefaultLibFilePriority ( b ) ) ;
10101048 }
@@ -1068,14 +1106,14 @@ namespace ts {
10681106 return classifiableNames ;
10691107 }
10701108
1071- function resolveModuleNamesReusingOldState ( moduleNames : string [ ] , containingFile : string , file : SourceFile ) {
1109+ function resolveModuleNamesReusingOldState ( moduleNames : string [ ] , file : SourceFile ) : readonly ResolvedModuleFull [ ] {
10721110 if ( structuralIsReused === StructureIsReused . Not && ! file . ambientModuleNames . length ) {
10731111 // If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
10741112 // the best we can do is fallback to the default logic.
1075- return resolveModuleNamesWorker ( moduleNames , containingFile , /*reusedNames*/ undefined , getResolvedProjectReferenceToRedirect ( file . originalFileName ) ) ;
1113+ return resolveModuleNamesWorker ( moduleNames , file , /*reusedNames*/ undefined ) ;
10761114 }
10771115
1078- const oldSourceFile = oldProgram && oldProgram . getSourceFile ( containingFile ) ;
1116+ const oldSourceFile = oldProgram && oldProgram . getSourceFile ( file . fileName ) ;
10791117 if ( oldSourceFile !== file && file . resolvedModules ) {
10801118 // `file` was created for the new program.
10811119 //
@@ -1120,7 +1158,7 @@ namespace ts {
11201158 const oldResolvedModule = getResolvedModule ( oldSourceFile , moduleName ) ;
11211159 if ( oldResolvedModule ) {
11221160 if ( isTraceEnabled ( options , host ) ) {
1123- trace ( host , Diagnostics . Reusing_resolution_of_module_0_to_file_1_from_old_program , moduleName , containingFile ) ;
1161+ trace ( host , Diagnostics . Reusing_resolution_of_module_0_to_file_1_from_old_program , moduleName , getNormalizedAbsolutePath ( file . originalFileName , currentDirectory ) ) ;
11241162 }
11251163 ( result || ( result = new Array ( moduleNames . length ) ) ) [ i ] = oldResolvedModule ;
11261164 ( reusedNames || ( reusedNames = [ ] ) ) . push ( moduleName ) ;
@@ -1135,7 +1173,7 @@ namespace ts {
11351173 if ( contains ( file . ambientModuleNames , moduleName ) ) {
11361174 resolvesToAmbientModuleInNonModifiedFile = true ;
11371175 if ( isTraceEnabled ( options , host ) ) {
1138- trace ( host , Diagnostics . Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1 , moduleName , containingFile ) ;
1176+ trace ( host , Diagnostics . Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1 , moduleName , getNormalizedAbsolutePath ( file . originalFileName , currentDirectory ) ) ;
11391177 }
11401178 }
11411179 else {
@@ -1152,7 +1190,7 @@ namespace ts {
11521190 }
11531191
11541192 const resolutions = unknownModuleNames && unknownModuleNames . length
1155- ? resolveModuleNamesWorker ( unknownModuleNames , containingFile , reusedNames , getResolvedProjectReferenceToRedirect ( file . originalFileName ) )
1193+ ? resolveModuleNamesWorker ( unknownModuleNames , file , reusedNames )
11561194 : emptyArray ;
11571195
11581196 // Combine results of resolutions and predicted results
@@ -1397,9 +1435,8 @@ namespace ts {
13971435 }
13981436 // try to verify results of module resolution
13991437 for ( const { oldFile : oldSourceFile , newFile : newSourceFile } of modifiedSourceFiles ) {
1400- const newSourceFilePath = getNormalizedAbsolutePath ( newSourceFile . originalFileName , currentDirectory ) ;
14011438 const moduleNames = getModuleNames ( newSourceFile ) ;
1402- const resolutions = resolveModuleNamesReusingOldState ( moduleNames , newSourceFilePath , newSourceFile ) ;
1439+ const resolutions = resolveModuleNamesReusingOldState ( moduleNames , newSourceFile ) ;
14031440 // ensure that module resolution results are still correct
14041441 const resolutionsChanged = hasChangesInResolutions ( moduleNames , resolutions , oldSourceFile . resolvedModules , moduleResolutionIsEqualTo ) ;
14051442 if ( resolutionsChanged ) {
@@ -1409,19 +1446,17 @@ namespace ts {
14091446 else {
14101447 newSourceFile . resolvedModules = oldSourceFile . resolvedModules ;
14111448 }
1412- if ( resolveTypeReferenceDirectiveNamesWorker ) {
1413- // We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
1414- const typesReferenceDirectives = map ( newSourceFile . typeReferenceDirectives , ref => toFileNameLowerCase ( ref . fileName ) ) ;
1415- const resolutions = resolveTypeReferenceDirectiveNamesWorker ( typesReferenceDirectives , newSourceFilePath , getResolvedProjectReferenceToRedirect ( newSourceFile . originalFileName ) ) ;
1416- // ensure that types resolutions are still correct
1417- const resolutionsChanged = hasChangesInResolutions ( typesReferenceDirectives , resolutions , oldSourceFile . resolvedTypeReferenceDirectiveNames , typeDirectiveIsEqualTo ) ;
1418- if ( resolutionsChanged ) {
1419- oldProgram . structureIsReused = StructureIsReused . SafeModules ;
1420- newSourceFile . resolvedTypeReferenceDirectiveNames = zipToMap ( typesReferenceDirectives , resolutions ) ;
1421- }
1422- else {
1423- newSourceFile . resolvedTypeReferenceDirectiveNames = oldSourceFile . resolvedTypeReferenceDirectiveNames ;
1424- }
1449+ // We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
1450+ const typesReferenceDirectives = map ( newSourceFile . typeReferenceDirectives , ref => toFileNameLowerCase ( ref . fileName ) ) ;
1451+ const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesWorker ( typesReferenceDirectives , newSourceFile ) ;
1452+ // ensure that types resolutions are still correct
1453+ const typeReferenceEesolutionsChanged = hasChangesInResolutions ( typesReferenceDirectives , typeReferenceResolutions , oldSourceFile . resolvedTypeReferenceDirectiveNames , typeDirectiveIsEqualTo ) ;
1454+ if ( typeReferenceEesolutionsChanged ) {
1455+ oldProgram . structureIsReused = StructureIsReused . SafeModules ;
1456+ newSourceFile . resolvedTypeReferenceDirectiveNames = zipToMap ( typesReferenceDirectives , typeReferenceResolutions ) ;
1457+ }
1458+ else {
1459+ newSourceFile . resolvedTypeReferenceDirectiveNames = oldSourceFile . resolvedTypeReferenceDirectiveNames ;
14251460 }
14261461 }
14271462
@@ -2685,7 +2720,7 @@ namespace ts {
26852720 return ;
26862721 }
26872722
2688- const resolutions = resolveTypeReferenceDirectiveNamesWorker ( typeDirectives , file . originalFileName , getResolvedProjectReferenceToRedirect ( file . originalFileName ) ) ;
2723+ const resolutions = resolveTypeReferenceDirectiveNamesWorker ( typeDirectives , file ) ;
26892724
26902725 for ( let i = 0 ; i < typeDirectives . length ; i ++ ) {
26912726 const ref = file . typeReferenceDirectives [ i ] ;
@@ -2823,7 +2858,7 @@ namespace ts {
28232858 if ( file . imports . length || file . moduleAugmentations . length ) {
28242859 // Because global augmentation doesn't have string literal name, we can check for global augmentation as such.
28252860 const moduleNames = getModuleNames ( file ) ;
2826- const resolutions = resolveModuleNamesReusingOldState ( moduleNames , getNormalizedAbsolutePath ( file . originalFileName , currentDirectory ) , file ) ;
2861+ const resolutions = resolveModuleNamesReusingOldState ( moduleNames , file ) ;
28272862 Debug . assert ( resolutions . length === moduleNames . length ) ;
28282863 for ( let i = 0 ; i < moduleNames . length ; i ++ ) {
28292864 const resolution = resolutions [ i ] ;
0 commit comments