Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show a spinner in the statusbar when lsp is busy #492

Merged
merged 2 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"@vscode/extension-telemetry": "^0.4.7",
"array-sort": "^1.0.0",
"backoff": "^2.5.0",
"brighterscript": "^0.65.1",
"brighterscript": "^0.65.4",
"brighterscript-formatter": "^1.6.30",
"debounce": "^1.2.0",
"dotenv": "^6.2.0",
Expand Down
65 changes: 46 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';
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(false);

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,43 @@ 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) {
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