fix crash due to exception on bg and etc (#634)

this PR also includes changes where we set completion as completion after a few characters once completion is up
This commit is contained in:
Heejae Chang 2020-04-21 14:28:56 -07:00 committed by GitHub
parent 250129961d
commit dfa5dc39d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 7 deletions

View File

@ -61,6 +61,12 @@ export class BackgroundAnalysisBase {
debug.fail(`${msg.requestType} is not expected`);
}
});
// this will catch any exception thrown from background thread,
// print log and ignore exception
worker.on('error', (msg) => {
this.log(`Error occurred on background thread: ${JSON.stringify(msg)}`);
});
}
setCompletionCallback(callback?: AnalysisCompleteCallback) {
@ -411,11 +417,11 @@ function run(code: () => any, port: MessagePort) {
port.postMessage({ kind: 'ok', data: result });
} catch (e) {
if (OperationCanceledException.is(e)) {
port.postMessage({ kind: 'cancelled', data: e });
port.postMessage({ kind: 'cancelled', data: e.message });
return;
}
port.postMessage({ kind: 'failed', data: e });
port.postMessage({ kind: 'failed', data: `Exception: ${e.message} in ${e.stack}` });
}
}

View File

@ -19,6 +19,7 @@ import {
CodeActionKind,
CodeActionParams,
Command,
CompletionTriggerKind,
ConfigurationItem,
ConnectionOptions,
createConnection,
@ -508,7 +509,23 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
};
});
let lastTriggerKind: CompletionTriggerKind | undefined = CompletionTriggerKind.Invoked;
this._connection.onCompletion(async (params, token) => {
// we set completion incomplete for the very first invocation and next consecutive call
// but after that, we mark it as completed so that client doesn't repeatedly call us back.
// we mark the very first one as incomplete since completion could be invoked without
// any meaingful character written yet; such as explict completion invocation (ctrl+space)
// or pd. <= after dot. that might cause us to not include some items (ex, auto-imports)
// the next consecutive call is so that we have some characters written to help us to pick
// better completion items.
// after that, we are not going to introduce new items so we can let client to do the filtering
// and caching.
const completionIncomplete =
lastTriggerKind !== CompletionTriggerKind.TriggerForIncompleteCompletions ||
params.context?.triggerKind !== CompletionTriggerKind.TriggerForIncompleteCompletions;
lastTriggerKind = params.context?.triggerKind;
const filePath = convertUriToPath(params.textDocument.uri);
const position: Position = {
@ -528,18 +545,20 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
token
);
// Always mark as incomplete so we get called back when the
// user continues typing. Without this, the editor will assume
// that it has received a complete list and will filter that list
// on its own.
if (completions) {
completions.isIncomplete = true;
completions.isIncomplete = completionIncomplete;
}
return completions;
});
this._connection.onCompletionResolve(async (params, token) => {
// cancellation bugs in vscode and lsp
// https://github.com/microsoft/vscode-languageserver-node/issues/615
// https://github.com/microsoft/vscode/issues/95485
//
// bugs are if resolver throws cancellation exception, lsp and vscode
// cache that result and never call us back
const completionItemData = params.data as CompletionItemData;
if (completionItemData && completionItemData.filePath) {
const workspace = await this.getWorkspaceForFile(completionItemData.workspacePath);