@@ -48,6 +48,11 @@ namespace ts {
48
48
*/
49
49
readonly exportedModulesMap : BuilderState . ManyToManyPathMap | undefined ;
50
50
51
+ previousCache ?: {
52
+ id : number ,
53
+ version : number ,
54
+ } ;
55
+
51
56
/**
52
57
* true if file version is used as signature
53
58
* This helps in delaying the calculation of the d.ts hash as version for the file till reasonable time
@@ -80,6 +85,7 @@ namespace ts {
80
85
}
81
86
82
87
export interface ReadonlyManyToManyPathMap {
88
+ readonly id : number ;
83
89
clone ( ) : ManyToManyPathMap ;
84
90
forEach ( action : ( v : ReadonlySet < Path > , k : Path ) => void ) : void ;
85
91
getKeys ( v : Path ) : ReadonlySet < Path > | undefined ;
@@ -96,13 +102,18 @@ namespace ts {
96
102
}
97
103
98
104
export interface ManyToManyPathMap extends ReadonlyManyToManyPathMap {
105
+ version ( ) : number ; // Incremented each time the contents are changed
99
106
deleteKey ( k : Path ) : boolean ;
100
107
set ( k : Path , v : ReadonlySet < Path > ) : void ;
101
108
}
102
109
110
+ let manyToManyPathMapCount = 0 ;
103
111
export function createManyToManyPathMap ( ) : ManyToManyPathMap {
104
112
function create ( forward : ESMap < Path , ReadonlySet < Path > > , reverse : ESMap < Path , Set < Path > > , deleted : Set < Path > | undefined ) : ManyToManyPathMap {
113
+ let version = 0 ;
105
114
const map : ManyToManyPathMap = {
115
+ id : manyToManyPathMapCount ++ ,
116
+ version : ( ) => version ,
106
117
clone : ( ) => create ( new Map ( forward ) , new Map ( reverse ) , deleted && new Set ( deleted ) ) ,
107
118
forEach : fn => forward . forEach ( fn ) ,
108
119
getKeys : v => reverse . get ( v ) ,
@@ -121,26 +132,33 @@ namespace ts {
121
132
122
133
set . forEach ( v => deleteFromMultimap ( reverse , v , k ) ) ;
123
134
forward . delete ( k ) ;
135
+ version ++ ;
124
136
return true ;
125
137
} ,
126
138
set : ( k , vSet ) => {
127
- deleted ?. delete ( k ) ;
139
+ let changed = ! ! deleted ?. delete ( k ) ;
128
140
129
141
const existingVSet = forward . get ( k ) ;
130
142
forward . set ( k , vSet ) ;
131
143
132
144
existingVSet ?. forEach ( v => {
133
145
if ( ! vSet . has ( v ) ) {
146
+ changed = true ;
134
147
deleteFromMultimap ( reverse , v , k ) ;
135
148
}
136
149
} ) ;
137
150
138
151
vSet . forEach ( v => {
139
152
if ( ! existingVSet ?. has ( v ) ) {
153
+ changed = true ;
140
154
addToMultimap ( reverse , v , k ) ;
141
155
}
142
156
} ) ;
143
157
158
+ if ( changed ) {
159
+ version ++ ;
160
+ }
161
+
144
162
return map ;
145
163
} ,
146
164
} ;
@@ -178,22 +196,16 @@ namespace ts {
178
196
*/
179
197
export type ComputeHash = ( ( data : string ) => string ) | undefined ;
180
198
181
- /**
182
- * Get the referencedFile from the imported module symbol
183
- */
184
- function getReferencedFileFromImportedModuleSymbol ( symbol : Symbol ) {
185
- if ( symbol . declarations && symbol . declarations [ 0 ] ) {
186
- const declarationSourceFile = getSourceFileOfNode ( symbol . declarations [ 0 ] ) ;
187
- return declarationSourceFile && declarationSourceFile . resolvedPath ;
188
- }
199
+ function getReferencedFilesFromImportedModuleSymbol ( symbol : Symbol ) : Path [ ] {
200
+ return mapDefined ( symbol . declarations , declaration => getSourceFileOfNode ( declaration ) ?. resolvedPath ) ;
189
201
}
190
202
191
203
/**
192
- * Get the referencedFile from the import name node from file
204
+ * Get the module source file and all augmenting files from the import name node from file
193
205
*/
194
- function getReferencedFileFromImportLiteral ( checker : TypeChecker , importName : StringLiteralLike ) {
206
+ function getReferencedFilesFromImportLiteral ( checker : TypeChecker , importName : StringLiteralLike ) : Path [ ] | undefined {
195
207
const symbol = checker . getSymbolAtLocation ( importName ) ;
196
- return symbol && getReferencedFileFromImportedModuleSymbol ( symbol ) ;
208
+ return symbol && getReferencedFilesFromImportedModuleSymbol ( symbol ) ;
197
209
}
198
210
199
211
/**
@@ -215,10 +227,8 @@ namespace ts {
215
227
if ( sourceFile . imports && sourceFile . imports . length > 0 ) {
216
228
const checker : TypeChecker = program . getTypeChecker ( ) ;
217
229
for ( const importName of sourceFile . imports ) {
218
- const declarationSourceFilePath = getReferencedFileFromImportLiteral ( checker , importName ) ;
219
- if ( declarationSourceFilePath ) {
220
- addReferencedFile ( declarationSourceFilePath ) ;
221
- }
230
+ const declarationSourceFilePaths = getReferencedFilesFromImportLiteral ( checker , importName ) ;
231
+ declarationSourceFilePaths ?. forEach ( addReferencedFile ) ;
222
232
}
223
233
}
224
234
@@ -458,20 +468,20 @@ namespace ts {
458
468
}
459
469
460
470
let exportedModules : Set < Path > | undefined ;
461
- exportedModulesFromDeclarationEmit . forEach ( symbol => addExportedModule ( getReferencedFileFromImportedModuleSymbol ( symbol ) ) ) ;
471
+ exportedModulesFromDeclarationEmit . forEach ( symbol => addExportedModule ( getReferencedFilesFromImportedModuleSymbol ( symbol ) ) ) ;
462
472
if ( exportedModules ) {
463
473
exportedModulesMapCache . set ( sourceFile . resolvedPath , exportedModules ) ;
464
474
}
465
475
else {
466
476
exportedModulesMapCache . deleteKey ( sourceFile . resolvedPath ) ;
467
477
}
468
478
469
- function addExportedModule ( exportedModulePath : Path | undefined ) {
470
- if ( exportedModulePath ) {
479
+ function addExportedModule ( exportedModulePaths : Path [ ] | undefined ) {
480
+ if ( exportedModulePaths ?. length ) {
471
481
if ( ! exportedModules ) {
472
482
exportedModules = new Set ( ) ;
473
483
}
474
- exportedModules . add ( exportedModulePath ) ;
484
+ exportedModulePaths . forEach ( path => exportedModules ! . add ( path ) ) ;
475
485
}
476
486
}
477
487
}
@@ -483,6 +493,22 @@ namespace ts {
483
493
export function updateExportedFilesMapFromCache ( state : BuilderState , exportedModulesMapCache : ManyToManyPathMap | undefined ) {
484
494
if ( exportedModulesMapCache ) {
485
495
Debug . assert ( ! ! state . exportedModulesMap ) ;
496
+
497
+ const cacheId = exportedModulesMapCache . id ;
498
+ const cacheVersion = exportedModulesMapCache . version ( ) ;
499
+ if ( state . previousCache ) {
500
+ if ( state . previousCache . id === cacheId && state . previousCache . version === cacheVersion ) {
501
+ // If this is the same cache at the same version as last time this BuilderState
502
+ // was updated, there's no need to update again
503
+ return ;
504
+ }
505
+ state . previousCache . id = cacheId ;
506
+ state . previousCache . version = cacheVersion ;
507
+ }
508
+ else {
509
+ state . previousCache = { id : cacheId , version : cacheVersion } ;
510
+ }
511
+
486
512
exportedModulesMapCache . deletedKeys ( ) ?. forEach ( path => state . exportedModulesMap ! . deleteKey ( path ) ) ;
487
513
exportedModulesMapCache . forEach ( ( exportedModules , path ) => state . exportedModulesMap ! . set ( path , exportedModules ) ) ;
488
514
}
0 commit comments