about summary refs log tree commit diff
path: root/editors/code/src
diff options
context:
space:
mode:
authorVeetaha <gerzoh1@gmail.com>2020-02-22 20:58:00 +0200
committerVeetaha <gerzoh1@gmail.com>2020-02-23 15:49:09 +0200
commit4cee7cddc84aa3769d5d3e87e5745f4c981bca28 (patch)
treef8b98268925cf01e2cc74a9e12fac81a460c1eff /editors/code/src
parent838ad6bcfb2a82c030e18d019b8a06752f0fc828 (diff)
downloadrust-4cee7cddc84aa3769d5d3e87e5745f4c981bca28.tar.gz
rust-4cee7cddc84aa3769d5d3e87e5745f4c981bca28.zip
vscode: gracefully handle cancellation errors
Diffstat (limited to 'editors/code/src')
-rw-r--r--editors/code/src/ctx.ts21
-rw-r--r--editors/code/src/highlighting.ts3
-rw-r--r--editors/code/src/inlay_hints.ts40
-rw-r--r--editors/code/src/util.ts40
4 files changed, 60 insertions, 44 deletions
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts
index dfc8aa7b9da..43540e0d8ea 100644
--- a/editors/code/src/ctx.ts
+++ b/editors/code/src/ctx.ts
@@ -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));
diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts
index b34e49c173a..77b4a1a68b8 100644
--- a/editors/code/src/highlighting.ts
+++ b/editors/code/src/highlighting.ts
@@ -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);
diff --git a/editors/code/src/inlay_hints.ts b/editors/code/src/inlay_hints.ts
index 7e6c310a9af..5f9229efbce 100644
--- a/editors/code/src/inlay_hints.ts
+++ b/editors/code/src/inlay_hints.ts
@@ -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);
+                }
+            });
     }
 }
diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts
index 7a6657753ba..2f18f85a392 100644
--- a/editors/code/src/util.ts
+++ b/editors/code/src/util.ts
@@ -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));
+}