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:
parent
2864014a3c
commit
c06bf8757a
|
@ -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;
|
||||
}
|
||||
|
|
44
src/vs/editor/test/common/services/getSemanticTokens.test.ts
Normal file
44
src/vs/editor/test/common/services/getSemanticTokens.test.ts
Normal 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();
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in a new issue