@@ -334,11 +334,6 @@ namespace ts.server {
334334 return project . dirty && project . updateGraph ( ) ;
335335 }
336336
337- type ScriptInfoOrVersion = ScriptInfo | ScriptInfoVersion ;
338- function isScriptInfoVersion ( infoOrVersion : ScriptInfoOrVersion ) : infoOrVersion is ScriptInfoVersion {
339- return ( infoOrVersion as ScriptInfoVersion ) . svc !== undefined ;
340- }
341-
342337 export class ProjectService {
343338
344339 /*@internal */
@@ -350,7 +345,13 @@ namespace ts.server {
350345 /**
351346 * Container of all known scripts
352347 */
353- private readonly filenameToScriptInfo = createMap < ScriptInfoOrVersion > ( ) ;
348+ private readonly filenameToScriptInfo = createMap < ScriptInfo > ( ) ;
349+ /**
350+ * Contains all the deleted script info's version information so that
351+ * it does not reset when creating script info again
352+ * (and could have potentially collided with version where contents mismatch)
353+ */
354+ private readonly filenameToScriptInfoVersion = createMap < ScriptInfoVersion > ( ) ;
354355 // Set of all '.js' files ever opened.
355356 private readonly allJsFilesForOpenFileTelemetry = createMap < true > ( ) ;
356357
@@ -889,7 +890,7 @@ namespace ts.server {
889890
890891 project . close ( ) ;
891892 if ( Debug . shouldAssert ( AssertionLevel . Normal ) ) {
892- this . filenameToScriptInfo . forEach ( info => Debug . assert ( isScriptInfoVersion ( info ) || ! info . isAttached ( project ) ) ) ;
893+ this . filenameToScriptInfo . forEach ( info => Debug . assert ( ! info . isAttached ( project ) ) ) ;
893894 }
894895 // Remove the project from pending project updates
895896 this . pendingProjectUpdates . delete ( project . getProjectName ( ) ) ;
@@ -1026,7 +1027,8 @@ namespace ts.server {
10261027 }
10271028
10281029 private deleteScriptInfo ( info : ScriptInfo ) {
1029- this . filenameToScriptInfo . set ( info . path , info . getVersion ( ) ) ;
1030+ this . filenameToScriptInfo . delete ( info . path ) ;
1031+ this . filenameToScriptInfoVersion . set ( info . path , info . getVersion ( ) ) ;
10301032 const realpath = info . getRealpathIfDifferent ( ) ;
10311033 if ( realpath ) {
10321034 this . realpathToScriptInfos ! . remove ( realpath , info ) ; // TODO: GH#18217
@@ -1855,8 +1857,8 @@ namespace ts.server {
18551857 private getOrCreateScriptInfoWorker ( fileName : NormalizedPath , currentDirectory : string , openedByClient : boolean , fileContent ?: string , scriptKind ?: ScriptKind , hasMixedContent ?: boolean , hostToQueryFileExistsOn ?: { fileExists ( path : string ) : boolean ; } ) {
18561858 Debug . assert ( fileContent === undefined || openedByClient , "ScriptInfo needs to be opened by client to be able to set its user defined content" ) ;
18571859 const path = normalizedPathToPath ( fileName , currentDirectory , this . toCanonicalFileName ) ;
1858- let info = this . filenameToScriptInfo . get ( path ) ;
1859- if ( ! info || isScriptInfoVersion ( info ) ) {
1860+ let info = this . getScriptInfoForPath ( path ) ;
1861+ if ( ! info ) {
18601862 const isDynamic = isDynamicFileName ( fileName ) ;
18611863 Debug . assert ( isRootedDiskPath ( fileName ) || isDynamic || openedByClient , "" , ( ) => `${ JSON . stringify ( { fileName, currentDirectory, hostCurrentDirectory : this . currentDirectory , openKeys : arrayFrom ( this . openFilesWithNonRootedDiskPath . keys ( ) ) } ) } \nScript info with non-dynamic relative file name can only be open script info` ) ;
18621864 Debug . assert ( ! isRootedDiskPath ( fileName ) || this . currentDirectory === currentDirectory || ! this . openFilesWithNonRootedDiskPath . has ( this . toCanonicalFileName ( fileName ) ) , "" , ( ) => `${ JSON . stringify ( { fileName, currentDirectory, hostCurrentDirectory : this . currentDirectory , openKeys : arrayFrom ( this . openFilesWithNonRootedDiskPath . keys ( ) ) } ) } \nOpen script files with non rooted disk path opened with current directory context cannot have same canonical names` ) ;
@@ -1865,8 +1867,9 @@ namespace ts.server {
18651867 if ( ! openedByClient && ! isDynamic && ! ( hostToQueryFileExistsOn || this . host ) . fileExists ( fileName ) ) {
18661868 return ;
18671869 }
1868- info = new ScriptInfo ( this . host , fileName , scriptKind ! , ! ! hasMixedContent , path , info ) ; // TODO: GH#18217
1870+ info = new ScriptInfo ( this . host , fileName , scriptKind ! , ! ! hasMixedContent , path , this . filenameToScriptInfoVersion . get ( path ) ) ; // TODO: GH#18217
18691871 this . filenameToScriptInfo . set ( info . path , info ) ;
1872+ this . filenameToScriptInfoVersion . delete ( info . path ) ;
18701873 if ( ! openedByClient ) {
18711874 this . watchClosedScriptInfo ( info ) ;
18721875 }
@@ -1899,8 +1902,7 @@ namespace ts.server {
18991902 }
19001903
19011904 getScriptInfoForPath ( fileName : Path ) {
1902- const info = this . filenameToScriptInfo . get ( fileName ) ;
1903- return info && isScriptInfoVersion ( info ) ? undefined : info ;
1905+ return this . filenameToScriptInfo . get ( fileName ) ;
19041906 }
19051907
19061908 setHostConfiguration ( args : protocol . ConfigureRequestArguments ) {
@@ -2151,7 +2153,7 @@ namespace ts.server {
21512153 // It was then postponed to cleanup these script infos so that they can be reused if
21522154 // the file from that old project is reopened because of opening file from here.
21532155 this . filenameToScriptInfo . forEach ( info => {
2154- if ( ! isScriptInfoVersion ( info ) && ! info . isScriptOpen ( ) && info . isOrphan ( ) ) {
2156+ if ( ! info . isScriptOpen ( ) && info . isOrphan ( ) ) {
21552157 // if there are not projects that include this script info - delete it
21562158 this . stopWatchingScriptInfo ( info ) ;
21572159 this . deleteScriptInfo ( info ) ;
0 commit comments