@@ -284,6 +284,10 @@ namespace ts.server {
284
284
configFileErrors ?: ReadonlyArray < Diagnostic > ;
285
285
}
286
286
287
+ interface AssignProjectResult extends OpenConfiguredProjectResult {
288
+ defaultConfigProject : ConfiguredProject | undefined ;
289
+ }
290
+
287
291
interface FilePropertyReader < T > {
288
292
getFileName ( f : T ) : string ;
289
293
getScriptKind ( f : T , extraFileExtensions ?: FileExtensionInfo [ ] ) : ScriptKind ;
@@ -2635,10 +2639,11 @@ namespace ts.server {
2635
2639
return info ;
2636
2640
}
2637
2641
2638
- private assignProjectToOpenedScriptInfo ( info : ScriptInfo ) : OpenConfiguredProjectResult {
2642
+ private assignProjectToOpenedScriptInfo ( info : ScriptInfo ) : AssignProjectResult {
2639
2643
let configFileName : NormalizedPath | undefined ;
2640
2644
let configFileErrors : ReadonlyArray < Diagnostic > | undefined ;
2641
2645
let project : ConfiguredProject | ExternalProject | undefined = this . findExternalProjectContainingOpenScriptInfo ( info ) ;
2646
+ let defaultConfigProject : ConfiguredProject | undefined ;
2642
2647
if ( ! project && ! this . syntaxOnly ) { // Checking syntaxOnly is an optimization
2643
2648
configFileName = this . getConfigFileNameForFile ( info ) ;
2644
2649
if ( configFileName ) {
@@ -2659,6 +2664,7 @@ namespace ts.server {
2659
2664
// Ensure project is ready to check if it contains opened script info
2660
2665
updateProjectIfDirty ( project ) ;
2661
2666
}
2667
+ defaultConfigProject = project ;
2662
2668
}
2663
2669
}
2664
2670
@@ -2678,13 +2684,13 @@ namespace ts.server {
2678
2684
this . assignOrphanScriptInfoToInferredProject ( info , this . openFiles . get ( info . path ) ) ;
2679
2685
}
2680
2686
Debug . assert ( ! info . isOrphan ( ) ) ;
2681
- return { configFileName, configFileErrors } ;
2687
+ return { configFileName, configFileErrors, defaultConfigProject } ;
2682
2688
}
2683
2689
2684
- private cleanupAfterOpeningFile ( ) {
2690
+ private cleanupAfterOpeningFile ( toRetainConfigProjects : ConfiguredProject [ ] | ConfiguredProject | undefined ) {
2685
2691
// This was postponed from closeOpenFile to after opening next file,
2686
2692
// so that we can reuse the project if we need to right away
2687
- this . removeOrphanConfiguredProjects ( ) ;
2693
+ this . removeOrphanConfiguredProjects ( toRetainConfigProjects ) ;
2688
2694
2689
2695
// Remove orphan inferred projects now that we have reused projects
2690
2696
// We need to create a duplicate because we cant guarantee order after removal
@@ -2705,22 +2711,30 @@ namespace ts.server {
2705
2711
2706
2712
openClientFileWithNormalizedPath ( fileName : NormalizedPath , fileContent ?: string , scriptKind ?: ScriptKind , hasMixedContent ?: boolean , projectRootPath ?: NormalizedPath ) : OpenConfiguredProjectResult {
2707
2713
const info = this . getOrCreateOpenScriptInfo ( fileName , fileContent , scriptKind , hasMixedContent , projectRootPath ) ;
2708
- const result = this . assignProjectToOpenedScriptInfo ( info ) ;
2709
- this . cleanupAfterOpeningFile ( ) ;
2714
+ const { defaultConfigProject , ... result } = this . assignProjectToOpenedScriptInfo ( info ) ;
2715
+ this . cleanupAfterOpeningFile ( defaultConfigProject ) ;
2710
2716
this . telemetryOnOpenFile ( info ) ;
2711
2717
return result ;
2712
2718
}
2713
2719
2714
- private removeOrphanConfiguredProjects ( ) {
2720
+ private removeOrphanConfiguredProjects ( toRetainConfiguredProjects : ConfiguredProject [ ] | ConfiguredProject | undefined ) {
2715
2721
const toRemoveConfiguredProjects = cloneMap ( this . configuredProjects ) ;
2722
+ if ( toRetainConfiguredProjects ) {
2723
+ if ( isArray ( toRetainConfiguredProjects ) ) {
2724
+ toRetainConfiguredProjects . forEach ( retainConfiguredProject ) ;
2725
+ }
2726
+ else {
2727
+ retainConfiguredProject ( toRetainConfiguredProjects ) ;
2728
+ }
2729
+ }
2716
2730
2717
2731
// Do not remove configured projects that are used as original projects of other
2718
2732
this . inferredProjects . forEach ( markOriginalProjectsAsUsed ) ;
2719
2733
this . externalProjects . forEach ( markOriginalProjectsAsUsed ) ;
2720
2734
this . configuredProjects . forEach ( project => {
2721
2735
// If project has open ref (there are more than zero references from external project/open file), keep it alive as well as any project it references
2722
2736
if ( project . hasOpenRef ( ) ) {
2723
- toRemoveConfiguredProjects . delete ( project . canonicalConfigFilePath ) ;
2737
+ retainConfiguredProject ( project ) ;
2724
2738
markOriginalProjectsAsUsed ( project ) ;
2725
2739
}
2726
2740
else {
@@ -2729,7 +2743,7 @@ namespace ts.server {
2729
2743
if ( ref ) {
2730
2744
const refProject = this . configuredProjects . get ( ref . sourceFile . path ) ;
2731
2745
if ( refProject && refProject . hasOpenRef ( ) ) {
2732
- toRemoveConfiguredProjects . delete ( project . canonicalConfigFilePath ) ;
2746
+ retainConfiguredProject ( project ) ;
2733
2747
}
2734
2748
}
2735
2749
} ) ;
@@ -2744,6 +2758,10 @@ namespace ts.server {
2744
2758
project . originalConfiguredProjects . forEach ( ( _value , configuredProjectPath ) => toRemoveConfiguredProjects . delete ( configuredProjectPath ) ) ;
2745
2759
}
2746
2760
}
2761
+
2762
+ function retainConfiguredProject ( project : ConfiguredProject ) {
2763
+ toRemoveConfiguredProjects . delete ( project . canonicalConfigFilePath ) ;
2764
+ }
2747
2765
}
2748
2766
2749
2767
private removeOrphanScriptInfos ( ) {
@@ -2886,8 +2904,9 @@ namespace ts.server {
2886
2904
}
2887
2905
2888
2906
// All the script infos now exist, so ok to go update projects for open files
2907
+ let defaultConfigProjects : ConfiguredProject [ ] | undefined ;
2889
2908
if ( openScriptInfos ) {
2890
- openScriptInfos . forEach ( info => this . assignProjectToOpenedScriptInfo ( info ) ) ;
2909
+ defaultConfigProjects = mapDefined ( openScriptInfos , info => this . assignProjectToOpenedScriptInfo ( info ) . defaultConfigProject ) ;
2891
2910
}
2892
2911
2893
2912
// While closing files there could be open files that needed assigning new inferred projects, do it now
@@ -2896,7 +2915,7 @@ namespace ts.server {
2896
2915
}
2897
2916
2898
2917
// Cleanup projects
2899
- this . cleanupAfterOpeningFile ( ) ;
2918
+ this . cleanupAfterOpeningFile ( defaultConfigProjects ) ;
2900
2919
2901
2920
// Telemetry
2902
2921
forEach ( openScriptInfos , info => this . telemetryOnOpenFile ( info ) ) ;
0 commit comments