From ce54ac184b597474d0e63b7a459227d3985f924d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Wed, 22 May 2024 15:35:41 +0200 Subject: [PATCH] vscode-ext: more error handling --- vscode-ext/src/CaesarClient.ts | 33 +++++++++++++++---------------- vscode-ext/src/Logger.ts | 11 +++++++++++ vscode-ext/src/ServerInstaller.ts | 17 ++++++++++------ 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/vscode-ext/src/CaesarClient.ts b/vscode-ext/src/CaesarClient.ts index 017820ed..a0e8013b 100644 --- a/vscode-ext/src/CaesarClient.ts +++ b/vscode-ext/src/CaesarClient.ts @@ -1,6 +1,6 @@ import { LanguageClientOptions, ResponseError, TextDocumentIdentifier, VersionedTextDocumentIdentifier } from "vscode-languageclient"; import { Executable, LanguageClient, ServerOptions } from "vscode-languageclient/node"; -import { ExtensionContext, OutputChannel, Range, TextDocument } from "vscode"; +import { ExtensionContext, Range, TextDocument } from "vscode"; import * as vscode from "vscode"; import { ConfigurationConstants } from "./constants"; import { CaesarConfig, ServerConfig } from "./Config"; @@ -10,6 +10,7 @@ import { ServerInstaller } from "./ServerInstaller"; import * as semver from 'semver'; import { isPatchCompatible } from "./version"; import { WalkthroughComponent } from "./WalkthroughComponent"; +import Logger from "./Logger"; export enum ServerStatus { Stopped, @@ -38,7 +39,7 @@ export interface ComputedPreNotification { export class CaesarClient { - private outputChannel: OutputChannel; + private logger: Logger; private walkthrough: WalkthroughComponent; private installer: ServerInstaller; private client: LanguageClient | null = null; @@ -48,11 +49,11 @@ export class CaesarClient { private computedPreListeners = new Array<(update: ComputedPreNotification) => void>(); private needsRestart = false; - constructor(context: ExtensionContext, outputChannel: OutputChannel, walkthrough: WalkthroughComponent, installer: ServerInstaller) { + constructor(context: ExtensionContext, logger: Logger, walkthrough: WalkthroughComponent, installer: ServerInstaller) { this.context = context; this.walkthrough = walkthrough; this.installer = installer; - this.outputChannel = outputChannel; + this.logger = logger; // listen to commands vscode.commands.registerCommand('caesar.restartServer', async () => { @@ -141,7 +142,7 @@ export class CaesarClient { fileEvents: vscode.workspace.createFileSystemWatcher('**/*.heyvl') }, initializationOptions, - outputChannel: this.outputChannel, + outputChannel: this.logger.outputChannel, }; const client = new LanguageClient( @@ -312,12 +313,12 @@ export class CaesarClient { }; } - async start(recommendInstallation: boolean) { + async start(recommendInstallation: boolean): Promise { if (this.client?.isRunning()) { if (this.needsRestart) { await this.stop(); } else { - return; + return true; } } @@ -328,31 +329,29 @@ export class CaesarClient { this.client = await this.createClient(recommendInstallation); if (this.client === null) { this.notifyStatusUpdate(ServerStatus.FailedToStart); - return; + return false; } } catch (error) { if (!(error instanceof Error)) { throw error; } this.notifyStatusUpdate(ServerStatus.FailedToStart); - void vscode.window.showErrorMessage(`Failed to initialize Caesar: ${error.message})`, "Show Output").then(() => { - this.outputChannel.show(); - });; - console.error(error); + this.logger.error("Failed to initialize Caesar.", error); + void this.logger.showErrorMessage(`Failed to initialize Caesar: ${error.message})`); this.client = null; - return; + return false; } try { await this.client.start(); } catch (error) { if (!(error instanceof Error)) { throw error; } - console.error("Failed to start Caesar", error); - void vscode.window.showErrorMessage(`Failed to start Caesar: ${error.message}`, "Show Output").then(() => { - this.outputChannel.show(); - }); + this.logger.error("Failed to initialize Caesar.", error); + void this.logger.showErrorMessage(`Failed to start Caesar: ${error.message})`); this.notifyStatusUpdate(ServerStatus.FailedToStart); + return false; } this.notifyStatusUpdate(ServerStatus.Ready); await this.walkthrough.setBinaryInstalled(true); + return true; } async restart() { diff --git a/vscode-ext/src/Logger.ts b/vscode-ext/src/Logger.ts index 7cd77e97..4baacdac 100644 --- a/vscode-ext/src/Logger.ts +++ b/vscode-ext/src/Logger.ts @@ -27,4 +27,15 @@ export default class Logger { public info(message: string, ...data: any[]) { this.printTimedMessage("Info", message, data); } + + public show() { + this.outputChannel.show(); + } + + public async showErrorMessage(message: string) { + const button = await window.showErrorMessage(message, "Show Output"); + if (button === "Show Output") { + this.show(); + } + } } \ No newline at end of file diff --git a/vscode-ext/src/ServerInstaller.ts b/vscode-ext/src/ServerInstaller.ts index f7351057..fcde2558 100644 --- a/vscode-ext/src/ServerInstaller.ts +++ b/vscode-ext/src/ServerInstaller.ts @@ -154,7 +154,7 @@ export class ServerInstaller { }); } - private async installAssetWithProgress(release: ReleaseAsset, progress: Progress<{ increment: number, message: string }>) { + private async installAssetWithProgress(release: ReleaseAsset, progress: Progress<{ increment: number, message?: string }>) { this.verifier.logger.info(`Installer: downloading ${release.releaseName} (${release.url})`); progress.report({ increment: 0, message: "Cleaning up old installation..." }); @@ -203,12 +203,17 @@ export class ServerInstaller { progress.report({ increment: 25, message: "Starting server..." }); await this.context.globalState.update("installedVersion", hashRelease(release)); - await this.verifier.client.start(false); + const success = await this.verifier.client.start(false); - this.verifier.logger.info(`Installer: server started.`); - progress.report({ increment: 100, message: `Successfully installed ${release.releaseName}` }); - // the progress message disappears after completion - void window.showInformationMessage(`Successfully installed Caesar ${release.releaseName}`); + if (success) { + this.verifier.logger.info(`Installer: server started.`); + progress.report({ increment: 100, message: `Successfully installed ${release.releaseName}` }); + // the progress message disappears after completion + void window.showInformationMessage(`Successfully installed Caesar ${release.releaseName}`); + } else { + progress.report({ increment: 100 }); + void this.verifier.logger.showErrorMessage("Caesar failed to install"); + } } async getLatestReleaseAsset(prerelease: boolean, assetNameIncludes: string): Promise {