Better handling of typing installer events and consuming typing files in tsserver#23438
Conversation
…rection and helps only in test only
…fos in the project. This helps in reducing number of forced typing installation requests We anyways use changes in unresolved import array to determine if we need to enqueue new typing request Hence there is no need to soley rely on hasChanges from updateGraph which just indicates that we didnt reused the program (that does not mean new files were added to the program or changes in unresolved imports)
This has 3 changes: 1. In updateGraph when enqueue the typing installation request (depending on unresolved imports) 2. When ActionSet event is received, invalidate only files with unresolved imports and resolve those. 3. When ActionInvalidate event is received, typing installer has detected some change in global typing cache location, so just enqueue a new typing installation request. This will repeat the cycle of setting correct typings and pickiing unresolved imports
…since watchers arent closed if they need to be reopened
| /** Remove the *first* occurrence of `item` from the array. */ | ||
| export function unorderedRemoveItem<T>(array: T[], item: T): void { | ||
| export function unorderedRemoveItem<T>(array: T[], item: T) { | ||
| unorderedRemoveFirstItemWhere(array, element => element === item); |
There was a problem hiding this comment.
this still does not return a value.. did you mean to change this to return unorderedRemoveFirstItemWhere(array, element => element === item);
| /*@internal*/ | ||
| lastCachedUnresolvedImportsList: SortedReadonlyArray<string>; | ||
| /*@internal*/ | ||
| hasMoreOrLessScriptInfos = false; |
There was a problem hiding this comment.
consider renaming this to hasAddedOrRemovedFiles
There was a problem hiding this comment.
how is that different from is this the same as projectStructureVersion change?
There was a problem hiding this comment.
projectStructureVersion is actually program version = every time new program is created this version is incremented. We could create new program using existing files (without any additional or removal of script infos when we decide its safe to reuse the modules, eg. adding import in file such that imported module was already part of the program, so it would be new program but no additional files woult be there in the program)
| // found cached result - use it and return | ||
| for (const f of cached) { | ||
| result.push(f); | ||
| (result || (result = [])).push(f); |
There was a problem hiding this comment.
kinda weird that we take result as an input and return it as an output.. i would just do one of them..
| /** | ||
| * This is the set that has entry to true if file doesnt contain any unresolved import | ||
| */ | ||
| private filesWithNoUnresolvedImports = createMap<true>(); |
There was a problem hiding this comment.
why do we need a separate list, would not an empty array or even undefined be sufficient in cachedUnresolvedImportsPerFile?
There was a problem hiding this comment.
Agreed. This was before when i was experimenting with the invalidation in a different way.
|
|
||
| let hasChanges = this.updateGraphWorker(); | ||
| const hasChanges = this.updateGraphWorker(); | ||
| const hasMoreOrLessScriptInfos = this.hasMoreOrLessScriptInfos; |
There was a problem hiding this comment.
not sure i understand the hasChanges vs hasMoreOrLessScriptInfos distinction here..
| const isNew = !this.isAttached(project); | ||
| if (isNew) { | ||
| this.containingProjects.push(project); | ||
| project.hasMoreOrLessScriptInfos = true; |
There was a problem hiding this comment.
i would rather make this a function call and let the project handle it by setting the flag, instead of setting the flag here.. just an encapsulation comment.
| }; | ||
|
|
||
| class TypingsCacheEntry { | ||
| interface TypingsCacheEntry { |
There was a problem hiding this comment.
so why did we make this change?
There was a problem hiding this comment.
we were never doing new TypingsCacheEntry() so i seems like a interface rather than class
| this.projectWatchers.set(projectName, watchers); | ||
| } | ||
|
|
||
| watchers.isInvoked = false; |
There was a problem hiding this comment.
so were we having same watchers in multiple projects? i am not sure i understand the change here..
There was a problem hiding this comment.
Previously the isInvoked was local variable that was captured. If there were additional watches added to the project (because it has more files etc) the new isInvoked would be used for additional watchers, but the existing watches would still refer to the previous isInvoked thus invalidating the typing multiple times or ignoring the typings assuming it was already invalidating.
| } | ||
|
|
||
| /* @internal */ | ||
| setHasMoreOrLessFiles() { |
There was a problem hiding this comment.
consider renaming the function to onFileAddedOrRemoved and the property to hasAddedorRemovedFiles, since the count can be the same, but we still need to invalidate the cache.
Note: this does not change any file/directory watches in typing installer. That needs to be handles irrespective of these changes.