From 5577502c1ced538626cba077e5b1fcd953e9393c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 28 Aug 2020 10:12:54 +0200 Subject: [PATCH] Do not load lib.d.ts files on the UI thread --- src/languageFeatures.ts | 51 +++++++++++++++++++++++------------------ src/tsMode.ts | 2 +- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/languageFeatures.ts b/src/languageFeatures.ts index ef7f6033..7ebed608 100644 --- a/src/languageFeatures.ts +++ b/src/languageFeatures.ts @@ -7,7 +7,6 @@ import { LanguageServiceDefaultsImpl } from './monaco.contribution'; import * as ts from './lib/typescriptServices'; import { TypeScriptWorker } from './tsWorker'; -import { libFileMap } from "./lib/lib" import { libFileSet } from "./lib/lib.index" import Uri = monaco.Uri; @@ -24,16 +23,6 @@ enum IndentStyle { Smart = 2 } -function getOrCreateLibFile(uri: Uri): monaco.editor.ITextModel | null { - let model = monaco.editor.getModel(uri) - if (!model) { - if (uri.path.indexOf("/lib.") === 0) { - return monaco.editor.createModel(libFileMap[uri.path.slice(1)], "javascript", uri) - } - } - return model -} - export function flattenDiagnosticMessageText(diag: string | ts.DiagnosticMessageChain | undefined, newLine: string, indent = 0): string { if (typeof diag === "string") { return diag; @@ -106,7 +95,10 @@ export class LibFiles { this._fetchLibFilesPromise = null; } - public isLibFile(uri: Uri): boolean { + public isLibFile(uri: Uri | null): boolean { + if (!uri) { + return false; + } if (uri.path.indexOf("/lib.") === 0) { return !!libFileSet[uri.path.slice(1)]; } @@ -124,7 +116,7 @@ export class LibFiles { return null; } - private _containsLibFile(uris: Uri[]): boolean { + private _containsLibFile(uris: (Uri | null)[]): boolean { for (let uri of uris) { if (this.isLibFile(uri)) { return true; @@ -133,7 +125,7 @@ export class LibFiles { return false; } - public async fetchLibFilesIfNecessary(uris: Uri[]): Promise { + public async fetchLibFilesIfNecessary(uris: (Uri | null)[]): Promise { if (!this._containsLibFile(uris)) { // no lib files necessary return; @@ -170,7 +162,10 @@ export class DiagnosticsAdapter extends Adapter { private _disposables: IDisposable[] = []; private _listener: { [uri: string]: IDisposable } = Object.create(null); - constructor(private _defaults: LanguageServiceDefaultsImpl, private _selector: string, + constructor( + private readonly _libFiles: LibFiles, + private _defaults: LanguageServiceDefaultsImpl, + private _selector: string, worker: (...uris: Uri[]) => Promise ) { super(worker); @@ -258,19 +253,31 @@ export class DiagnosticsAdapter extends Adapter { promises.push(worker.getSuggestionDiagnostics(model.uri.toString())); } - const diagnostics = await Promise.all(promises); + const allDiagnostics = await Promise.all(promises); - if (!diagnostics || model.isDisposed()) { + if (!allDiagnostics || model.isDisposed()) { // model was disposed in the meantime return; } - const markers = diagnostics + const diagnostics = allDiagnostics .reduce((p, c) => c.concat(p), []) - .filter(d => (this._defaults.getDiagnosticsOptions().diagnosticCodesToIgnore || []).indexOf(d.code) === -1) - .map(d => this._convertDiagnostics(model, d)); + .filter(d => (this._defaults.getDiagnosticsOptions().diagnosticCodesToIgnore || []).indexOf(d.code) === -1); + + // Fetch lib files if necessary + const relatedUris = diagnostics + .map(d => d.relatedInformation || []) + .reduce((p, c) => c.concat(p), []) + .map(relatedInformation => relatedInformation.file ? monaco.Uri.parse(relatedInformation.file.fileName) : null); + + await this._libFiles.fetchLibFilesIfNecessary(relatedUris); + + if (model.isDisposed()) { + // model was disposed in the meantime + return; + } - monaco.editor.setModelMarkers(model, this._selector, markers); + monaco.editor.setModelMarkers(model, this._selector, diagnostics.map(d => this._convertDiagnostics(model, d))); } private _convertDiagnostics(model: monaco.editor.ITextModel, diag: ts.Diagnostic): monaco.editor.IMarkerData { @@ -302,7 +309,7 @@ export class DiagnosticsAdapter extends Adapter { let relatedResource: monaco.editor.ITextModel | null = model; if (info.file) { const relatedResourceUri = monaco.Uri.parse(info.file.fileName); - relatedResource = getOrCreateLibFile(relatedResourceUri); + relatedResource = this._libFiles.getOrCreateModel(relatedResourceUri); } if (!relatedResource) { diff --git a/src/tsMode.ts b/src/tsMode.ts index 9bfbed37..aef2a6ea 100644 --- a/src/tsMode.ts +++ b/src/tsMode.ts @@ -68,7 +68,7 @@ function setupMode(defaults: LanguageServiceDefaultsImpl, modeId: string): (...u monaco.languages.registerOnTypeFormattingEditProvider(modeId, new languageFeatures.FormatOnTypeAdapter(worker)); monaco.languages.registerCodeActionProvider(modeId, new languageFeatures.CodeActionAdaptor(worker)); monaco.languages.registerRenameProvider(modeId, new languageFeatures.RenameAdapter(worker)); - new languageFeatures.DiagnosticsAdapter(defaults, modeId, worker); + new languageFeatures.DiagnosticsAdapter(libFiles, defaults, modeId, worker); return worker; }