From acf29319557d700472acdb2307f7eb66aec08a0e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 29 Jan 2020 16:21:55 +0100 Subject: [PATCH] Fixes #89552: Throw from the provider when semantic tokens cannot be computed and keep old semantic tokens if this happens --- .../src/features/semanticTokens.ts | 6 +++++- src/vs/editor/common/services/modelServiceImpl.ts | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/extensions/typescript-language-features/src/features/semanticTokens.ts b/extensions/typescript-language-features/src/features/semanticTokens.ts index 3c3aff06202..252d946eb25 100644 --- a/extensions/typescript-language-features/src/features/semanticTokens.ts +++ b/extensions/typescript-language-features/src/features/semanticTokens.ts @@ -80,7 +80,11 @@ class DocumentSemanticTokensProvider implements vscode.DocumentSemanticTokensPro if (versionBeforeRequest !== versionAfterRequest) { // cannot convert result's offsets to (line;col) values correctly // a new request will come in soon... - return null; + // + // here we cannot return null, because returning null would remove all semantic tokens. + // we must throw to indicate that the semantic tokens should not be removed. + // using the string busy here because it is not logged to error telemetry if the error text contains busy. + throw new Error('busy'); } const tokenSpan = response.body.spans; diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index d77ae9bce70..ece088d6ee4 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -785,10 +785,21 @@ class ModelSemanticColoring extends Disposable { contentChangeListener.dispose(); this._setSemanticTokens(provider, res || null, styling, pendingChanges); }, (err) => { - errors.onUnexpectedError(err); + if (!err || typeof err.message !== 'string' || err.message.indexOf('busy') === -1) { + errors.onUnexpectedError(err); + } + + // Semantic tokens eats up all errors and considers errors to mean that the result is temporarily not available + // The API does not have a special error kind to express this... this._currentRequestCancellationTokenSource = null; contentChangeListener.dispose(); - this._setSemanticTokens(provider, null, styling, pendingChanges); + + if (pendingChanges.length > 0) { + // More changes occurred while the request was running + if (!this._fetchSemanticTokens.isScheduled()) { + this._fetchSemanticTokens.schedule(); + } + } }); }