Skip to content

Better handling of typing installer events and consuming typing files in tsserver#23438

Merged
sheetalkamat merged 7 commits into
masterfrom
typingsFiles
Apr 18, 2018
Merged

Better handling of typing installer events and consuming typing files in tsserver#23438
sheetalkamat merged 7 commits into
masterfrom
typingsFiles

Conversation

@sheetalkamat
Copy link
Copy Markdown
Member

  1. Removes unnecessary indirection of unresolved imports map
  2. Force new typings resolution only if there are more or less script infos in the project. Earlier if program is not completely reused, we would enqueue new typing request, which is too frequent and not necessary. The unresolved imports and compiler options change is anyways detected to determine to queue typing request, so we want to force the typing request only if there are more or less source files in the program.
  3. In update graph, do not re-update/create new program but rather just enqueue typing request. We would handle the typing files when there are events of setting typing files from typing installer.
  4. When ActionSet event is received from typing installer, invalidate only files with unresolved imports and resolve those. The invalidation should be quite fast since it just passes list of files with unresolved imports and re-resolution happens during program creation.
  5. 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 picking unresolved imports. Earlier we use to delete existing typing files and updated program. This meant there would be need to create new program with few files (all files - typing files) and then re-queuing the request and that would just be unnecessary step.
    Note: this does not change any file/directory watches in typing installer. That needs to be handles irrespective of these changes.

…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
Comment thread src/compiler/core.ts Outdated
/** 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);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this still does not return a value.. did you mean to change this to return unorderedRemoveFirstItemWhere(array, element => element === item);

Comment thread src/server/project.ts Outdated
/*@internal*/
lastCachedUnresolvedImportsList: SortedReadonlyArray<string>;
/*@internal*/
hasMoreOrLessScriptInfos = false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider renaming this to hasAddedOrRemovedFiles

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how is that different from is this the same as projectStructureVersion change?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Comment thread src/server/project.ts Outdated
// found cached result - use it and return
for (const f of cached) {
result.push(f);
(result || (result = [])).push(f);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kinda weird that we take result as an input and return it as an output.. i would just do one of them..

Comment thread src/server/project.ts Outdated
/**
* This is the set that has entry to true if file doesnt contain any unresolved import
*/
private filesWithNoUnresolvedImports = createMap<true>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need a separate list, would not an empty array or even undefined be sufficient in cachedUnresolvedImportsPerFile?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. This was before when i was experimenting with the invalidation in a different way.

Comment thread src/server/project.ts Outdated

let hasChanges = this.updateGraphWorker();
const hasChanges = this.updateGraphWorker();
const hasMoreOrLessScriptInfos = this.hasMoreOrLessScriptInfos;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure i understand the hasChanges vs hasMoreOrLessScriptInfos distinction here..

Comment thread src/server/scriptInfo.ts Outdated
const isNew = !this.isAttached(project);
if (isNew) {
this.containingProjects.push(project);
project.hasMoreOrLessScriptInfos = true;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so why did we make this change?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we were never doing new TypingsCacheEntry() so i seems like a interface rather than class

this.projectWatchers.set(projectName, watchers);
}

watchers.isInvoked = false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so were we having same watchers in multiple projects? i am not sure i understand the change here..

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/server/project.ts Outdated
}

/* @internal */
setHasMoreOrLessFiles() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants