@@ -83,12 +83,26 @@ namespace ts {
83
83
* @param fileName The name of the file to be released
84
84
* @param compilationSettings The compilation settings used to acquire the file
85
85
*/
86
+ /**@deprecated pass scriptKind for correctness */
86
87
releaseDocument ( fileName : string , compilationSettings : CompilerOptions ) : void ;
87
-
88
+ /**
89
+ * Informs the DocumentRegistry that a file is not needed any longer.
90
+ *
91
+ * Note: It is not allowed to call release on a SourceFile that was not acquired from
92
+ * this registry originally.
93
+ *
94
+ * @param fileName The name of the file to be released
95
+ * @param compilationSettings The compilation settings used to acquire the file
96
+ * @param scriptKind The script kind of the file to be released
97
+ */
98
+ releaseDocument ( fileName : string , compilationSettings : CompilerOptions , scriptKind : ScriptKind ) : void ; // eslint-disable-line @typescript-eslint/unified-signatures
99
+ /**
100
+ * @deprecated pass scriptKind for correctness */
88
101
releaseDocumentWithKey ( path : Path , key : DocumentRegistryBucketKey ) : void ;
102
+ releaseDocumentWithKey ( path : Path , key : DocumentRegistryBucketKey , scriptKind : ScriptKind ) : void ; // eslint-disable-line @typescript-eslint/unified-signatures
89
103
90
104
/*@internal */
91
- getLanguageServiceRefCounts ( path : Path ) : [ string , number | undefined ] [ ] ;
105
+ getLanguageServiceRefCounts ( path : Path , scriptKind : ScriptKind ) : [ string , number | undefined ] [ ] ;
92
106
93
107
reportStats ( ) : string ;
94
108
}
@@ -110,6 +124,11 @@ namespace ts {
110
124
languageServiceRefCount : number ;
111
125
}
112
126
127
+ type BucketEntry = DocumentRegistryEntry | ESMap < ScriptKind , DocumentRegistryEntry > ;
128
+ function isDocumentRegistryEntry ( entry : BucketEntry ) : entry is DocumentRegistryEntry {
129
+ return ! ! ( entry as DocumentRegistryEntry ) . sourceFile ;
130
+ }
131
+
113
132
export function createDocumentRegistry ( useCaseSensitiveFileNames ?: boolean , currentDirectory ?: string ) : DocumentRegistry {
114
133
return createDocumentRegistryInternal ( useCaseSensitiveFileNames , currentDirectory ) ;
115
134
}
@@ -118,18 +137,24 @@ namespace ts {
118
137
export function createDocumentRegistryInternal ( useCaseSensitiveFileNames ?: boolean , currentDirectory = "" , externalCache ?: ExternalDocumentCache ) : DocumentRegistry {
119
138
// Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
120
139
// for those settings.
121
- const buckets = new Map < string , ESMap < Path , DocumentRegistryEntry > > ( ) ;
140
+ const buckets = new Map < DocumentRegistryBucketKey , ESMap < Path , BucketEntry > > ( ) ;
122
141
const getCanonicalFileName = createGetCanonicalFileName ( ! ! useCaseSensitiveFileNames ) ;
123
142
124
143
function reportStats ( ) {
125
144
const bucketInfoArray = arrayFrom ( buckets . keys ( ) ) . filter ( name => name && name . charAt ( 0 ) === "_" ) . map ( name => {
126
145
const entries = buckets . get ( name ) ! ;
127
- const sourceFiles : { name : string ; refCount : number ; } [ ] = [ ] ;
146
+ const sourceFiles : { name : string ; scriptKind : ScriptKind , refCount : number ; } [ ] = [ ] ;
128
147
entries . forEach ( ( entry , name ) => {
129
- sourceFiles . push ( {
130
- name,
131
- refCount : entry . languageServiceRefCount
132
- } ) ;
148
+ if ( isDocumentRegistryEntry ( entry ) ) {
149
+ sourceFiles . push ( {
150
+ name,
151
+ scriptKind : entry . sourceFile . scriptKind ,
152
+ refCount : entry . languageServiceRefCount
153
+ } ) ;
154
+ }
155
+ else {
156
+ entry . forEach ( ( value , scriptKind ) => sourceFiles . push ( { name, scriptKind, refCount : value . languageServiceRefCount } ) ) ;
157
+ }
133
158
} ) ;
134
159
sourceFiles . sort ( ( x , y ) => y . refCount - x . refCount ) ;
135
160
return {
@@ -160,6 +185,12 @@ namespace ts {
160
185
return acquireOrUpdateDocument ( fileName , path , compilationSettings , key , scriptSnapshot , version , /*acquiring*/ false , scriptKind ) ;
161
186
}
162
187
188
+ function getDocumentRegistryEntry ( bucketEntry : BucketEntry , scriptKind : ScriptKind | undefined ) {
189
+ const entry = isDocumentRegistryEntry ( bucketEntry ) ? bucketEntry : bucketEntry . get ( Debug . checkDefined ( scriptKind , "If there are more than one scriptKind's for same document the scriptKind should be provided" ) ) ;
190
+ Debug . assert ( scriptKind === undefined || ! entry || entry . sourceFile . scriptKind === scriptKind , `Script kind should match provided ScriptKind:${ scriptKind } and sourceFile.scriptKind: ${ entry ?. sourceFile . scriptKind } , !entry: ${ ! entry } ` ) ;
191
+ return entry ;
192
+ }
193
+
163
194
function acquireOrUpdateDocument (
164
195
fileName : string ,
165
196
path : Path ,
@@ -169,10 +200,11 @@ namespace ts {
169
200
version : string ,
170
201
acquiring : boolean ,
171
202
scriptKind ?: ScriptKind ) : SourceFile {
172
-
173
- const bucket = getOrUpdate ( buckets , key , ( ) => new Map < Path , DocumentRegistryEntry > ( ) ) ;
174
- let entry = bucket . get ( path ) ;
203
+ scriptKind = ensureScriptKind ( fileName , scriptKind ) ;
175
204
const scriptTarget = scriptKind === ScriptKind . JSON ? ScriptTarget . JSON : compilationSettings . target || ScriptTarget . ES5 ;
205
+ const bucket = getOrUpdate ( buckets , key , ( ) => new Map ( ) ) ;
206
+ const bucketEntry = bucket . get ( path ) ;
207
+ let entry = bucketEntry && getDocumentRegistryEntry ( bucketEntry , scriptKind ) ;
176
208
if ( ! entry && externalCache ) {
177
209
const sourceFile = externalCache . getDocument ( key , path ) ;
178
210
if ( sourceFile ) {
@@ -181,7 +213,7 @@ namespace ts {
181
213
sourceFile,
182
214
languageServiceRefCount : 0
183
215
} ;
184
- bucket . set ( path , entry ) ;
216
+ setBucketEntry ( ) ;
185
217
}
186
218
}
187
219
@@ -195,7 +227,7 @@ namespace ts {
195
227
sourceFile,
196
228
languageServiceRefCount : 1 ,
197
229
} ;
198
- bucket . set ( path , entry ) ;
230
+ setBucketEntry ( ) ;
199
231
}
200
232
else {
201
233
// We have an entry for this file. However, it may be for a different version of
@@ -221,28 +253,53 @@ namespace ts {
221
253
Debug . assert ( entry . languageServiceRefCount !== 0 ) ;
222
254
223
255
return entry . sourceFile ;
256
+
257
+ function setBucketEntry ( ) {
258
+ if ( ! bucketEntry ) {
259
+ bucket . set ( path , entry ! ) ;
260
+ }
261
+ else if ( isDocumentRegistryEntry ( bucketEntry ) ) {
262
+ const scriptKindMap = new Map < ScriptKind , DocumentRegistryEntry > ( ) ;
263
+ scriptKindMap . set ( bucketEntry . sourceFile . scriptKind , bucketEntry ) ;
264
+ scriptKindMap . set ( scriptKind ! , entry ! ) ;
265
+ bucket . set ( path , scriptKindMap ) ;
266
+ }
267
+ else {
268
+ bucketEntry . set ( scriptKind ! , entry ! ) ;
269
+ }
270
+ }
224
271
}
225
272
226
- function releaseDocument ( fileName : string , compilationSettings : CompilerOptions ) : void {
273
+ function releaseDocument ( fileName : string , compilationSettings : CompilerOptions , scriptKind ?: ScriptKind ) : void {
227
274
const path = toPath ( fileName , currentDirectory , getCanonicalFileName ) ;
228
275
const key = getKeyForCompilationSettings ( compilationSettings ) ;
229
- return releaseDocumentWithKey ( path , key ) ;
276
+ return releaseDocumentWithKey ( path , key , scriptKind ) ;
230
277
}
231
278
232
- function releaseDocumentWithKey ( path : Path , key : DocumentRegistryBucketKey ) : void {
279
+ function releaseDocumentWithKey ( path : Path , key : DocumentRegistryBucketKey , scriptKind ?: ScriptKind ) : void {
233
280
const bucket = Debug . checkDefined ( buckets . get ( key ) ) ;
234
- const entry = bucket . get ( path ) ! ;
281
+ const bucketEntry = bucket . get ( path ) ! ;
282
+ const entry = getDocumentRegistryEntry ( bucketEntry , scriptKind ) ! ;
235
283
entry . languageServiceRefCount -- ;
236
284
237
285
Debug . assert ( entry . languageServiceRefCount >= 0 ) ;
238
286
if ( entry . languageServiceRefCount === 0 ) {
239
- bucket . delete ( path ) ;
287
+ if ( isDocumentRegistryEntry ( bucketEntry ) ) {
288
+ bucket . delete ( path ) ;
289
+ }
290
+ else {
291
+ bucketEntry . delete ( scriptKind ! ) ;
292
+ if ( bucketEntry . size === 1 ) {
293
+ bucket . set ( path , firstDefinedIterator ( bucketEntry . values ( ) , identity ) ! ) ;
294
+ }
295
+ }
240
296
}
241
297
}
242
298
243
- function getLanguageServiceRefCounts ( path : Path ) {
299
+ function getLanguageServiceRefCounts ( path : Path , scriptKind : ScriptKind ) {
244
300
return arrayFrom ( buckets . entries ( ) , ( [ key , bucket ] ) : [ string , number | undefined ] => {
245
- const entry = bucket . get ( path ) ;
301
+ const bucketEntry = bucket . get ( path ) ;
302
+ const entry = bucketEntry && getDocumentRegistryEntry ( bucketEntry , scriptKind ) ;
246
303
return [ key , entry && entry . languageServiceRefCount ] ;
247
304
} ) ;
248
305
}
0 commit comments