@@ -334,11 +334,6 @@ namespace ts.server {
334
334
return project . dirty && project . updateGraph ( ) ;
335
335
}
336
336
337
- type ScriptInfoOrVersion = ScriptInfo | ScriptInfoVersion ;
338
- function isScriptInfoVersion ( infoOrVersion : ScriptInfoOrVersion ) : infoOrVersion is ScriptInfoVersion {
339
- return ( infoOrVersion as ScriptInfoVersion ) . svc !== undefined ;
340
- }
341
-
342
337
export class ProjectService {
343
338
344
339
/*@internal */
@@ -350,7 +345,13 @@ namespace ts.server {
350
345
/**
351
346
* Container of all known scripts
352
347
*/
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 > ( ) ;
354
355
// Set of all '.js' files ever opened.
355
356
private readonly allJsFilesForOpenFileTelemetry = createMap < true > ( ) ;
356
357
@@ -889,7 +890,7 @@ namespace ts.server {
889
890
890
891
project . close ( ) ;
891
892
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 ) ) ) ;
893
894
}
894
895
// Remove the project from pending project updates
895
896
this . pendingProjectUpdates . delete ( project . getProjectName ( ) ) ;
@@ -1026,7 +1027,8 @@ namespace ts.server {
1026
1027
}
1027
1028
1028
1029
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 ( ) ) ;
1030
1032
const realpath = info . getRealpathIfDifferent ( ) ;
1031
1033
if ( realpath ) {
1032
1034
this . realpathToScriptInfos ! . remove ( realpath , info ) ; // TODO: GH#18217
@@ -1855,8 +1857,8 @@ namespace ts.server {
1855
1857
private getOrCreateScriptInfoWorker ( fileName : NormalizedPath , currentDirectory : string , openedByClient : boolean , fileContent ?: string , scriptKind ?: ScriptKind , hasMixedContent ?: boolean , hostToQueryFileExistsOn ?: { fileExists ( path : string ) : boolean ; } ) {
1856
1858
Debug . assert ( fileContent === undefined || openedByClient , "ScriptInfo needs to be opened by client to be able to set its user defined content" ) ;
1857
1859
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 ) {
1860
1862
const isDynamic = isDynamicFileName ( fileName ) ;
1861
1863
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` ) ;
1862
1864
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 {
1865
1867
if ( ! openedByClient && ! isDynamic && ! ( hostToQueryFileExistsOn || this . host ) . fileExists ( fileName ) ) {
1866
1868
return ;
1867
1869
}
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
1869
1871
this . filenameToScriptInfo . set ( info . path , info ) ;
1872
+ this . filenameToScriptInfoVersion . delete ( info . path ) ;
1870
1873
if ( ! openedByClient ) {
1871
1874
this . watchClosedScriptInfo ( info ) ;
1872
1875
}
@@ -1899,8 +1902,7 @@ namespace ts.server {
1899
1902
}
1900
1903
1901
1904
getScriptInfoForPath ( fileName : Path ) {
1902
- const info = this . filenameToScriptInfo . get ( fileName ) ;
1903
- return info && isScriptInfoVersion ( info ) ? undefined : info ;
1905
+ return this . filenameToScriptInfo . get ( fileName ) ;
1904
1906
}
1905
1907
1906
1908
setHostConfiguration ( args : protocol . ConfigureRequestArguments ) {
@@ -2151,7 +2153,7 @@ namespace ts.server {
2151
2153
// It was then postponed to cleanup these script infos so that they can be reused if
2152
2154
// the file from that old project is reopened because of opening file from here.
2153
2155
this . filenameToScriptInfo . forEach ( info => {
2154
- if ( ! isScriptInfoVersion ( info ) && ! info . isScriptOpen ( ) && info . isOrphan ( ) ) {
2156
+ if ( ! info . isScriptOpen ( ) && info . isOrphan ( ) ) {
2155
2157
// if there are not projects that include this script info - delete it
2156
2158
this . stopWatchingScriptInfo ( info ) ;
2157
2159
this . deleteScriptInfo ( info ) ;
0 commit comments