@@ -16,6 +16,7 @@ import {
16
16
SymbolInformation ,
17
17
} from 'vscode-languageserver' ;
18
18
import { CallHierarchyIncomingCall , CallHierarchyItem , CallHierarchyOutgoingCall } from 'vscode-languageserver-types' ;
19
+ import { isMainThread } from 'worker_threads' ;
19
20
20
21
import { OperationCanceledException , throwIfCancellationRequested } from '../common/cancellationUtils' ;
21
22
import { ConfigOptions , ExecutionEnvironment } from '../common/configOptions' ;
@@ -26,6 +27,7 @@ import { Diagnostic } from '../common/diagnostic';
26
27
import { FileDiagnostics } from '../common/diagnosticSink' ;
27
28
import { FileEditAction , TextEditAction } from '../common/editAction' ;
28
29
import { LanguageServiceExtension } from '../common/extensibility' ;
30
+ import { LogTracker } from '../common/logTracker' ;
29
31
import {
30
32
combinePaths ,
31
33
getDirectoryPath ,
@@ -118,6 +120,7 @@ export class Program {
118
120
private _evaluator : TypeEvaluator ;
119
121
private _configOptions : ConfigOptions ;
120
122
private _importResolver : ImportResolver ;
123
+ private _logTracker : LogTracker ;
121
124
122
125
constructor (
123
126
initialImportResolver : ImportResolver ,
@@ -126,6 +129,7 @@ export class Program {
126
129
private _extension ?: LanguageServiceExtension
127
130
) {
128
131
this . _console = console || new StandardConsole ( ) ;
132
+ this . _logTracker = new LogTracker ( console , isMainThread ? 'FG' : 'BG' ) ;
129
133
this . _importResolver = initialImportResolver ;
130
134
this . _configOptions = initialConfigOptions ;
131
135
this . _createNewEvaluator ( ) ;
@@ -189,7 +193,7 @@ export class Program {
189
193
return sourceFileInfo . sourceFile ;
190
194
}
191
195
192
- const sourceFile = new SourceFile ( this . _fs , filePath , false , this . _console ) ;
196
+ const sourceFile = new SourceFile ( this . _fs , filePath , false , this . _console , this . _logTracker ) ;
193
197
sourceFileInfo = {
194
198
sourceFile,
195
199
isTracked : true ,
@@ -209,7 +213,7 @@ export class Program {
209
213
setFileOpened ( filePath : string , version : number | null , contents : string ) {
210
214
let sourceFileInfo = this . _sourceFileMap . get ( filePath ) ;
211
215
if ( ! sourceFileInfo ) {
212
- const sourceFile = new SourceFile ( this . _fs , filePath , false , this . _console ) ;
216
+ const sourceFile = new SourceFile ( this . _fs , filePath , false , this . _console , this . _logTracker ) ;
213
217
sourceFileInfo = {
214
218
sourceFile,
215
219
isTracked : false ,
@@ -524,7 +528,7 @@ export class Program {
524
528
return sourceFileInfo . sourceFile ;
525
529
}
526
530
527
- const sourceFile = new SourceFile ( this . _fs , filePath , false , this . _console ) ;
531
+ const sourceFile = new SourceFile ( this . _fs , filePath , false , this . _console , this . _logTracker ) ;
528
532
sourceFileInfo = {
529
533
sourceFile,
530
534
isTracked : true ,
@@ -549,7 +553,7 @@ export class Program {
549
553
let shadowFileInfo = this . _sourceFileMap . get ( shadowImplPath ) ;
550
554
551
555
if ( ! shadowFileInfo ) {
552
- const sourceFile = new SourceFile ( this . _fs , shadowImplPath , false , this . _console ) ;
556
+ const sourceFile = new SourceFile ( this . _fs , shadowImplPath , false , this . _console , this . _logTracker ) ;
553
557
shadowFileInfo = {
554
558
sourceFile,
555
559
isTracked : false ,
@@ -679,62 +683,67 @@ export class Program {
679
683
}
680
684
681
685
private _checkTypes ( fileToCheck : SourceFileInfo ) {
682
- // If the file isn't needed because it was eliminated from the
683
- // transitive closure or deleted, skip the file rather than wasting
684
- // time on it.
685
- if ( ! this . _isFileNeeded ( fileToCheck ) ) {
686
- return false ;
687
- }
686
+ return this . _logTracker . log ( `analyzing: ${ fileToCheck . sourceFile . getFilePath ( ) } ` , ( ls ) => {
687
+ // If the file isn't needed because it was eliminated from the
688
+ // transitive closure or deleted, skip the file rather than wasting
689
+ // time on it.
690
+ if ( ! this . _isFileNeeded ( fileToCheck ) ) {
691
+ ls . add ( `analysis not needed` ) ;
692
+ return false ;
693
+ }
688
694
689
- if ( ! fileToCheck . sourceFile . isCheckingRequired ( ) ) {
690
- return false ;
691
- }
695
+ if ( ! fileToCheck . sourceFile . isCheckingRequired ( ) ) {
696
+ ls . add ( `cache hit` ) ;
697
+ return false ;
698
+ }
692
699
693
- if ( ! this . _shouldCheckFile ( fileToCheck ) ) {
694
- return false ;
695
- }
700
+ if ( ! this . _shouldCheckFile ( fileToCheck ) ) {
701
+ ls . add ( `analysis not needed` ) ;
702
+ return false ;
703
+ }
696
704
697
- this . _bindFile ( fileToCheck ) ;
705
+ this . _bindFile ( fileToCheck ) ;
698
706
699
- // For very large programs, we may need to discard the evaluator and
700
- // its cached types to avoid running out of heap space.
701
- const typeCacheSize = this . _evaluator . getTypeCacheSize ( ) ;
707
+ // For very large programs, we may need to discard the evaluator and
708
+ // its cached types to avoid running out of heap space.
709
+ const typeCacheSize = this . _evaluator . getTypeCacheSize ( ) ;
702
710
703
- // If the type cache size has exceeded a high-water mark, query the heap usage.
704
- // Don't bother doing this until we hit this point because the heap usage may not
705
- // drop immediately after we empty the cache due to garbage collection timing.
706
- if ( typeCacheSize > 750000 ) {
707
- const heapSizeInMb = Math . round ( process . memoryUsage ( ) . heapUsed / ( 1024 * 1024 ) ) ;
711
+ // If the type cache size has exceeded a high-water mark, query the heap usage.
712
+ // Don't bother doing this until we hit this point because the heap usage may not
713
+ // drop immediately after we empty the cache due to garbage collection timing.
714
+ if ( typeCacheSize > 750000 ) {
715
+ const heapSizeInMb = Math . round ( process . memoryUsage ( ) . heapUsed / ( 1024 * 1024 ) ) ;
708
716
709
- // Don't allow the heap to get close to the 2GB limit imposed by
710
- // the OS when running Node in a 32-bit process.
711
- if ( heapSizeInMb > 1536 ) {
712
- this . _console . info ( `Emptying type cache to avoid heap overflow. Heap size used: ${ heapSizeInMb } MB` ) ;
713
- this . _createNewEvaluator ( ) ;
717
+ // Don't allow the heap to get close to the 2GB limit imposed by
718
+ // the OS when running Node in a 32-bit process.
719
+ if ( heapSizeInMb > 1536 ) {
720
+ this . _console . info ( `Emptying type cache to avoid heap overflow. Heap size used: ${ heapSizeInMb } MB` ) ;
721
+ this . _createNewEvaluator ( ) ;
722
+ }
714
723
}
715
- }
716
724
717
- fileToCheck . sourceFile . check ( this . _evaluator ) ;
718
-
719
- // Detect import cycles that involve the file.
720
- if ( this . _configOptions . diagnosticRuleSet . reportImportCycles !== 'none' ) {
721
- // Don't detect import cycles when doing type stub generation. Some
722
- // third-party modules are pretty convoluted.
723
- if ( ! this . _allowedThirdPartyImports ) {
724
- // We need to force all of the files to be parsed and build
725
- // a closure map for the files.
726
- const closureMap = new Map < string , SourceFileInfo > ( ) ;
727
- this . _getImportsRecursive ( fileToCheck , closureMap , 0 ) ;
728
-
729
- closureMap . forEach ( ( file ) => {
730
- timingStats . cycleDetectionTime . timeOperation ( ( ) => {
731
- this . _detectAndReportImportCycles ( file ) ;
725
+ fileToCheck . sourceFile . check ( this . _evaluator ) ;
726
+
727
+ // Detect import cycles that involve the file.
728
+ if ( this . _configOptions . diagnosticRuleSet . reportImportCycles !== 'none' ) {
729
+ // Don't detect import cycles when doing type stub generation. Some
730
+ // third-party modules are pretty convoluted.
731
+ if ( ! this . _allowedThirdPartyImports ) {
732
+ // We need to force all of the files to be parsed and build
733
+ // a closure map for the files.
734
+ const closureMap = new Map < string , SourceFileInfo > ( ) ;
735
+ this . _getImportsRecursive ( fileToCheck , closureMap , 0 ) ;
736
+
737
+ closureMap . forEach ( ( file ) => {
738
+ timingStats . cycleDetectionTime . timeOperation ( ( ) => {
739
+ this . _detectAndReportImportCycles ( file ) ;
740
+ } ) ;
732
741
} ) ;
733
- } ) ;
742
+ }
734
743
}
735
- }
736
744
737
- return true ;
745
+ return true ;
746
+ } ) ;
738
747
}
739
748
740
749
// Builds a map of files that includes the specified file and all of the files
@@ -1686,7 +1695,8 @@ export class Program {
1686
1695
this . _fs ,
1687
1696
importPath ,
1688
1697
importInfo . isThirdPartyImport ,
1689
- this . _console
1698
+ this . _console ,
1699
+ this . _logTracker
1690
1700
) ;
1691
1701
importedFileInfo = {
1692
1702
sourceFile,
0 commit comments