Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 33 additions & 7 deletions client-node-tests/src/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1679,7 +1679,7 @@ suite('Client integration', () => {
* settled. Only registrations made synchronously by this call are counted, so
* the client's background workspace pull doesn't interfere.
*/
async function workspacePullProgressHandlers(token: vscode.CancellationToken, expectRejection?: RegExp): Promise<{ registered: (string | number)[]; active: (string | number)[] }> {
async function workspacePullProgressHandlers(token: vscode.CancellationToken): Promise<{ registered: (string | number)[]; active: (string | number)[] }> {
const provider = client.getFeature(lsclient.DocumentDiagnosticRequest.method)?.getProvider(document);
isDefined(provider);
isDefined(provider.diagnostics.provideWorkspaceDiagnostics);
Expand All @@ -1695,11 +1695,7 @@ suite('Client integration', () => {
} finally {
onProgress.restore();
}
if (expectRejection !== undefined) {
await assert.rejects(pull, expectRejection);
} else {
await pull;
}
await pull;
return { registered, active: registered.filter(item => progressHandlers.has(item)) };
}

Expand Down Expand Up @@ -1750,7 +1746,7 @@ suite('Client integration', () => {
});
let handlers: { registered: (string | number)[]; active: (string | number)[] };
try {
handlers = await workspacePullProgressHandlers(source.token, /conversion failed/);
handlers = await workspacePullProgressHandlers(source.token);
} finally {
stub.restore();
source.dispose();
Expand All @@ -1759,6 +1755,36 @@ suite('Client integration', () => {
assert.strictEqual(handlers.active.length, 0, 'expected the progress handler to be disposed');
});

test('Workspace diagnostic pull skips a report that fails to convert and keeps the rest', async () => {
const provider = client.getFeature(lsclient.DocumentDiagnosticRequest.method)?.getProvider(document);
isDefined(provider);
isDefined(provider.diagnostics.provideWorkspaceDiagnostics);
const source = new vscode.CancellationTokenSource();
const sendRequest = client.sendRequest.bind(client) as (...args: any[]) => Promise<any>;
// Append a report whose empty message makes VS Code's Diagnostic constructor throw.
const stub = sinon.stub(client, 'sendRequest').callsFake(async (...args: any[]) => {
const result = await sendRequest(...args);
if (args[2] === source.token) {
result.items.push({ kind: 'full', uri: 'file:///bad.txt', items: [{ range: { start: { line: 0, character: 0 }, end: { line: 0, character: 1 } }, message: '' }] });
}
return result;
});
const errorLog = sinon.stub(client, 'error');
const chunks: (vsdiag.WorkspaceDiagnosticReportPartialResult | null)[] = [];
try {
await provider.diagnostics.provideWorkspaceDiagnostics([], source.token, (chunk) => chunks.push(chunk));
} finally {
stub.restore();
errorLog.restore();
source.dispose();
}
assert.strictEqual(chunks.length, 1, 'expected the final report to be delivered');
const items = chunks[0]?.items ?? [];
assert.strictEqual(items.length, 1, 'expected the valid report to be kept');
assert.notStrictEqual(items[0].uri.toString(), 'file:///bad.txt', 'expected the bad report to be skipped');
assert.ok(errorLog.calledOnceWithExactly('Converting workspace diagnostics failed.', sinon.match.any, false), 'expected the conversion failure to be logged without a notification');
});

test('Document diagnostic pull after quick reopen', async () => {
await vscode.window.showTextDocument(document);
let initialPullFinished: (() => void) | undefined;
Expand Down
10 changes: 7 additions & 3 deletions client/src/common/diagnostic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ class DiagnosticRequestor implements Disposable {
try {
converted.items.push(await convertReport(item));
} catch (error) {
this.client.error(`Converting workspace diagnostics failed.`, error);
this.client.error(`Converting workspace diagnostics failed.`, error, false);
}
}
resultReporter(converted);
Expand All @@ -644,14 +644,18 @@ class DiagnosticRequestor implements Disposable {
items: []
};
for (const item of result.items) {
converted.items.push(await convertReport(item));
try {
converted.items.push(await convertReport(item));
} catch (error) {
this.client.error(`Converting workspace diagnostics failed.`, error, false);
}
}
resultReporter(converted);
return { items: [] };
}, (error) => {
return this.client.handleFailedRequest(DocumentDiagnosticRequest.type, token, error, { items: [] });
}).finally(() => {
// Runs on success, cancellation, request failure, and a convertReport throw.
// Runs on success, cancellation, and request failure.
disposable.dispose();
});
};
Expand Down
Loading