From dcdbbddd1630a4ed01906c2aff0e2b65ed99a591 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 17 Feb 2020 12:17:01 +0100 Subject: Simplify TS reload logic Fixes #3164 --- editors/code/src/commands/index.ts | 7 ------- editors/code/src/ctx.ts | 23 +++++++++++++---------- editors/code/src/highlighting.ts | 2 +- editors/code/src/inlay_hints.ts | 19 +++++++++++++++++-- editors/code/src/main.ts | 21 +++++++++++++++++++-- editors/code/src/status_display.ts | 2 +- 6 files changed, 51 insertions(+), 23 deletions(-) (limited to 'editors') diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts index b5ebec117..d05f40d67 100644 --- a/editors/code/src/commands/index.ts +++ b/editors/code/src/commands/index.ts @@ -51,10 +51,3 @@ export function selectAndApplySourceChange(ctx: Ctx): Cmd { } }; } - -export function reload(ctx: Ctx): Cmd { - return async () => { - vscode.window.showInformationMessage('Reloading rust-analyzer...'); - await ctx.restartServer(); - }; -} diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index ff6245f78..1eff88df2 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -1,5 +1,6 @@ import * as vscode from 'vscode'; import * as lc from 'vscode-languageclient'; +import { strict as assert } from "assert"; import { Config } from './config'; import { createClient } from './client'; @@ -16,19 +17,16 @@ export class Ctx { // on the event loop to get a better picture of what we can do here) client: lc.LanguageClient | null = null; private extCtx: vscode.ExtensionContext; - private onDidRestartHooks: Array<(client: lc.LanguageClient) => void> = []; + private onStartHooks: Array<(client: lc.LanguageClient) => void> = []; constructor(extCtx: vscode.ExtensionContext) { this.config = new Config(extCtx); this.extCtx = extCtx; } - async restartServer() { - const old = this.client; - if (old) { - await old.stop(); - } - this.client = null; + async startServer() { + assert(this.client == null); + const client = await createClient(this.config); if (!client) { throw new Error( @@ -41,7 +39,7 @@ export class Ctx { await client.onReady(); this.client = client; - for (const hook of this.onDidRestartHooks) { + for (const hook of this.onStartHooks) { hook(client); } } @@ -72,8 +70,13 @@ export class Ctx { this.extCtx.subscriptions.push(d); } - onDidRestart(hook: (client: lc.LanguageClient) => void) { - this.onDidRestartHooks.push(hook); + onStart(hook: (client: lc.LanguageClient) => void) { + const client = this.client; + if (client == null) { + this.onStartHooks.push(hook); + } else { + hook(client) + } } } diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 4fbbe3ddc..f693fb8ba 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -7,7 +7,7 @@ import { Ctx, sendRequestWithRetry } from './ctx'; export function activateHighlighting(ctx: Ctx) { const highlighter = new Highlighter(ctx); - ctx.onDidRestart(client => { + ctx.onStart(client => { client.onNotification( 'rust-analyzer/publishDecorations', (params: PublishDecorationsParams) => { diff --git a/editors/code/src/inlay_hints.ts b/editors/code/src/inlay_hints.ts index 3896878cd..9e400fabe 100644 --- a/editors/code/src/inlay_hints.ts +++ b/editors/code/src/inlay_hints.ts @@ -27,9 +27,15 @@ export function activateInlayHints(ctx: Ctx) { ctx.subscriptions ); + ctx.pushCleanup({ + dispose() { + hintsUpdater.clear() + } + }) + // We pass async function though it will not be awaited when called, // thus Promise rejections won't be handled, but this should never throw in fact... - ctx.onDidRestart(async _ => hintsUpdater.setEnabled(ctx.config.displayInlayHints)); + ctx.onStart(async _ => hintsUpdater.setEnabled(ctx.config.displayInlayHints)); } interface InlayHintsParams { @@ -61,16 +67,23 @@ class HintsUpdater { constructor(ctx: Ctx) { this.ctx = ctx; - this.enabled = ctx.config.displayInlayHints; + this.enabled = false; } async setEnabled(enabled: boolean): Promise { + console.log({ enabled, prev: this.enabled }); + if (this.enabled == enabled) return; this.enabled = enabled; if (this.enabled) { return await this.refresh(); + } else { + return this.clear(); } + } + + clear() { this.allEditors.forEach(it => { this.setTypeDecorations(it, []); this.setParameterDecorations(it, []); @@ -79,6 +92,8 @@ class HintsUpdater { async refresh() { if (!this.enabled) return; + console.log("freshin!"); + await Promise.all(this.allEditors.map(it => this.refreshEditor(it))); } diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 5a99e96f0..ec488c340 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -11,6 +11,23 @@ let ctx: Ctx | undefined; export async function activate(context: vscode.ExtensionContext) { ctx = new Ctx(context); + ctx.registerCommand('reload', (ctx) => { + return async () => { + vscode.window.showInformationMessage('Reloading rust-analyzer...'); + // @DanTup maneuver + // https://github.com/microsoft/vscode/issues/45774#issuecomment-373423895 + await deactivate() + for (const sub of ctx.subscriptions) { + try { + sub.dispose(); + } catch (e) { + console.error(e); + } + } + await activate(context) + } + }) + // Commands which invokes manually via command palette, shortcut, etc. ctx.registerCommand('analyzerStatus', commands.analyzerStatus); ctx.registerCommand('collectGarbage', commands.collectGarbage); @@ -20,7 +37,6 @@ export async function activate(context: vscode.ExtensionContext) { ctx.registerCommand('syntaxTree', commands.syntaxTree); ctx.registerCommand('expandMacro', commands.expandMacro); ctx.registerCommand('run', commands.run); - ctx.registerCommand('reload', commands.reload); ctx.registerCommand('onEnter', commands.onEnter); ctx.registerCommand('ssr', commands.ssr) @@ -38,7 +54,7 @@ export async function activate(context: vscode.ExtensionContext) { // // This a horribly, horribly wrong way to deal with this problem. try { - await ctx.restartServer(); + await ctx.startServer(); } catch (e) { vscode.window.showErrorMessage(e.message); } @@ -47,4 +63,5 @@ export async function activate(context: vscode.ExtensionContext) { export async function deactivate() { await ctx?.client?.stop(); + ctx = undefined; } diff --git a/editors/code/src/status_display.ts b/editors/code/src/status_display.ts index 993e79d70..326b5217b 100644 --- a/editors/code/src/status_display.ts +++ b/editors/code/src/status_display.ts @@ -9,7 +9,7 @@ const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', ' export function activateStatusDisplay(ctx: Ctx) { const statusDisplay = new StatusDisplay(ctx.config.cargoWatchOptions.command); ctx.pushCleanup(statusDisplay); - ctx.onDidRestart(client => ctx.pushCleanup(client.onProgress( + ctx.onStart(client => ctx.pushCleanup(client.onProgress( WorkDoneProgress.type, 'rustAnalyzer/cargoWatcher', params => statusDisplay.handleProgressNotification(params) -- cgit v1.2.3 From d24e612106867c4bb6a1e59bf99aabfb7bc27823 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 17 Feb 2020 13:40:20 +0100 Subject: Simplify startup --- editors/code/src/ctx.ts | 13 ------------- editors/code/src/highlighting.ts | 5 +++-- editors/code/src/inlay_hints.ts | 6 +++--- editors/code/src/main.ts | 21 +++++++++++---------- editors/code/src/status_display.ts | 13 ++++++++----- 5 files changed, 25 insertions(+), 33 deletions(-) (limited to 'editors') diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 1eff88df2..c06d8ac31 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -17,7 +17,6 @@ export class Ctx { // on the event loop to get a better picture of what we can do here) client: lc.LanguageClient | null = null; private extCtx: vscode.ExtensionContext; - private onStartHooks: Array<(client: lc.LanguageClient) => void> = []; constructor(extCtx: vscode.ExtensionContext) { this.config = new Config(extCtx); @@ -39,9 +38,6 @@ export class Ctx { await client.onReady(); this.client = client; - for (const hook of this.onStartHooks) { - hook(client); - } } get activeRustEditor(): vscode.TextEditor | undefined { @@ -69,15 +65,6 @@ export class Ctx { pushCleanup(d: Disposable) { this.extCtx.subscriptions.push(d); } - - onStart(hook: (client: lc.LanguageClient) => void) { - const client = this.client; - if (client == null) { - this.onStartHooks.push(hook); - } else { - hook(client) - } - } } export interface Disposable { diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index f693fb8ba..a2db04de8 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -7,7 +7,8 @@ import { Ctx, sendRequestWithRetry } from './ctx'; export function activateHighlighting(ctx: Ctx) { const highlighter = new Highlighter(ctx); - ctx.onStart(client => { + const client = ctx.client; + if (client != null) { client.onNotification( 'rust-analyzer/publishDecorations', (params: PublishDecorationsParams) => { @@ -28,7 +29,7 @@ export function activateHighlighting(ctx: Ctx) { highlighter.setHighlights(targetEditor, params.decorations); }, ); - }); + }; vscode.workspace.onDidChangeConfiguration( _ => highlighter.removeHighlights(), diff --git a/editors/code/src/inlay_hints.ts b/editors/code/src/inlay_hints.ts index 9e400fabe..55bbd7f00 100644 --- a/editors/code/src/inlay_hints.ts +++ b/editors/code/src/inlay_hints.ts @@ -33,9 +33,9 @@ export function activateInlayHints(ctx: Ctx) { } }) - // We pass async function though it will not be awaited when called, - // thus Promise rejections won't be handled, but this should never throw in fact... - ctx.onStart(async _ => hintsUpdater.setEnabled(ctx.config.displayInlayHints)); + // XXX: we don't await this, thus Promise rejections won't be handled, but + // this should never throw in fact... + hintsUpdater.setEnabled(ctx.config.displayInlayHints) } interface InlayHintsParams { diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index ec488c340..0bf2c4829 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -11,6 +11,17 @@ let ctx: Ctx | undefined; export async function activate(context: vscode.ExtensionContext) { ctx = new Ctx(context); + // Note: we try to start the server before we activate type hints so that it + // registers its `onDidChangeDocument` handler before us. + // + // This a horribly, horribly wrong way to deal with this problem. + try { + await ctx.startServer(); + } catch (e) { + vscode.window.showErrorMessage(e.message); + } + + // Commands which invokes manually via command palette, shortcut, etc. ctx.registerCommand('reload', (ctx) => { return async () => { vscode.window.showInformationMessage('Reloading rust-analyzer...'); @@ -28,7 +39,6 @@ export async function activate(context: vscode.ExtensionContext) { } }) - // Commands which invokes manually via command palette, shortcut, etc. ctx.registerCommand('analyzerStatus', commands.analyzerStatus); ctx.registerCommand('collectGarbage', commands.collectGarbage); ctx.registerCommand('matchingBrace', commands.matchingBrace); @@ -49,15 +59,6 @@ export async function activate(context: vscode.ExtensionContext) { activateStatusDisplay(ctx); activateHighlighting(ctx); - // Note: we try to start the server before we activate type hints so that it - // registers its `onDidChangeDocument` handler before us. - // - // This a horribly, horribly wrong way to deal with this problem. - try { - await ctx.startServer(); - } catch (e) { - vscode.window.showErrorMessage(e.message); - } activateInlayHints(ctx); } diff --git a/editors/code/src/status_display.ts b/editors/code/src/status_display.ts index 326b5217b..ed0d82166 100644 --- a/editors/code/src/status_display.ts +++ b/editors/code/src/status_display.ts @@ -9,11 +9,14 @@ const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', ' export function activateStatusDisplay(ctx: Ctx) { const statusDisplay = new StatusDisplay(ctx.config.cargoWatchOptions.command); ctx.pushCleanup(statusDisplay); - ctx.onStart(client => ctx.pushCleanup(client.onProgress( - WorkDoneProgress.type, - 'rustAnalyzer/cargoWatcher', - params => statusDisplay.handleProgressNotification(params) - ))); + const client = ctx.client; + if (client != null) { + ctx.pushCleanup(client.onProgress( + WorkDoneProgress.type, + 'rustAnalyzer/cargoWatcher', + params => statusDisplay.handleProgressNotification(params) + )) + } } class StatusDisplay implements Disposable { -- cgit v1.2.3