Skip to content

Commit

Permalink
fix(language-service): use tsLSHost to do module resolution
Browse files Browse the repository at this point in the history
This is a patch PR for #32479

This PR fixes a critical performance issue where the language
service makes a MASSIVE number of filesystem calls when performing
module resolution.
This is because there is no caching. To make matters worse, module
resolution is performed for every program change (which means every
few keystrokes trigger a massive number of fs calls).

There are two solutions here:

Provide a cache to ts.resolveModuleName()
Use ts.LanguageServiceHost.resolveModuleNames()
Since every Project (and by extension ConfiguredProject) implements
ts.LanguageServiceHost interface, (2) is the preferred solution here.
i.e. the TypeScript LanguageServiceHost always has the
resolveModuleNames() defined even though it's optional in the interface.
  • Loading branch information
kyliau committed Sep 4, 2019
1 parent 2b7116a commit 7c143bb
Showing 1 changed file with 7 additions and 2 deletions.
9 changes: 7 additions & 2 deletions packages/language-service/src/reflector_host.ts
Expand Up @@ -52,9 +52,9 @@ export class ReflectorHost implements StaticSymbolResolverHost {
private metadataReaderCache = createMetadataReaderCache();

constructor(
getProgram: () => ts.Program, serviceHost: ts.LanguageServiceHost,
getProgram: () => ts.Program, private readonly tsLSHost: ts.LanguageServiceHost,
private options: CompilerOptions) {
this.hostAdapter = new ReflectorModuleModuleResolutionHost(serviceHost, getProgram);
this.hostAdapter = new ReflectorModuleModuleResolutionHost(tsLSHost, getProgram);
}

getMetadataFor(modulePath: string): {[key: string]: any}[]|undefined {
Expand All @@ -69,6 +69,11 @@ export class ReflectorHost implements StaticSymbolResolverHost {
// Any containing file gives the same result for absolute imports
containingFile = path.join(this.options.basePath !, 'index.ts').replace(/\\/g, '/');
}
if (this.tsLSHost.resolveModuleNames) {
// tsLSHost contains module resolution cache that improves performance.
const result = this.tsLSHost.resolveModuleNames([moduleName], containingFile)[0];
return result ? result.resolvedFileName : null;
}
const resolved =
ts.resolveModuleName(moduleName, containingFile !, this.options, this.hostAdapter)
.resolvedModule;
Expand Down

0 comments on commit 7c143bb

Please sign in to comment.