@@ -352,9 +352,9 @@ namespace ts.server {
352352 */
353353 readonly configuredProjects = createMap < ConfiguredProject > ( ) ;
354354 /**
355- * list of open files
355+ * Open files: with value being project root path, and key being Path of the file that is open
356356 */
357- readonly openFiles : ScriptInfo [ ] = [ ] ;
357+ readonly openFiles = createMap < NormalizedPath > ( ) ;
358358
359359 private compilerOptionsForInferredProjects : CompilerOptions ;
360360 private compilerOptionsForInferredProjectsPerProjectRoot = createMap < CompilerOptions > ( ) ;
@@ -582,7 +582,7 @@ namespace ts.server {
582582 const event : ProjectsUpdatedInBackgroundEvent = {
583583 eventName : ProjectsUpdatedInBackgroundEvent ,
584584 data : {
585- openFiles : this . openFiles . map ( f => f . fileName )
585+ openFiles : arrayFrom ( this . openFiles . keys ( ) , path => this . getScriptInfoForPath ( path as Path ) . fileName )
586586 }
587587 } ;
588588 this . eventHandler ( event ) ;
@@ -891,7 +891,7 @@ namespace ts.server {
891891 }
892892
893893 /*@internal */
894- assignOrphanScriptInfoToInferredProject ( info : ScriptInfo , projectRootPath ?: string ) {
894+ assignOrphanScriptInfoToInferredProject ( info : ScriptInfo , projectRootPath : NormalizedPath | undefined ) {
895895 Debug . assert ( info . isOrphan ( ) ) ;
896896
897897 const project = this . getOrCreateInferredProjectForProjectRootPathIfEnabled ( info , projectRootPath ) ||
@@ -935,7 +935,7 @@ namespace ts.server {
935935 info . close ( ) ;
936936 this . stopWatchingConfigFilesForClosedScriptInfo ( info ) ;
937937
938- unorderedRemoveItem ( this . openFiles , info ) ;
938+ this . openFiles . delete ( info . path ) ;
939939
940940 const fileExists = this . host . fileExists ( info . fileName ) ;
941941
@@ -974,11 +974,12 @@ namespace ts.server {
974974 }
975975
976976 // 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 ) ;
978979 if ( f . isOrphan ( ) ) {
979- this . assignOrphanScriptInfoToInferredProject ( f ) ;
980+ this . assignOrphanScriptInfoToInferredProject ( f , projectRootPath ) ;
980981 }
981- }
982+ } ) ;
982983
983984 // Cleanup script infos that arent part of any project (eg. those could be closed script infos not referenced by any project)
984985 // is postponed to next file open so that if file from same project is opened,
@@ -1172,7 +1173,7 @@ namespace ts.server {
11721173 * This is called by inferred project whenever script info is added as a root
11731174 */
11741175 /* @internal */
1175- startWatchingConfigFilesForInferredProjectRoot ( info : ScriptInfo ) {
1176+ startWatchingConfigFilesForInferredProjectRoot ( info : ScriptInfo , projectRootPath : NormalizedPath | undefined ) {
11761177 Debug . assert ( info . isScriptOpen ( ) ) ;
11771178 this . forEachConfigFileLocation ( info , ( configFileName , canonicalConfigFilePath ) => {
11781179 let configFileExistenceInfo = this . configFileExistenceInfoCache . get ( canonicalConfigFilePath ) ;
@@ -1194,7 +1195,7 @@ namespace ts.server {
11941195 ! this . getConfiguredProjectByCanonicalConfigFilePath ( canonicalConfigFilePath ) ) {
11951196 this . createConfigFileWatcherOfConfigFileExistence ( configFileName , canonicalConfigFilePath , configFileExistenceInfo ) ;
11961197 }
1197- } ) ;
1198+ } , projectRootPath ) ;
11981199 }
11991200
12001201 /**
@@ -1262,7 +1263,7 @@ namespace ts.server {
12621263 * The server must start searching from the directory containing
12631264 * the newly opened file.
12641265 */
1265- private getConfigFileNameForFile ( info : ScriptInfo , projectRootPath ? : NormalizedPath ) {
1266+ private getConfigFileNameForFile ( info : ScriptInfo , projectRootPath : NormalizedPath | undefined ) {
12661267 Debug . assert ( info . isScriptOpen ( ) ) ;
12671268 this . logger . info ( `Search path: ${ getDirectoryPath ( info . fileName ) } ` ) ;
12681269 const configFileName = this . forEachConfigFileLocation ( info ,
@@ -1301,9 +1302,9 @@ namespace ts.server {
13011302 printProjects ( this . inferredProjects , counter ) ;
13021303
13031304 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+ } ) ;
13071308
13081309 this . logger . endGroup ( ) ;
13091310 }
@@ -1605,7 +1606,7 @@ namespace ts.server {
16051606 } ) ;
16061607 }
16071608
1608- private getOrCreateInferredProjectForProjectRootPathIfEnabled ( info : ScriptInfo , projectRootPath : string | undefined ) : InferredProject | undefined {
1609+ private getOrCreateInferredProjectForProjectRootPathIfEnabled ( info : ScriptInfo , projectRootPath : NormalizedPath | undefined ) : InferredProject | undefined {
16091610 if ( ! this . useInferredProjectPerProjectRoot ) {
16101611 return undefined ;
16111612 }
@@ -1659,7 +1660,7 @@ namespace ts.server {
16591660 return this . createInferredProject ( /*currentDirectory*/ undefined , /*isSingleInferredProject*/ true ) ;
16601661 }
16611662
1662- private createInferredProject ( currentDirectory : string | undefined , isSingleInferredProject ?: boolean , projectRootPath ?: string ) : InferredProject {
1663+ private createInferredProject ( currentDirectory : string | undefined , isSingleInferredProject ?: boolean , projectRootPath ?: NormalizedPath ) : InferredProject {
16631664 const compilerOptions = projectRootPath && this . compilerOptionsForInferredProjectsPerProjectRoot . get ( projectRootPath ) || this . compilerOptionsForInferredProjects ;
16641665 const project = new InferredProject ( this , this . documentRegistry , compilerOptions , projectRootPath , currentDirectory ) ;
16651666 if ( isSingleInferredProject ) {
@@ -1796,23 +1797,19 @@ namespace ts.server {
17961797 // as there is no need to load contents of the files from the disk
17971798
17981799 // Reload Projects
1799- this . reloadConfiguredProjectForFiles ( this . openFiles , /*delayReload*/ false ) ;
1800+ this . reloadConfiguredProjectForFiles ( this . openFiles , /*delayReload*/ false , returnTrue ) ;
18001801 this . refreshInferredProjects ( ) ;
18011802 }
18021803
18031804 private delayReloadConfiguredProjectForFiles ( configFileExistenceInfo : ConfigFileExistenceInfo , ignoreIfNotRootOfInferredProject : boolean ) {
18041805 // 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
18141812 ) ;
1815- this . reloadConfiguredProjectForFiles ( openFiles , /*delayReload*/ true ) ;
18161813 this . delayInferredProjectsRefresh ( ) ;
18171814 }
18181815
@@ -1821,16 +1818,24 @@ namespace ts.server {
18211818 * If the config file is found and it refers to existing project, it reloads it either immediately
18221819 * or schedules it for reload depending on delayReload option
18231820 * 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
18241822 */
1825- private reloadConfiguredProjectForFiles ( openFiles : ReadonlyArray < ScriptInfo > , delayReload : boolean ) {
1823+ private reloadConfiguredProjectForFiles < T > ( openFiles : Map < T > , delayReload : boolean , shouldReloadProjectFor : ( openFileValue : T ) => boolean ) {
18261824 const updatedProjects = createMap < true > ( ) ;
18271825 // 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 ( ) ) ;
18291834 // This tries to search for a tsconfig.json for the given file. If we found it,
18301835 // we first detect if there is already a configured project created for it: if so,
18311836 // we re- read the tsconfig file content and update the project only if we havent already done so
18321837 // otherwise we create a new one.
1833- const configFileName = this . getConfigFileNameForFile ( info ) ;
1838+ const configFileName = this . getConfigFileNameForFile ( info , this . openFiles . get ( path ) ) ;
18341839 if ( configFileName ) {
18351840 const project = this . findConfiguredProjectByProjectName ( configFileName ) ;
18361841 if ( ! project ) {
@@ -1848,7 +1853,7 @@ namespace ts.server {
18481853 updatedProjects . set ( configFileName , true ) ;
18491854 }
18501855 }
1851- }
1856+ } ) ;
18521857 }
18531858
18541859 /**
@@ -1893,16 +1898,17 @@ namespace ts.server {
18931898 this . logger . info ( "refreshInferredProjects: updating project structure from ..." ) ;
18941899 this . printProjects ( ) ;
18951900
1896- for ( const info of this . openFiles ) {
1901+ this . openFiles . forEach ( ( projectRootPath , path ) => {
1902+ const info = this . getScriptInfoForPath ( path as Path ) ;
18971903 // collect all orphaned script infos from open files
18981904 if ( info . isOrphan ( ) ) {
1899- this . assignOrphanScriptInfoToInferredProject ( info ) ;
1905+ this . assignOrphanScriptInfoToInferredProject ( info , projectRootPath ) ;
19001906 }
19011907 else {
19021908 // Or remove the root of inferred project if is referenced in more than one projects
19031909 this . removeRootOfInferredProjectIfNowPartOfOtherProject ( info ) ;
19041910 }
1905- }
1911+ } ) ;
19061912
19071913 for ( const p of this . inferredProjects ) {
19081914 p . updateGraph ( ) ;
@@ -1956,7 +1962,7 @@ namespace ts.server {
19561962 this . assignOrphanScriptInfoToInferredProject ( info , projectRootPath ) ;
19571963 }
19581964 Debug . assert ( ! info . isOrphan ( ) ) ;
1959- this . openFiles . push ( info ) ;
1965+ this . openFiles . set ( info . path , projectRootPath ) ;
19601966
19611967 if ( sendConfigFileDiagEvent ) {
19621968 configFileErrors = project . getAllProjectErrors ( ) ;
0 commit comments