@@ -290,6 +290,11 @@ namespace ts {
290290 return resolutions ;
291291 }
292292
293+ interface DiagnosticCache {
294+ perFile ?: FileMap < Diagnostic [ ] > ;
295+ allDiagnostics ?: Diagnostic [ ] ;
296+ }
297+
293298 export function createProgram ( rootNames : string [ ] , options : CompilerOptions , host ?: CompilerHost , oldProgram ?: Program ) : Program {
294299 let program : Program ;
295300 let files : SourceFile [ ] = [ ] ;
@@ -298,6 +303,9 @@ namespace ts {
298303 let noDiagnosticsTypeChecker : TypeChecker ;
299304 let classifiableNames : Map < string > ;
300305
306+ let cachedSemanticDiagnosticsForFile : DiagnosticCache = { } ;
307+ let cachedDeclarationDiagnosticsForFile : DiagnosticCache = { } ;
308+
301309 let resolvedTypeReferenceDirectives = createMap < ResolvedTypeReferenceDirective > ( ) ;
302310 let fileProcessingDiagnostics = createDiagnosticCollection ( ) ;
303311
@@ -899,6 +907,10 @@ namespace ts {
899907 }
900908
901909 function getSemanticDiagnosticsForFile ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : Diagnostic [ ] {
910+ return getAndCacheDiagnostics ( sourceFile , cancellationToken , cachedSemanticDiagnosticsForFile , getSemanticDiagnosticsForFileNoCache ) ;
911+ }
912+
913+ function getSemanticDiagnosticsForFileNoCache ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : Diagnostic [ ] {
902914 return runWithCancellationToken ( ( ) => {
903915 const typeChecker = getDiagnosticsProducingTypeChecker ( ) ;
904916
@@ -1094,14 +1106,44 @@ namespace ts {
10941106 } ) ;
10951107 }
10961108
1097- function getDeclarationDiagnosticsWorker ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : Diagnostic [ ] {
1109+ function getDeclarationDiagnosticsWorker ( sourceFile : SourceFile | undefined , cancellationToken : CancellationToken ) : Diagnostic [ ] {
1110+ return getAndCacheDiagnostics ( sourceFile , cancellationToken , cachedDeclarationDiagnosticsForFile , getDeclarationDiagnosticsForFileNoCache ) ;
1111+ }
1112+
1113+ function getDeclarationDiagnosticsForFileNoCache ( sourceFile : SourceFile | undefined , cancellationToken : CancellationToken ) {
10981114 return runWithCancellationToken ( ( ) => {
10991115 const resolver = getDiagnosticsProducingTypeChecker ( ) . getEmitResolver ( sourceFile , cancellationToken ) ;
11001116 // Don't actually write any files since we're just getting diagnostics.
11011117 return ts . getDeclarationDiagnostics ( getEmitHost ( noop ) , resolver , sourceFile ) ;
11021118 } ) ;
11031119 }
11041120
1121+ function getAndCacheDiagnostics (
1122+ sourceFile : SourceFile | undefined ,
1123+ cancellationToken : CancellationToken ,
1124+ cache : DiagnosticCache ,
1125+ getDiagnostics : ( sourceFile : SourceFile , cancellationToken : CancellationToken ) => Diagnostic [ ] ) {
1126+
1127+ const cachedResult = sourceFile
1128+ ? cache . perFile && cache . perFile . get ( sourceFile . path )
1129+ : cache . allDiagnostics ;
1130+
1131+ if ( cachedResult ) {
1132+ return cachedResult ;
1133+ }
1134+ const result = getDiagnostics ( sourceFile , cancellationToken ) || emptyArray ;
1135+ if ( sourceFile ) {
1136+ if ( ! cache . perFile ) {
1137+ cache . perFile = createFileMap < Diagnostic [ ] > ( ) ;
1138+ }
1139+ cache . perFile . set ( sourceFile . path , result ) ;
1140+ }
1141+ else {
1142+ cache . allDiagnostics = result ;
1143+ }
1144+ return result ;
1145+ }
1146+
11051147 function getDeclarationDiagnosticsForFile ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : Diagnostic [ ] {
11061148 return isDeclarationFile ( sourceFile ) ? [ ] : getDeclarationDiagnosticsWorker ( sourceFile , cancellationToken ) ;
11071149 }
0 commit comments