-
Notifications
You must be signed in to change notification settings - Fork 795
/
Copy pathstartLanguageServer.ts
155 lines (141 loc) · 5.19 KB
/
startLanguageServer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*---------------------------------------------------------
* Copyright 2022 The Go Authors. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------*/
import * as vscode from 'vscode';
import { CommandFactory } from '.';
import { getGoConfig } from '../config';
import { GoExtensionContext } from '../context';
import { outputChannel, updateLanguageServerIconGoStatusBar } from '../goStatus';
import {
buildLanguageClient,
buildLanguageServerConfig,
errorKind,
RestartReason,
scheduleGoplsSuggestions,
stopLanguageClient,
suggestGoplsIssueReport,
toServerInfo,
updateRestartHistory
} from '../language/goLanguageServer';
import { LegacyLanguageService } from '../language/registerDefaultProviders';
import { Mutex } from '../utils/mutex';
import { TelemetryService } from '../goTelemetry';
const languageServerStartMutex = new Mutex();
export const startLanguageServer: CommandFactory = (ctx, goCtx) => {
return async (reason: RestartReason = RestartReason.MANUAL) => {
const goConfig = getGoConfig();
const cfg = await buildLanguageServerConfig(goConfig);
if (typeof reason === 'string') {
updateRestartHistory(goCtx, reason, cfg.enabled);
}
const unlock = await languageServerStartMutex.lock();
goCtx.latestConfig = cfg;
try {
if (reason === RestartReason.MANUAL) {
await suggestGoplsIssueReport(
goCtx,
cfg,
"Looks like you're about to manually restart the language server.",
errorKind.manualRestart
);
}
outputChannel.info(`Try to start language server - ${reason} (enabled: ${cfg.enabled})`);
// If the client has already been started, make sure to clear existing
// diagnostics and stop it.
if (goCtx.languageClient) {
goCtx.serverOutputChannel?.append(
`Request to stop language server - ${reason} (enabled: ${cfg.enabled})`
);
await stopLanguageClient(goCtx);
}
updateStatus(goCtx, goConfig, false);
// Before starting the language server, make sure to deregister any
// currently registered language providers.
if (goCtx.legacyLanguageService) {
goCtx.legacyLanguageService.dispose();
goCtx.legacyLanguageService = undefined;
}
if (!shouldActivateLanguageFeatures()) {
outputChannel.warn('Cannot activate language features - unsupported environment');
return;
}
// We have some extra prompts for gopls users and for people who have opted
// out of gopls.
if (reason === RestartReason.ACTIVATION) {
scheduleGoplsSuggestions(goCtx);
}
if (!cfg.enabled) {
outputChannel.warn('Language server is disabled');
const legacyService = new LegacyLanguageService();
goCtx.legacyLanguageService = legacyService;
ctx.subscriptions.push(legacyService);
updateStatus(goCtx, goConfig, false);
return;
}
goCtx.languageClient = await buildLanguageClient(goCtx, cfg);
await goCtx.languageClient.start();
goCtx.serverInfo = toServerInfo(goCtx.languageClient.initializeResult);
goCtx.telemetryService = new TelemetryService(
goCtx.languageClient,
ctx.globalState,
goCtx.serverInfo?.Commands
);
outputChannel.info(
`Running language server ${goCtx.serverInfo?.Name}(${goCtx.serverInfo?.Version}/${goCtx.serverInfo?.GoVersion})`
);
} catch (e) {
const msg = `Error starting language server: ${e}`;
outputChannel.error(msg);
goCtx.serverOutputChannel?.append(msg);
} finally {
updateStatus(goCtx, goConfig, true);
unlock();
}
};
};
function updateStatus(goCtx: GoExtensionContext, goConfig: vscode.WorkspaceConfiguration, didStart: boolean) {
goCtx.languageServerIsRunning = didStart;
vscode.commands.executeCommand('setContext', 'go.goplsIsRunning', didStart);
updateLanguageServerIconGoStatusBar(goCtx.languageClient, goConfig['useLanguageServer'] === true);
}
function shouldActivateLanguageFeatures() {
for (const folder of vscode.workspace.workspaceFolders || []) {
switch (folder.uri.scheme) {
case 'vsls':
outputChannel.error(
'Language service on the guest side is disabled. ' +
'The server-side language service will provide the language features.'
);
return;
case 'ssh':
outputChannel.error('The language server is not supported for SSH. Disabling it.');
return;
}
}
const schemes = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.scheme);
if (schemes && schemes.length > 0 && !schemes.includes('file') && !schemes.includes('untitled')) {
outputChannel.error(
`None of the folders in this workspace ${schemes.join(
','
)} are the types the language server recognizes. Disabling the language features.`
);
return;
}
return true;
}
export const startGoplsMaintainerInterface: CommandFactory = (ctx, goCtx) => {
return () => {
if (!goCtx.languageServerIsRunning) {
vscode.window.showErrorMessage(
'"Go: Start language server\'s maintainer interface" command is available only when the language server is running'
);
return;
}
vscode.commands.executeCommand('gopls.start_debugging', {}).then(undefined, (reason) => {
vscode.window.showErrorMessage(
`"Go: Start language server's maintainer interface" command failed: ${reason}`
);
});
};
};