@@ -89,7 +89,18 @@ namespace ts.server {
89
89
private plugins : PluginModule [ ] = [ ] ;
90
90
91
91
/*@internal */
92
+ /**
93
+ * This is map from files to unresolved imports in it
94
+ * Maop does not contain entries for files that do not have unresolved imports
95
+ * This helps in containing the set of files to invalidate
96
+ */
92
97
cachedUnresolvedImportsPerFile = createMap < ReadonlyArray < string > > ( ) ;
98
+
99
+ /**
100
+ * This is the set that has entry to true if file doesnt contain any unresolved import
101
+ */
102
+ private filesWithNoUnresolvedImports = createMap < true > ( ) ;
103
+
93
104
/*@internal */
94
105
lastCachedUnresolvedImportsList : SortedReadonlyArray < string > ;
95
106
/*@internal */
@@ -143,7 +154,8 @@ namespace ts.server {
143
154
/*@internal */
144
155
hasChangedAutomaticTypeDirectiveNames = false ;
145
156
146
- private typingFiles : SortedReadonlyArray < string > ;
157
+ /*@internal */
158
+ typingFiles : SortedReadonlyArray < string > = emptyArray ;
147
159
148
160
private readonly cancellationToken : ThrottledCancellationToken ;
149
161
@@ -554,6 +566,7 @@ namespace ts.server {
554
566
this . resolutionCache . clear ( ) ;
555
567
this . resolutionCache = undefined ;
556
568
this . cachedUnresolvedImportsPerFile = undefined ;
569
+ this . filesWithNoUnresolvedImports = undefined ;
557
570
this . directoryStructureHost = undefined ;
558
571
559
572
// Clean up file watchers waiting for missing files
@@ -714,6 +727,7 @@ namespace ts.server {
714
727
else {
715
728
this . resolutionCache . invalidateResolutionOfFile ( info . path ) ;
716
729
}
730
+ this . filesWithNoUnresolvedImports . delete ( info . path ) ;
717
731
this . cachedUnresolvedImportsPerFile . delete ( info . path ) ;
718
732
719
733
if ( detachFromProject ) {
@@ -735,16 +749,21 @@ namespace ts.server {
735
749
}
736
750
737
751
/* @internal */
738
- private extractUnresolvedImportsFromSourceFile ( file : SourceFile , result : Push < string > , ambientModules : string [ ] ) {
752
+ private extractUnresolvedImportsFromSourceFile ( file : SourceFile , result : string [ ] | undefined , ambientModules : string [ ] ) : string [ ] | undefined {
753
+ // No unresolve imports in this file
754
+ if ( this . filesWithNoUnresolvedImports . has ( file . path ) ) {
755
+ return result ;
756
+ }
757
+
739
758
const cached = this . cachedUnresolvedImportsPerFile . get ( file . path ) ;
740
759
if ( cached ) {
741
760
// found cached result - use it and return
742
761
for ( const f of cached ) {
743
- result . push ( f ) ;
762
+ ( result || ( result = [ ] ) ) . push ( f ) ;
744
763
}
745
- return ;
764
+ return result ;
746
765
}
747
- let unresolvedImports : string [ ] ;
766
+ let unresolvedImports : string [ ] | undefined ;
748
767
if ( file . resolvedModules ) {
749
768
file . resolvedModules . forEach ( ( resolvedModule , name ) => {
750
769
// pick unresolved non-relative names
@@ -760,11 +779,17 @@ namespace ts.server {
760
779
trimmed = trimmed . substr ( 0 , i ) ;
761
780
}
762
781
( unresolvedImports || ( unresolvedImports = [ ] ) ) . push ( trimmed ) ;
763
- result . push ( trimmed ) ;
782
+ ( result || ( result = [ ] ) ) . push ( trimmed ) ;
764
783
}
765
784
} ) ;
766
785
}
767
- this . cachedUnresolvedImportsPerFile . set ( file . path , unresolvedImports || emptyArray ) ;
786
+ if ( unresolvedImports ) {
787
+ this . cachedUnresolvedImportsPerFile . set ( file . path , unresolvedImports ) ;
788
+ }
789
+ else {
790
+ this . filesWithNoUnresolvedImports . set ( file . path , true ) ;
791
+ }
792
+ return result ;
768
793
769
794
function isAmbientlyDeclaredModule ( name : string ) {
770
795
return ambientModules . some ( m => m === name ) ;
@@ -778,7 +803,7 @@ namespace ts.server {
778
803
updateGraph ( ) : boolean {
779
804
this . resolutionCache . startRecordingFilesWithChangedResolutions ( ) ;
780
805
781
- let hasChanges = this . updateGraphWorker ( ) ;
806
+ const hasChanges = this . updateGraphWorker ( ) ;
782
807
const hasMoreOrLessScriptInfos = this . hasMoreOrLessScriptInfos ;
783
808
this . hasMoreOrLessScriptInfos = false ;
784
809
@@ -787,6 +812,7 @@ namespace ts.server {
787
812
for ( const file of changedFiles ) {
788
813
// delete cached information for changed files
789
814
this . cachedUnresolvedImportsPerFile . delete ( file ) ;
815
+ this . filesWithNoUnresolvedImports . delete ( file ) ;
790
816
}
791
817
792
818
// update builder only if language service is enabled
@@ -799,20 +825,15 @@ namespace ts.server {
799
825
// (can reuse cached imports for files that were not changed)
800
826
// 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch
801
827
if ( hasChanges || changedFiles . length ) {
802
- const result : string [ ] = [ ] ;
828
+ let result : string [ ] | undefined ;
803
829
const ambientModules = this . program . getTypeChecker ( ) . getAmbientModules ( ) . map ( mod => stripQuotes ( mod . getName ( ) ) ) ;
804
830
for ( const sourceFile of this . program . getSourceFiles ( ) ) {
805
- this . extractUnresolvedImportsFromSourceFile ( sourceFile , result , ambientModules ) ;
831
+ result = this . extractUnresolvedImportsFromSourceFile ( sourceFile , result , ambientModules ) ;
806
832
}
807
- this . lastCachedUnresolvedImportsList = toDeduplicatedSortedArray ( result ) ;
833
+ this . lastCachedUnresolvedImportsList = result ? toDeduplicatedSortedArray ( result ) : emptyArray ;
808
834
}
809
835
810
- const cachedTypings = this . projectService . typingsCache . getTypingsForProject ( this , this . lastCachedUnresolvedImportsList , hasMoreOrLessScriptInfos ) ;
811
- if ( ! arrayIsEqualTo ( this . typingFiles , cachedTypings ) ) {
812
- this . typingFiles = cachedTypings ;
813
- this . markAsDirty ( ) ;
814
- hasChanges = this . updateGraphWorker ( ) || hasChanges ;
815
- }
836
+ this . projectService . typingsCache . enqueueInstallTypingsForProject ( this , this . lastCachedUnresolvedImportsList , hasMoreOrLessScriptInfos ) ;
816
837
}
817
838
else {
818
839
this . lastCachedUnresolvedImportsList = undefined ;
@@ -824,6 +845,13 @@ namespace ts.server {
824
845
return ! hasChanges ;
825
846
}
826
847
848
+ /*@internal */
849
+ updateTypingFiles ( typingFiles : SortedReadonlyArray < string > ) {
850
+ this . typingFiles = typingFiles ;
851
+ // Invalidate files with unresolved imports
852
+ this . resolutionCache . setFilesWithInvalidatedNonRelativeUnresolvedImports ( this . cachedUnresolvedImportsPerFile ) ;
853
+ }
854
+
827
855
/* @internal */
828
856
getCurrentProgram ( ) {
829
857
return this . program ;
@@ -959,15 +987,14 @@ namespace ts.server {
959
987
setCompilerOptions ( compilerOptions : CompilerOptions ) {
960
988
if ( compilerOptions ) {
961
989
compilerOptions . allowNonTsExtensions = true ;
962
- if ( changesAffectModuleResolution ( this . compilerOptions , compilerOptions ) ) {
963
- // reset cached unresolved imports if changes in compiler options affected module resolution
964
- this . cachedUnresolvedImportsPerFile . clear ( ) ;
965
- this . lastCachedUnresolvedImportsList = undefined ;
966
- }
967
990
const oldOptions = this . compilerOptions ;
968
991
this . compilerOptions = compilerOptions ;
969
992
this . setInternalCompilerOptionsForEmittingJsFiles ( ) ;
970
993
if ( changesAffectModuleResolution ( oldOptions , compilerOptions ) ) {
994
+ // reset cached unresolved imports if changes in compiler options affected module resolution
995
+ this . cachedUnresolvedImportsPerFile . clear ( ) ;
996
+ this . filesWithNoUnresolvedImports . clear ( ) ;
997
+ this . lastCachedUnresolvedImportsList = undefined ;
971
998
this . resolutionCache . clear ( ) ;
972
999
}
973
1000
this . markAsDirty ( ) ;
0 commit comments