@@ -433,6 +433,7 @@ namespace ts {
433
433
const missingRoots = createMap < true > ( ) ;
434
434
let globalDependencyGraph : DependencyGraph | undefined ;
435
435
const writeFileName = ( s : string ) => host . trace && host . trace ( s ) ;
436
+ let readFileWithCache = ( f : string ) => host . readFile ( f ) ;
436
437
437
438
// Watch state
438
439
const diagnostics = createFileMap < ReadonlyArray < Diagnostic > > ( toPath ) ;
@@ -1072,7 +1073,7 @@ namespace ts {
1072
1073
let priorChangeTime : Date | undefined ;
1073
1074
if ( ! anyDtsChanged && isDeclarationFile ( fileName ) ) {
1074
1075
// Check for unchanged .d.ts files
1075
- if ( host . fileExists ( fileName ) && host . readFile ( fileName ) === content ) {
1076
+ if ( host . fileExists ( fileName ) && readFileWithCache ( fileName ) === content ) {
1076
1077
priorChangeTime = host . getModifiedTime ( fileName ) ;
1077
1078
}
1078
1079
else {
@@ -1182,6 +1183,97 @@ namespace ts {
1182
1183
1183
1184
function buildAllProjects ( ) : ExitStatus {
1184
1185
if ( options . watch ) { reportWatchStatus ( Diagnostics . Starting_compilation_in_watch_mode ) ; }
1186
+ const originalReadFile = host . readFile ;
1187
+ const originalFileExists = host . fileExists ;
1188
+ const originalDirectoryExists = host . directoryExists ;
1189
+ const originalCreateDirectory = host . createDirectory ;
1190
+ const originalWriteFile = host . writeFile ;
1191
+ const originalGetSourceFile = host . getSourceFile ;
1192
+ const readFileCache = createMap < string | false > ( ) ;
1193
+ const fileExistsCache = createMap < boolean > ( ) ;
1194
+ const directoryExistsCache = createMap < boolean > ( ) ;
1195
+ const sourceFileCache = createMap < SourceFile > ( ) ;
1196
+ const savedReadFileWithCache = readFileWithCache ;
1197
+
1198
+ // TODO:: In watch mode as well to use caches for incremental build once we can invalidate caches correctly and have right api
1199
+ // Override readFile for json files and output .d.ts to cache the text
1200
+ readFileWithCache = fileName => {
1201
+ const key = toPath ( fileName ) ;
1202
+ const value = readFileCache . get ( key ) ;
1203
+ if ( value !== undefined ) return value || undefined ;
1204
+ return setReadFileCache ( key , fileName ) ;
1205
+ } ;
1206
+ const setReadFileCache = ( key : Path , fileName : string ) => {
1207
+ const newValue = originalReadFile . call ( host , fileName ) ;
1208
+ readFileCache . set ( key , newValue || false ) ;
1209
+ return newValue ;
1210
+ } ;
1211
+ host . readFile = fileName => {
1212
+ const key = toPath ( fileName ) ;
1213
+ const value = readFileCache . get ( key ) ;
1214
+ if ( value !== undefined ) return value ; // could be .d.ts from output
1215
+ if ( ! fileExtensionIs ( fileName , Extension . Json ) ) {
1216
+ return originalReadFile . call ( host , fileName ) ;
1217
+ }
1218
+
1219
+ return setReadFileCache ( key , fileName ) ;
1220
+ } ;
1221
+ host . getSourceFile = ( fileName , languageVersion , onError , shouldCreateNewSourceFile ) => {
1222
+ const key = toPath ( fileName ) ;
1223
+ const value = sourceFileCache . get ( key ) ;
1224
+ if ( value ) return value ;
1225
+
1226
+ const sourceFile = originalGetSourceFile . call ( host , fileName , languageVersion , onError , shouldCreateNewSourceFile ) ;
1227
+ if ( sourceFile && ( isDeclarationFileName ( fileName ) || fileExtensionIs ( fileName , Extension . Json ) ) ) {
1228
+ sourceFileCache . set ( key , sourceFile ) ;
1229
+ }
1230
+ return sourceFile ;
1231
+ } ;
1232
+
1233
+ // fileExits for any kind of extension
1234
+ host . fileExists = fileName => {
1235
+ const key = toPath ( fileName ) ;
1236
+ const value = fileExistsCache . get ( key ) ;
1237
+ if ( value !== undefined ) return value ;
1238
+ const newValue = originalFileExists . call ( host , fileName ) ;
1239
+ fileExistsCache . set ( key , ! ! newValue ) ;
1240
+ return newValue ;
1241
+ } ;
1242
+ host . writeFile = ( fileName , data , writeByteOrderMark , onError , sourceFiles ) => {
1243
+ const key = toPath ( fileName ) ;
1244
+ fileExistsCache . delete ( key ) ;
1245
+
1246
+ const value = readFileCache . get ( key ) ;
1247
+ if ( value && value !== data ) {
1248
+ readFileCache . delete ( key ) ;
1249
+ sourceFileCache . delete ( key ) ;
1250
+ }
1251
+ else {
1252
+ const sourceFile = sourceFileCache . get ( key ) ;
1253
+ if ( sourceFile && sourceFile . text !== data ) {
1254
+ sourceFileCache . delete ( key ) ;
1255
+ }
1256
+ }
1257
+ originalWriteFile . call ( host , fileName , data , writeByteOrderMark , onError , sourceFiles ) ;
1258
+ } ;
1259
+
1260
+ // directoryExists
1261
+ if ( originalDirectoryExists && originalCreateDirectory ) {
1262
+ host . directoryExists = directory => {
1263
+ const key = toPath ( directory ) ;
1264
+ const value = directoryExistsCache . get ( key ) ;
1265
+ if ( value !== undefined ) return value ;
1266
+ const newValue = originalDirectoryExists . call ( host , directory ) ;
1267
+ directoryExistsCache . set ( key , ! ! newValue ) ;
1268
+ return newValue ;
1269
+ } ;
1270
+ host . createDirectory = directory => {
1271
+ const key = toPath ( directory ) ;
1272
+ directoryExistsCache . delete ( key ) ;
1273
+ originalCreateDirectory . call ( host , directory ) ;
1274
+ } ;
1275
+ }
1276
+
1185
1277
const graph = getGlobalDependencyGraph ( ) ;
1186
1278
reportBuildQueue ( graph ) ;
1187
1279
let anyFailed = false ;
@@ -1232,6 +1324,13 @@ namespace ts {
1232
1324
anyFailed = anyFailed || ! ! ( buildResult & BuildResultFlags . AnyErrors ) ;
1233
1325
}
1234
1326
reportErrorSummary ( ) ;
1327
+ host . readFile = originalReadFile ;
1328
+ host . fileExists = originalFileExists ;
1329
+ host . directoryExists = originalDirectoryExists ;
1330
+ host . createDirectory = originalCreateDirectory ;
1331
+ host . writeFile = originalWriteFile ;
1332
+ readFileWithCache = savedReadFileWithCache ;
1333
+ host . getSourceFile = originalGetSourceFile ;
1235
1334
return anyFailed ? ExitStatus . DiagnosticsPresent_OutputsSkipped : ExitStatus . Success ;
1236
1335
}
1237
1336
0 commit comments