@@ -407,8 +407,8 @@ namespace ts.server {
407
407
}
408
408
409
409
function setProjectOptionsUsed ( project : ConfiguredProject | ExternalProject ) {
410
- if ( project . projectKind === ProjectKind . Configured ) {
411
- ( project as ConfiguredProject ) . projectOptions = true ;
410
+ if ( isConfiguredProject ( project ) ) {
411
+ project . projectOptions = true ;
412
412
}
413
413
}
414
414
@@ -1009,6 +1009,9 @@ namespace ts.server {
1009
1009
1010
1010
// don't trigger callback on open, existing files
1011
1011
if ( project . fileIsOpen ( fileOrDirectoryPath ) ) {
1012
+ if ( project . pendingReload !== ConfigFileProgramReloadLevel . Full ) {
1013
+ project . openFileWatchTriggered . set ( fileOrDirectoryPath , true ) ;
1014
+ }
1012
1015
return ;
1013
1016
}
1014
1017
@@ -1208,16 +1211,26 @@ namespace ts.server {
1208
1211
// collect all projects that should be removed
1209
1212
let ensureProjectsForOpenFiles = false ;
1210
1213
for ( const p of info . containingProjects ) {
1211
- if ( p . projectKind === ProjectKind . Configured ) {
1214
+ if ( isConfiguredProject ( p ) ) {
1212
1215
if ( info . hasMixedContent ) {
1213
1216
info . registerFileUpdate ( ) ;
1214
1217
}
1215
1218
// Do not remove the project so that we can reuse this project
1216
1219
// if it would need to be re-created with next file open
1220
+
1221
+ // If project had open file affecting
1222
+ // Reload the root Files from config if its not already scheduled
1223
+ if ( p . openFileWatchTriggered . has ( info . path ) ) {
1224
+ p . openFileWatchTriggered . delete ( info . path ) ;
1225
+ if ( ! p . pendingReload ) {
1226
+ p . pendingReload = ConfigFileProgramReloadLevel . Partial ;
1227
+ p . markFileAsDirty ( info . path ) ;
1228
+ }
1229
+ }
1217
1230
}
1218
- else if ( p . projectKind === ProjectKind . Inferred && p . isRoot ( info ) ) {
1231
+ else if ( isInferredProject ( p ) && p . isRoot ( info ) ) {
1219
1232
// If this was the last open root file of inferred project
1220
- if ( ( p as InferredProject ) . isProjectWithSingleRoot ( ) ) {
1233
+ if ( p . isProjectWithSingleRoot ( ) ) {
1221
1234
ensureProjectsForOpenFiles = true ;
1222
1235
}
1223
1236
@@ -1679,7 +1692,7 @@ namespace ts.server {
1679
1692
return ;
1680
1693
}
1681
1694
1682
- const projectOptions = project . projectKind === ProjectKind . Configured ? ( project as ConfiguredProject ) . projectOptions as ProjectOptions : undefined ;
1695
+ const projectOptions = isConfiguredProject ( project ) ? project . projectOptions as ProjectOptions : undefined ;
1683
1696
setProjectOptionsUsed ( project ) ;
1684
1697
const data : ProjectInfoTelemetryEventData = {
1685
1698
projectId : this . host . createSHA256Hash ( project . projectName ) ,
@@ -1699,7 +1712,7 @@ namespace ts.server {
1699
1712
this . eventHandler ( { eventName : ProjectInfoTelemetryEvent , data } ) ;
1700
1713
1701
1714
function configFileName ( ) : ProjectInfoTelemetryEventData [ "configFileName" ] {
1702
- if ( ! ( project instanceof ConfiguredProject ) ) {
1715
+ if ( ! isConfiguredProject ( project ) ) {
1703
1716
return "other" ;
1704
1717
}
1705
1718
@@ -1832,49 +1845,64 @@ namespace ts.server {
1832
1845
1833
1846
private updateNonInferredProjectFiles < T > ( project : ExternalProject | ConfiguredProject , files : T [ ] , propertyReader : FilePropertyReader < T > ) {
1834
1847
const projectRootFilesMap = project . getRootFilesMap ( ) ;
1835
- const newRootScriptInfoMap = createMap < ProjectRoot > ( ) ;
1848
+ const newRootScriptInfoMap = createMap < true > ( ) ;
1836
1849
1837
1850
for ( const f of files ) {
1838
1851
const newRootFile = propertyReader . getFileName ( f ) ;
1839
- const normalizedPath = toNormalizedPath ( newRootFile ) ;
1840
- const isDynamic = isDynamicFileName ( normalizedPath ) ;
1841
- let scriptInfo : ScriptInfo | NormalizedPath ;
1852
+ const fileName = toNormalizedPath ( newRootFile ) ;
1853
+ const isDynamic = isDynamicFileName ( fileName ) ;
1842
1854
let path : Path ;
1843
1855
// Use the project's fileExists so that it can use caching instead of reaching to disk for the query
1844
1856
if ( ! isDynamic && ! project . fileExistsWithCache ( newRootFile ) ) {
1845
- path = normalizedPathToPath ( normalizedPath , this . currentDirectory , this . toCanonicalFileName ) ;
1846
- const existingValue = projectRootFilesMap . get ( path ) ! ;
1847
- if ( isScriptInfo ( existingValue ) ) {
1848
- project . removeFile ( existingValue , /*fileExists*/ false , /*detachFromProject*/ true ) ;
1857
+ path = normalizedPathToPath ( fileName , this . currentDirectory , this . toCanonicalFileName ) ;
1858
+ const existingValue = projectRootFilesMap . get ( path ) ;
1859
+ if ( existingValue ) {
1860
+ if ( existingValue . info ) {
1861
+ project . removeFile ( existingValue . info , /*fileExists*/ false , /*detachFromProject*/ true ) ;
1862
+ existingValue . info = undefined ;
1863
+ }
1864
+ existingValue . fileName = fileName ;
1865
+ }
1866
+ else {
1867
+ projectRootFilesMap . set ( path , { fileName } ) ;
1849
1868
}
1850
- projectRootFilesMap . set ( path , normalizedPath ) ;
1851
- scriptInfo = normalizedPath ;
1852
1869
}
1853
1870
else {
1854
1871
const scriptKind = propertyReader . getScriptKind ( f , this . hostConfiguration . extraFileExtensions ) ;
1855
1872
const hasMixedContent = propertyReader . hasMixedContent ( f , this . hostConfiguration . extraFileExtensions ) ;
1856
- scriptInfo = this . getOrCreateScriptInfoNotOpenedByClientForNormalizedPath ( normalizedPath , project . currentDirectory , scriptKind , hasMixedContent , project . directoryStructureHost ) ! ; // TODO: GH#18217
1873
+ const scriptInfo = Debug . assertDefined ( this . getOrCreateScriptInfoNotOpenedByClientForNormalizedPath (
1874
+ fileName ,
1875
+ project . currentDirectory ,
1876
+ scriptKind ,
1877
+ hasMixedContent ,
1878
+ project . directoryStructureHost
1879
+ ) ) ;
1857
1880
path = scriptInfo . path ;
1881
+ const existingValue = projectRootFilesMap . get ( path ) ;
1858
1882
// If this script info is not already a root add it
1859
- if ( ! project . isRoot ( scriptInfo ) ) {
1860
- project . addRoot ( scriptInfo ) ;
1883
+ if ( ! existingValue || existingValue . info !== scriptInfo ) {
1884
+ project . addRoot ( scriptInfo , fileName ) ;
1861
1885
if ( scriptInfo . isScriptOpen ( ) ) {
1862
1886
// if file is already root in some inferred project
1863
1887
// - remove the file from that project and delete the project if necessary
1864
1888
this . removeRootOfInferredProjectIfNowPartOfOtherProject ( scriptInfo ) ;
1865
1889
}
1866
1890
}
1891
+ else {
1892
+ // Already root update the fileName
1893
+ existingValue . fileName = fileName ;
1894
+ }
1867
1895
}
1868
- newRootScriptInfoMap . set ( path , scriptInfo ) ;
1896
+ newRootScriptInfoMap . set ( path , true ) ;
1869
1897
}
1870
1898
1871
1899
// project's root file map size is always going to be same or larger than new roots map
1872
1900
// as we have already all the new files to the project
1873
1901
if ( projectRootFilesMap . size > newRootScriptInfoMap . size ) {
1874
1902
projectRootFilesMap . forEach ( ( value , path ) => {
1875
1903
if ( ! newRootScriptInfoMap . has ( path ) ) {
1876
- if ( isScriptInfo ( value ) ) {
1877
- project . removeFile ( value , project . fileExistsWithCache ( path ) , /*detachFromProject*/ true ) ;
1904
+ if ( value . info ) {
1905
+ project . removeFile ( value . info , project . fileExistsWithCache ( path ) , /*detachFromProject*/ true ) ;
1878
1906
}
1879
1907
else {
1880
1908
projectRootFilesMap . delete ( path ) ;
@@ -2562,7 +2590,7 @@ namespace ts.server {
2562
2590
const firstProject = info . containingProjects [ 0 ] ;
2563
2591
2564
2592
if ( ! firstProject . isOrphan ( ) &&
2565
- firstProject . projectKind === ProjectKind . Inferred &&
2593
+ isInferredProject ( firstProject ) &&
2566
2594
firstProject . isRoot ( info ) &&
2567
2595
forEach ( info . containingProjects , p => p !== firstProject && ! p . isOrphan ( ) ) ) {
2568
2596
firstProject . removeFile ( info , /*fileExists*/ true , /*detachFromProject*/ true ) ;
@@ -2633,8 +2661,8 @@ namespace ts.server {
2633
2661
2634
2662
// Add configured projects as referenced
2635
2663
originalScriptInfo . containingProjects . forEach ( project => {
2636
- if ( project . projectKind === ProjectKind . Configured ) {
2637
- addOriginalConfiguredProject ( project as ConfiguredProject ) ;
2664
+ if ( isConfiguredProject ( project ) ) {
2665
+ addOriginalConfiguredProject ( project ) ;
2638
2666
}
2639
2667
} ) ;
2640
2668
return originalLocation ;
0 commit comments