Fixes #136540: Do not eat up error or fall back to the next provider in case an error is thrown

This commit is contained in:
Alexandru Dima 2021-11-11 09:39:06 +01:00
parent 2864014a3c
commit c06bf8757a
No known key found for this signature in database
GPG key ID: 39563C1504FDD0C9
2 changed files with 53 additions and 3 deletions

View file

@ -27,6 +27,7 @@ export class DocumentSemanticTokensResult {
constructor(
public readonly provider: DocumentSemanticTokensProvider,
public readonly tokens: SemanticTokens | SemanticTokensEdits | null,
public readonly error: any
) { }
}
@ -45,10 +46,11 @@ export async function getDocumentSemanticTokens(model: ITextModel, lastProvider:
// Get tokens from all providers at the same time.
const results = await Promise.all(providers.map(async (provider) => {
let result: SemanticTokens | SemanticTokensEdits | null | undefined;
let error: any = null;
try {
result = await provider.provideDocumentSemanticTokens(model, (provider === lastProvider ? lastResultId : null), token);
} catch (err) {
onUnexpectedExternalError(err);
error = err;
result = null;
}
@ -56,11 +58,15 @@ export async function getDocumentSemanticTokens(model: ITextModel, lastProvider:
result = null;
}
return new DocumentSemanticTokensResult(provider, result);
return new DocumentSemanticTokensResult(provider, result, error);
}));
// Try to return the first result with actual tokens
// Try to return the first result with actual tokens or
// the first result which threw an error (!!)
for (const result of results) {
if (result.error) {
throw result.error;
}
if (result.tokens) {
return result;
}

View file

@ -0,0 +1,44 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { CancellationToken } from 'vs/base/common/cancellation';
import { canceled } from 'vs/base/common/errors';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { ITextModel } from 'vs/editor/common/model';
import { DocumentSemanticTokensProvider, DocumentSemanticTokensProviderRegistry, ProviderResult, SemanticTokens, SemanticTokensEdits, SemanticTokensLegend } from 'vs/editor/common/modes';
import { getDocumentSemanticTokens } from 'vs/editor/common/services/getSemanticTokens';
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
suite('getSemanticTokens', () => {
test('issue #136540: semantic highlighting flickers', async () => {
const disposables = new DisposableStore();
const provider = new class implements DocumentSemanticTokensProvider {
getLegend(): SemanticTokensLegend {
return { tokenTypes: ['test'], tokenModifiers: [] };
}
provideDocumentSemanticTokens(model: ITextModel, lastResultId: string | null, token: CancellationToken): ProviderResult<SemanticTokens | SemanticTokensEdits> {
throw canceled();
}
releaseDocumentSemanticTokens(resultId: string | undefined): void {
}
};
disposables.add(DocumentSemanticTokensProviderRegistry.register('testLang', provider));
const textModel = disposables.add(createTextModel('example', undefined, 'testLang'));
await getDocumentSemanticTokens(textModel, null, null, CancellationToken.None).then((res) => {
assert.fail();
}, (err) => {
assert.ok(!!err);
});
disposables.dispose();
});
});