@@ -2197,8 +2197,8 @@ namespace ts.server {
21972197 }
21982198
21992199 /*@internal */
2200- getDocumentPositionMapper ( fileName : string , project : Project ) : DocumentPositionMapper | undefined {
2201- const declarationInfo = this . getOrCreateScriptInfoNotOpenedByClient ( fileName , project . currentDirectory , project . directoryStructureHost ) ;
2200+ getDocumentPositionMapper ( project : Project , generatedFileName : string , sourceFileName ?: string ) : DocumentPositionMapper | undefined {
2201+ const declarationInfo = this . getOrCreateScriptInfoNotOpenedByClient ( generatedFileName , project . currentDirectory , project . directoryStructureHost ) ;
22022202 if ( ! declarationInfo ) return undefined ;
22032203
22042204 declarationInfo . getSnapshot ( ) ; // Ensure synchronized
@@ -2210,7 +2210,6 @@ namespace ts.server {
22102210 // Create the mapper
22112211 declarationInfo . mapInfo = undefined ;
22122212
2213- // TODO: shkamat Lifetime of declarationInfo and mapInfo
22142213 let readMapFile : ( ( fileName : string ) => string | undefined ) | undefined = fileName => {
22152214 const mapInfo = this . getOrCreateScriptInfoNotOpenedByClient ( fileName , project . currentDirectory , project . directoryStructureHost ) ;
22162215 if ( ! mapInfo ) return undefined ;
@@ -2227,6 +2226,11 @@ namespace ts.server {
22272226 ) ;
22282227 readMapFile = undefined ; // Remove ref to project
22292228 declarationInfo . mapper = mapper || false ;
2229+ if ( sourceFileName && mapper ) {
2230+ // Attach as source
2231+ const sourceInfo = this . getOrCreateScriptInfoNotOpenedByClient ( sourceFileName , project . currentDirectory , project . directoryStructureHost ) ! ;
2232+ ( declarationInfo . mapInfo ! . sourceInfos || ( declarationInfo . mapInfo ! . sourceInfos = createMap ( ) ) ) . set ( sourceInfo . path , true ) ;
2233+ }
22302234 return mapper ;
22312235 }
22322236
@@ -2609,13 +2613,25 @@ namespace ts.server {
26092613 private removeOrphanScriptInfos ( ) {
26102614 const toRemoveScriptInfos = cloneMap ( this . filenameToScriptInfo ) ;
26112615 this . filenameToScriptInfo . forEach ( info => {
2612- if ( info . isScriptOpen ( ) || ! info . isOrphan ( ) ) {
2613- toRemoveScriptInfos . delete ( info . path ) ;
2614- if ( info . mapInfo ) {
2615- toRemoveScriptInfos . delete ( info . mapInfo . path ) ;
2616- if ( info . mapInfo . sourceInfos ) {
2617- info . mapInfo . sourceInfos . forEach ( ( _value , path ) => toRemoveScriptInfos . delete ( path ) ) ;
2618- }
2616+ // If script info is open or orphan, retain it and its dependencies
2617+ if ( ! info . isScriptOpen ( ) && info . isOrphan ( ) ) {
2618+ // Otherwise if there is any source info that is alive, this alive too
2619+ if ( ! info . mapInfo || ! info . mapInfo . sourceInfos ) return ;
2620+ if ( ! forEachKey ( info . mapInfo . sourceInfos , path => {
2621+ const info = this . getScriptInfoForPath ( path as Path ) ! ;
2622+ return info . isScriptOpen ( ) || ! info . isOrphan ( ) ;
2623+ } ) ) {
2624+ return ;
2625+ }
2626+ }
2627+
2628+ // Retain this script info
2629+ toRemoveScriptInfos . delete ( info . path ) ;
2630+ if ( info . mapInfo ) {
2631+ // And map file info and source infos
2632+ toRemoveScriptInfos . delete ( info . mapInfo . path ) ;
2633+ if ( info . mapInfo . sourceInfos ) {
2634+ info . mapInfo . sourceInfos . forEach ( ( _value , path ) => toRemoveScriptInfos . delete ( path ) ) ;
26192635 }
26202636 }
26212637 } ) ;
0 commit comments