Skip to content

Commit

Permalink
Show a spinner in the statusbar when lsp is busy
Browse files Browse the repository at this point in the history
  • Loading branch information
TwitchBronBron committed Jul 22, 2023
1 parent f1598bf commit 8d07b5b
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 20 deletions.
66 changes: 47 additions & 19 deletions src/LanguageServerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
window,
workspace
} from 'vscode';
import { BusyStatus, NotificationName, Logger } from 'brighterscript';

Check failure on line 17 in src/LanguageServerManager.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest)

Module '"brighterscript"' has no exported member 'BusyStatus'.

Check failure on line 17 in src/LanguageServerManager.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest)

Module '"brighterscript"' has no exported member 'NotificationName'.

Check failure on line 17 in src/LanguageServerManager.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest)

Module '"brighterscript"' has no exported member 'Logger'.
import { CustomCommands, Deferred } from 'brighterscript';
import type { CodeWithSourceMap } from 'source-map';
import BrightScriptDefinitionProvider from './BrightScriptDefinitionProvider';
Expand All @@ -26,6 +27,8 @@ import { util } from './util';
import { LanguageServerInfoCommand, languageServerInfoCommand } from './commands/LanguageServerInfoCommand';
import * as fsExtra from 'fs-extra';

export const LANGUAGE_SERVER_NAME = 'BrighterScript Language Server';

export class LanguageServerManager {
constructor() {
this.deferred = new Deferred();
Expand Down Expand Up @@ -101,7 +104,10 @@ export class LanguageServerManager {
//create the statusbar
this.languageServerStatusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
this.languageServerStatusBar.command = LanguageServerInfoCommand.commandName;
this.updateStatusbar('running');

//enable the statusbar loading anmation. the language server will disable once it finishes loading
this.updateStatusbar(true);

this.languageServerStatusBar.show();

//disable the simple providers (the language server will handle all of these)
Expand Down Expand Up @@ -151,7 +157,7 @@ export class LanguageServerManager {
// Create the language client and start the client.
this.client = new LanguageClient(
'brighterScriptLanguageServer',
'BrighterScript Language Server',
LANGUAGE_SERVER_NAME,
serverOptions,
clientOptions
);
Expand All @@ -162,19 +168,7 @@ export class LanguageServerManager {
this.client.onNotification('critical-failure', (message) => {
void window.showErrorMessage(message);
});

//update the statusbar with build statuses
this.client.onNotification('build-status', (message) => {
if (message === 'building') {
this.updateStatusbar('running');

} else if (message === 'success') {
this.updateStatusbar('running');

} else if (message === 'critical-error') {
this.updateStatusbar('encountered a critical runtime error', '#FF0000');
}
});
this.registerBusyStatusHandler();
this.deferred.resolve(true);
} catch (e) {
console.error(e);
Expand All @@ -188,10 +182,44 @@ export class LanguageServerManager {
return this.ready();
}

private updateStatusbar(tooltip: string, color?: string) {
this.languageServerStatusBar.text = `$(flame)bsc-${this.selectedBscInfo.version}`;
this.languageServerStatusBar.tooltip = 'BrightScript Language Server: ' + tooltip;
this.languageServerStatusBar.color = color;
private registerBusyStatusHandler() {
let timeoutHandle: NodeJS.Timeout;

const logger = new Logger();
this.client.onNotification(NotificationName.busyStatus, (event: any) => {
this.setBusyStatus(event.status);

//if the busy status takes too long, write a lsp log entry with details of what's still pending
if (event.status === BusyStatus.busy) {
timeoutHandle = setTimeout(() => {
const delay = Date.now() - event.timestamp;
this.client.outputChannel.appendLine(`${logger.getTimestamp()} language server has been 'busy' for ${delay}ms. most recent busyStatus event: ${JSON.stringify(event, undefined, 4)}`);
}, 60_000);

//clear any existing timeout
} else if (timeoutHandle) {
clearTimeout(timeoutHandle);
}
});

}

private setBusyStatus(status: BusyStatus) {
if (status === BusyStatus.busy) {
this.updateStatusbar(true);
} else {
this.updateStatusbar(false);
}
}

/**
* Enable/disable the loading spinner on the statusbar item
*/
private updateStatusbar(isLoading: boolean) {
console.log('update statusbar:', isLoading);
const icon = isLoading ? '$(sync~spin)' : '$(flame)';
this.languageServerStatusBar.text = `${icon} bsc-${this.selectedBscInfo.version}`;
this.languageServerStatusBar.tooltip = `BrightScript Language Server: running`;
}

/**
Expand Down
15 changes: 14 additions & 1 deletion src/commands/LanguageServerInfoCommand.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as vscode from 'vscode';
import { languageServerManager } from '../LanguageServerManager';
import { LANGUAGE_SERVER_NAME, languageServerManager } from '../LanguageServerManager';
import * as path from 'path';

export class LanguageServerInfoCommand {
Expand All @@ -18,12 +18,25 @@ export class LanguageServerInfoCommand {
label: `Restart BrighterScript Language Server`,
description: ``,
command: this.restartLanguageServer.bind(this)
}, {
label: `View language server logs`,
description: ``,
command: this.focusLanguageServerOutputChannel.bind(this)
}];

let selection = await vscode.window.showQuickPick(commands, { placeHolder: `BrighterScript Project Info` });
await selection?.command();
}));
}

private async focusLanguageServerOutputChannel() {
const commands = await vscode.commands.getCommands();
const command = commands.find(x => x.endsWith(LANGUAGE_SERVER_NAME));
if (command) {
void vscode.commands.executeCommand(command);
}
}

private async restartLanguageServer() {
await vscode.commands.executeCommand('extension.brightscript.languageServer.restart');
}
Expand Down

0 comments on commit 8d07b5b

Please sign in to comment.