]> git.lizzy.rs Git - rust.git/commitdiff
vscode: gracefully handle cancellation errors
authorVeetaha <gerzoh1@gmail.com>
Sat, 22 Feb 2020 18:58:00 +0000 (20:58 +0200)
committerVeetaha <gerzoh1@gmail.com>
Sun, 23 Feb 2020 13:49:09 +0000 (15:49 +0200)
editors/code/src/ctx.ts
editors/code/src/highlighting.ts
editors/code/src/inlay_hints.ts
editors/code/src/util.ts

index dfc8aa7b9dae29da58841e1f42799525f5e8853f..43540e0d8ea3f4a7cd92e989e55b95c869f8001d 100644 (file)
@@ -52,24 +52,3 @@ export interface Disposable {
     dispose(): void;
 }
 export type Cmd = (...args: any[]) => unknown;
-
-export async function sendRequestWithRetry<R>(
-    client: lc.LanguageClient,
-    method: string,
-    param: unknown,
-    token?: vscode.CancellationToken,
-): Promise<R> {
-    for (const delay of [2, 4, 6, 8, 10, null]) {
-        try {
-            return await (token ? client.sendRequest(method, param, token) : client.sendRequest(method, param));
-        } catch (err) {
-            if (delay === null || err.code !== lc.ErrorCodes.ContentModified) {
-                throw err;
-            }
-            await sleep(10 * (1 << delay));
-        }
-    }
-    throw 'unreachable';
-}
-
-const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
index b34e49c173aa2fd62822a7d898098a68265c8ec3..77b4a1a68b86de1f2db99e707a2cdecb1ea7f2d9 100644 (file)
@@ -3,7 +3,8 @@ import * as lc from 'vscode-languageclient';
 
 import { ColorTheme, TextMateRuleSettings } from './color_theme';
 
-import { Ctx, sendRequestWithRetry } from './ctx';
+import { Ctx } from './ctx';
+import { sendRequestWithRetry } from './util';
 
 export function activateHighlighting(ctx: Ctx) {
     const highlighter = new Highlighter(ctx);
index 7e6c310a9af6dd8c73af70df406a0a190a322588..5f9229efbced64fc4e2dcb932cc1e275625cb523 100644 (file)
@@ -1,8 +1,8 @@
 import * as vscode from 'vscode';
 import * as lc from 'vscode-languageclient';
 
-import { Ctx, sendRequestWithRetry } from './ctx';
-import { log } from './util';
+import { Ctx } from './ctx';
+import { log, sendRequestWithRetry } from './util';
 
 export function activateInlayHints(ctx: Ctx) {
     const hintsUpdater = new HintsUpdater(ctx);
@@ -152,28 +152,24 @@ class HintsUpdater {
     }
 
     private async queryHints(documentUri: string): Promise<InlayHint[] | null> {
-        const client = this.ctx.client;
-        if (!client) return null;
+        this.pending.get(documentUri)?.cancel();
 
-        const request: InlayHintsParams = {
-            textDocument: { uri: documentUri },
-        };
         const tokenSource = new vscode.CancellationTokenSource();
-        const prevHintsRequest = this.pending.get(documentUri);
-        prevHintsRequest?.cancel();
-
         this.pending.set(documentUri, tokenSource);
-        try {
-            return await sendRequestWithRetry<InlayHint[] | null>(
-                client,
-                'rust-analyzer/inlayHints',
-                request,
-                tokenSource.token,
-            );
-        } finally {
-            if (!tokenSource.token.isCancellationRequested) {
-                this.pending.delete(documentUri);
-            }
-        }
+
+        const request: InlayHintsParams = { textDocument: { uri: documentUri } };
+
+        return sendRequestWithRetry<InlayHint[]>(
+            this.ctx.client,
+            'rust-analyzer/inlayHints',
+            request,
+            tokenSource.token
+        )
+            .catch(_ => null)
+            .finally(() => {
+                if (!tokenSource.token.isCancellationRequested) {
+                    this.pending.delete(documentUri);
+                }
+            });
     }
 }
index 7a6657753bad7fbf0f7dd1c25615de0aae528957..2f18f85a39251414f926e2643380524f6ce78500 100644 (file)
@@ -1,3 +1,6 @@
+import * as lc from "vscode-languageclient";
+import * as vscode from "vscode";
+
 let enabled: boolean = false;
 
 export const log = {
@@ -16,3 +19,40 @@ export const log = {
         enabled = yes;
     }
 };
+
+export async function sendRequestWithRetry<R>(
+    client: lc.LanguageClient,
+    method: string,
+    param: unknown,
+    token?: vscode.CancellationToken,
+): Promise<R> {
+    for (const delay of [2, 4, 6, 8, 10, null]) {
+        try {
+            return await (token
+                ? client.sendRequest(method, param, token)
+                : client.sendRequest(method, param)
+            );
+        } catch (error) {
+            if (delay === null) {
+                log.error("LSP request timed out", { method, param, error });
+                throw error;
+            }
+
+            if (error.code === lc.ErrorCodes.RequestCancelled) {
+                throw error;
+            }
+
+            if (error.code !== lc.ErrorCodes.ContentModified) {
+                log.error("LSP request failed", { method, param, error });
+                throw error;
+            }
+
+            await sleep(10 * (1 << delay));
+        }
+    }
+    throw 'unreachable';
+}
+
+function sleep(ms: number) {
+    return new Promise(resolve => setTimeout(resolve, ms));
+}