@@ -352,9 +352,9 @@ namespace ts.server {
352
352
*/
353
353
readonly configuredProjects = createMap < ConfiguredProject > ( ) ;
354
354
/**
355
- * list of open files
355
+ * Open files: with value being project root path, and key being Path of the file that is open
356
356
*/
357
- readonly openFiles : ScriptInfo [ ] = [ ] ;
357
+ readonly openFiles = createMap < NormalizedPath > ( ) ;
358
358
359
359
private compilerOptionsForInferredProjects : CompilerOptions ;
360
360
private compilerOptionsForInferredProjectsPerProjectRoot = createMap < CompilerOptions > ( ) ;
@@ -582,7 +582,7 @@ namespace ts.server {
582
582
const event : ProjectsUpdatedInBackgroundEvent = {
583
583
eventName : ProjectsUpdatedInBackgroundEvent ,
584
584
data : {
585
- openFiles : this . openFiles . map ( f => f . fileName )
585
+ openFiles : arrayFrom ( this . openFiles . keys ( ) , path => this . getScriptInfoForPath ( path as Path ) . fileName )
586
586
}
587
587
} ;
588
588
this . eventHandler ( event ) ;
@@ -891,7 +891,7 @@ namespace ts.server {
891
891
}
892
892
893
893
/*@internal */
894
- assignOrphanScriptInfoToInferredProject ( info : ScriptInfo , projectRootPath ?: string ) {
894
+ assignOrphanScriptInfoToInferredProject ( info : ScriptInfo , projectRootPath : NormalizedPath | undefined ) {
895
895
Debug . assert ( info . isOrphan ( ) ) ;
896
896
897
897
const project = this . getOrCreateInferredProjectForProjectRootPathIfEnabled ( info , projectRootPath ) ||
@@ -935,7 +935,7 @@ namespace ts.server {
935
935
info . close ( ) ;
936
936
this . stopWatchingConfigFilesForClosedScriptInfo ( info ) ;
937
937
938
- unorderedRemoveItem ( this . openFiles , info ) ;
938
+ this . openFiles . delete ( info . path ) ;
939
939
940
940
const fileExists = this . host . fileExists ( info . fileName ) ;
941
941
@@ -974,11 +974,12 @@ namespace ts.server {
974
974
}
975
975
976
976
// collect orphaned files and assign them to inferred project just like we treat open of a file
977
- for ( const f of this . openFiles ) {
977
+ this . openFiles . forEach ( ( projectRootPath , path ) => {
978
+ const f = this . getScriptInfoForPath ( path as Path ) ;
978
979
if ( f . isOrphan ( ) ) {
979
- this . assignOrphanScriptInfoToInferredProject ( f ) ;
980
+ this . assignOrphanScriptInfoToInferredProject ( f , projectRootPath ) ;
980
981
}
981
- }
982
+ } ) ;
982
983
983
984
// Cleanup script infos that arent part of any project (eg. those could be closed script infos not referenced by any project)
984
985
// is postponed to next file open so that if file from same project is opened,
@@ -1172,7 +1173,7 @@ namespace ts.server {
1172
1173
* This is called by inferred project whenever script info is added as a root
1173
1174
*/
1174
1175
/* @internal */
1175
- startWatchingConfigFilesForInferredProjectRoot ( info : ScriptInfo ) {
1176
+ startWatchingConfigFilesForInferredProjectRoot ( info : ScriptInfo , projectRootPath : NormalizedPath | undefined ) {
1176
1177
Debug . assert ( info . isScriptOpen ( ) ) ;
1177
1178
this . forEachConfigFileLocation ( info , ( configFileName , canonicalConfigFilePath ) => {
1178
1179
let configFileExistenceInfo = this . configFileExistenceInfoCache . get ( canonicalConfigFilePath ) ;
@@ -1194,7 +1195,7 @@ namespace ts.server {
1194
1195
! this . getConfiguredProjectByCanonicalConfigFilePath ( canonicalConfigFilePath ) ) {
1195
1196
this . createConfigFileWatcherOfConfigFileExistence ( configFileName , canonicalConfigFilePath , configFileExistenceInfo ) ;
1196
1197
}
1197
- } ) ;
1198
+ } , projectRootPath ) ;
1198
1199
}
1199
1200
1200
1201
/**
@@ -1262,7 +1263,7 @@ namespace ts.server {
1262
1263
* The server must start searching from the directory containing
1263
1264
* the newly opened file.
1264
1265
*/
1265
- private getConfigFileNameForFile ( info : ScriptInfo , projectRootPath ? : NormalizedPath ) {
1266
+ private getConfigFileNameForFile ( info : ScriptInfo , projectRootPath : NormalizedPath | undefined ) {
1266
1267
Debug . assert ( info . isScriptOpen ( ) ) ;
1267
1268
this . logger . info ( `Search path: ${ getDirectoryPath ( info . fileName ) } ` ) ;
1268
1269
const configFileName = this . forEachConfigFileLocation ( info ,
@@ -1301,9 +1302,9 @@ namespace ts.server {
1301
1302
printProjects ( this . inferredProjects , counter ) ;
1302
1303
1303
1304
this . logger . info ( "Open files: " ) ;
1304
- for ( const rootFile of this . openFiles ) {
1305
- this . logger . info ( `\t ${ rootFile . fileName } ` ) ;
1306
- }
1305
+ this . openFiles . forEach ( ( projectRootPath , path ) => {
1306
+ this . logger . info ( `\tFileName: ${ this . getScriptInfoForPath ( path as Path ) . fileName } ProjectRootPath: ${ projectRootPath } ` ) ;
1307
+ } ) ;
1307
1308
1308
1309
this . logger . endGroup ( ) ;
1309
1310
}
@@ -1605,7 +1606,7 @@ namespace ts.server {
1605
1606
} ) ;
1606
1607
}
1607
1608
1608
- private getOrCreateInferredProjectForProjectRootPathIfEnabled ( info : ScriptInfo , projectRootPath : string | undefined ) : InferredProject | undefined {
1609
+ private getOrCreateInferredProjectForProjectRootPathIfEnabled ( info : ScriptInfo , projectRootPath : NormalizedPath | undefined ) : InferredProject | undefined {
1609
1610
if ( ! this . useInferredProjectPerProjectRoot ) {
1610
1611
return undefined ;
1611
1612
}
@@ -1659,7 +1660,7 @@ namespace ts.server {
1659
1660
return this . createInferredProject ( /*currentDirectory*/ undefined , /*isSingleInferredProject*/ true ) ;
1660
1661
}
1661
1662
1662
- private createInferredProject ( currentDirectory : string | undefined , isSingleInferredProject ?: boolean , projectRootPath ?: string ) : InferredProject {
1663
+ private createInferredProject ( currentDirectory : string | undefined , isSingleInferredProject ?: boolean , projectRootPath ?: NormalizedPath ) : InferredProject {
1663
1664
const compilerOptions = projectRootPath && this . compilerOptionsForInferredProjectsPerProjectRoot . get ( projectRootPath ) || this . compilerOptionsForInferredProjects ;
1664
1665
const project = new InferredProject ( this , this . documentRegistry , compilerOptions , projectRootPath , currentDirectory ) ;
1665
1666
if ( isSingleInferredProject ) {
@@ -1796,23 +1797,19 @@ namespace ts.server {
1796
1797
// as there is no need to load contents of the files from the disk
1797
1798
1798
1799
// Reload Projects
1799
- this . reloadConfiguredProjectForFiles ( this . openFiles , /*delayReload*/ false ) ;
1800
+ this . reloadConfiguredProjectForFiles ( this . openFiles , /*delayReload*/ false , returnTrue ) ;
1800
1801
this . refreshInferredProjects ( ) ;
1801
1802
}
1802
1803
1803
1804
private delayReloadConfiguredProjectForFiles ( configFileExistenceInfo : ConfigFileExistenceInfo , ignoreIfNotRootOfInferredProject : boolean ) {
1804
1805
// Get open files to reload projects for
1805
- const openFiles = mapDefinedIter (
1806
- configFileExistenceInfo . openFilesImpactedByConfigFile . entries ( ) ,
1807
- ( [ path , isRootOfInferredProject ] ) => {
1808
- if ( ! ignoreIfNotRootOfInferredProject || isRootOfInferredProject ) {
1809
- const info = this . getScriptInfoForPath ( path as Path ) ;
1810
- Debug . assert ( ! ! info ) ;
1811
- return info ;
1812
- }
1813
- }
1806
+ this . reloadConfiguredProjectForFiles (
1807
+ configFileExistenceInfo . openFilesImpactedByConfigFile ,
1808
+ /*delayReload*/ true ,
1809
+ ignoreIfNotRootOfInferredProject ?
1810
+ isRootOfInferredProject => isRootOfInferredProject : // Reload open files if they are root of inferred project
1811
+ returnTrue // Reload all the open files impacted by config file
1814
1812
) ;
1815
- this . reloadConfiguredProjectForFiles ( openFiles , /*delayReload*/ true ) ;
1816
1813
this . delayInferredProjectsRefresh ( ) ;
1817
1814
}
1818
1815
@@ -1821,16 +1818,24 @@ namespace ts.server {
1821
1818
* If the config file is found and it refers to existing project, it reloads it either immediately
1822
1819
* or schedules it for reload depending on delayReload option
1823
1820
* If the there is no existing project it just opens the configured project for the config file
1821
+ * reloadForInfo provides a way to filter out files to reload configured project for
1824
1822
*/
1825
- private reloadConfiguredProjectForFiles ( openFiles : ReadonlyArray < ScriptInfo > , delayReload : boolean ) {
1823
+ private reloadConfiguredProjectForFiles < T > ( openFiles : Map < T > , delayReload : boolean , shouldReloadProjectFor : ( openFileValue : T ) => boolean ) {
1826
1824
const updatedProjects = createMap < true > ( ) ;
1827
1825
// try to reload config file for all open files
1828
- for ( const info of openFiles ) {
1826
+ openFiles . forEach ( ( openFileValue , path ) => {
1827
+ // Filter out the files that need to be ignored
1828
+ if ( ! shouldReloadProjectFor ( openFileValue ) ) {
1829
+ return ;
1830
+ }
1831
+
1832
+ const info = this . getScriptInfoForPath ( path as Path ) ;
1833
+ Debug . assert ( info . isScriptOpen ( ) ) ;
1829
1834
// This tries to search for a tsconfig.json for the given file. If we found it,
1830
1835
// we first detect if there is already a configured project created for it: if so,
1831
1836
// we re- read the tsconfig file content and update the project only if we havent already done so
1832
1837
// otherwise we create a new one.
1833
- const configFileName = this . getConfigFileNameForFile ( info ) ;
1838
+ const configFileName = this . getConfigFileNameForFile ( info , this . openFiles . get ( path ) ) ;
1834
1839
if ( configFileName ) {
1835
1840
const project = this . findConfiguredProjectByProjectName ( configFileName ) ;
1836
1841
if ( ! project ) {
@@ -1848,7 +1853,7 @@ namespace ts.server {
1848
1853
updatedProjects . set ( configFileName , true ) ;
1849
1854
}
1850
1855
}
1851
- }
1856
+ } ) ;
1852
1857
}
1853
1858
1854
1859
/**
@@ -1893,16 +1898,17 @@ namespace ts.server {
1893
1898
this . logger . info ( "refreshInferredProjects: updating project structure from ..." ) ;
1894
1899
this . printProjects ( ) ;
1895
1900
1896
- for ( const info of this . openFiles ) {
1901
+ this . openFiles . forEach ( ( projectRootPath , path ) => {
1902
+ const info = this . getScriptInfoForPath ( path as Path ) ;
1897
1903
// collect all orphaned script infos from open files
1898
1904
if ( info . isOrphan ( ) ) {
1899
- this . assignOrphanScriptInfoToInferredProject ( info ) ;
1905
+ this . assignOrphanScriptInfoToInferredProject ( info , projectRootPath ) ;
1900
1906
}
1901
1907
else {
1902
1908
// Or remove the root of inferred project if is referenced in more than one projects
1903
1909
this . removeRootOfInferredProjectIfNowPartOfOtherProject ( info ) ;
1904
1910
}
1905
- }
1911
+ } ) ;
1906
1912
1907
1913
for ( const p of this . inferredProjects ) {
1908
1914
p . updateGraph ( ) ;
@@ -1956,7 +1962,7 @@ namespace ts.server {
1956
1962
this . assignOrphanScriptInfoToInferredProject ( info , projectRootPath ) ;
1957
1963
}
1958
1964
Debug . assert ( ! info . isOrphan ( ) ) ;
1959
- this . openFiles . push ( info ) ;
1965
+ this . openFiles . set ( info . path , projectRootPath ) ;
1960
1966
1961
1967
if ( sendConfigFileDiagEvent ) {
1962
1968
configFileErrors = project . getAllProjectErrors ( ) ;
0 commit comments