Skip to content

Commit 8b7bc62

Browse files
committed
src/goLanguageServer: show language server start progress
Prevent duplicate language server restart requests while another restart is in progress. Allow users to cancel language server restart requests, which results in asking users to reload the window. We observed, when gopls is in a really bad state, it fails to respond to the shutdown request promptly and the restart request looks hang. In such cases, reloading the window is a quicker way to kill the language server and recover. Tested by using a broken language server that sleeps for a while upon shutdown request. Fixes #1011 Change-Id: Id1317315370ecfc8e124341a170848f7b1786335 Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/276973 Reviewed-by: Suzy Mueller <[email protected]> Trust: Hyang-Ah Hana Kim <[email protected]>
1 parent b950da5 commit 8b7bc62

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

src/goLanguageServer.ts

+40-9
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ let languageServerDisposable: vscode.Disposable;
8181
let latestConfig: LanguageServerConfig;
8282
export let serverOutputChannel: vscode.OutputChannel;
8383
export let languageServerIsRunning = false;
84+
// TODO: combine languageServerIsRunning & languageServerStartInProgress
85+
// as one languageServerStatus variable.
86+
let languageServerStartInProgress = false;
8487
let serverTraceChannel: vscode.OutputChannel;
8588
let crashCount = 0;
8689

@@ -98,6 +101,12 @@ let lastUserAction: Date = new Date();
98101
// startLanguageServerWithFallback starts the language server, if enabled,
99102
// or falls back to the default language providers.
100103
export async function startLanguageServerWithFallback(ctx: vscode.ExtensionContext, activation: boolean) {
104+
if (!activation && languageServerStartInProgress) {
105+
console.log('language server restart is already in progress...');
106+
return;
107+
}
108+
languageServerStartInProgress = true;
109+
101110
const cfg = buildLanguageServerConfig(getGoConfig());
102111

103112
// If the language server is gopls, we enable a few additional features.
@@ -109,17 +118,39 @@ export async function startLanguageServerWithFallback(ctx: vscode.ExtensionConte
109118
}
110119
}
111120

112-
const started = await startLanguageServer(ctx, cfg);
121+
const progressMsg = languageServerIsRunning ? 'Restarting language service' : 'Starting language service';
122+
await vscode.window.withProgress({
123+
title: progressMsg,
124+
cancellable: !activation,
125+
location: vscode.ProgressLocation.Notification,
126+
}, async (progress, token) => {
127+
let disposable: vscode.Disposable;
128+
if (token) {
129+
disposable = token.onCancellationRequested(async () => {
130+
const choice = await vscode.window.showErrorMessage(
131+
'Language service restart request was interrupted and language service may be in a bad state. ' +
132+
'Please reload the window.',
133+
'Reload Window');
134+
if (choice === 'Reload Window') {
135+
await vscode.commands.executeCommand('workbench.action.reloadWindow');
136+
}
137+
});
138+
}
139+
140+
const started = await startLanguageServer(ctx, cfg);
113141

114-
// If the server has been disabled, or failed to start,
115-
// fall back to the default providers, while making sure not to
116-
// re-register any providers.
117-
if (!started && defaultLanguageProviders.length === 0) {
118-
registerDefaultProviders(ctx);
119-
}
142+
// If the server has been disabled, or failed to start,
143+
// fall back to the default providers, while making sure not to
144+
// re-register any providers.
145+
if (!started && defaultLanguageProviders.length === 0) {
146+
registerDefaultProviders(ctx);
147+
}
120148

121-
languageServerIsRunning = started;
122-
updateLanguageServerIconGoStatusBar(started, cfg.serverName);
149+
if (disposable) { disposable.dispose(); }
150+
languageServerIsRunning = started;
151+
updateLanguageServerIconGoStatusBar(started, cfg.serverName);
152+
languageServerStartInProgress = false;
153+
});
123154
}
124155

125156
// scheduleGoplsSuggestions sets timeouts for the various gopls-specific

0 commit comments

Comments
 (0)