Skip to content

Commit 3f0bdc5

Browse files
authored
Add r.lsp.multiServer setting (#1375)
* Use single language server and client * Add r.lsp.multiServer setting * Update setting description * Update setting description * Update startLanguageService * Update stopLanguageService
1 parent 36f5493 commit 3f0bdc5

2 files changed

Lines changed: 38 additions & 11 deletions

File tree

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,11 @@
15061506
"default": false,
15071507
"description": "Use STDIO connection instead of TCP. (Unix/macOS users only)"
15081508
},
1509+
"r.lsp.multiServer": {
1510+
"type": "boolean",
1511+
"default": true,
1512+
"markdownDescription": "Use multiple language servers for [multi-root workspaces](https://code.visualstudio.com/docs/editor/multi-root-workspaces). If disabled, only one language server will be used to handle all requests from all workspaces and files."
1513+
},
15091514
"r.rmarkdown.codeLensCommands": {
15101515
"type": "array",
15111516
"items": {

src/languageService.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@ import { extensionContext } from './extension';
99
import { CommonOptions } from 'child_process';
1010

1111
export class LanguageService implements Disposable {
12+
private client: LanguageClient | undefined;
1213
private readonly clients: Map<string, LanguageClient> = new Map();
1314
private readonly initSet: Set<string> = new Set();
15+
private readonly config: WorkspaceConfiguration;
16+
private readonly outputChannel: OutputChannel;
1417

1518
constructor() {
16-
this.startLanguageService(this);
19+
this.outputChannel = window.createOutputChannel('R Language Server');
20+
this.client = undefined;
21+
this.config = workspace.getConfiguration('r');
22+
void this.startLanguageService(this);
1723
}
1824

1925
dispose(): Thenable<void> {
@@ -154,6 +160,7 @@ export class LanguageService implements Disposable {
154160
return client;
155161
}
156162

163+
157164
private checkClient(name: string): boolean {
158165
if (this.initSet.has(name)) {
159166
return true;
@@ -174,10 +181,7 @@ export class LanguageService implements Disposable {
174181
}
175182
}
176183

177-
private startLanguageService(self: LanguageService): void {
178-
const config = workspace.getConfiguration('r');
179-
const outputChannel: OutputChannel = window.createOutputChannel('R Language Server');
180-
184+
private startMultiLanguageService(self: LanguageService): void {
181185
async function didOpenTextDocument(document: TextDocument) {
182186
if (document.uri.scheme !== 'file' && document.uri.scheme !== 'untitled' && document.uri.scheme !== 'vscode-notebook-cell') {
183187
return;
@@ -197,8 +201,8 @@ export class LanguageService implements Disposable {
197201
const documentSelector: DocumentFilter[] = [
198202
{ scheme: 'vscode-notebook-cell', language: 'r', pattern: `${document.uri.fsPath}` },
199203
];
200-
const client = await self.createClient(config, documentSelector,
201-
dirname(document.uri.fsPath), folder, outputChannel);
204+
const client = await self.createClient(self.config, documentSelector,
205+
dirname(document.uri.fsPath), folder, self.outputChannel);
202206
self.clients.set(key, client);
203207
self.initSet.delete(key);
204208
}
@@ -216,7 +220,7 @@ export class LanguageService implements Disposable {
216220
{ scheme: 'file', language: 'r', pattern: pattern },
217221
{ scheme: 'file', language: 'rmd', pattern: pattern },
218222
];
219-
const client = await self.createClient(config, documentSelector, folder.uri.fsPath, folder, outputChannel);
223+
const client = await self.createClient(self.config, documentSelector, folder.uri.fsPath, folder, self.outputChannel);
220224
self.clients.set(key, client);
221225
self.initSet.delete(key);
222226
}
@@ -232,7 +236,7 @@ export class LanguageService implements Disposable {
232236
{ scheme: 'untitled', language: 'r' },
233237
{ scheme: 'untitled', language: 'rmd' },
234238
];
235-
const client = await self.createClient(config, documentSelector, os.homedir(), undefined, outputChannel);
239+
const client = await self.createClient(self.config, documentSelector, os.homedir(), undefined, self.outputChannel);
236240
self.clients.set(key, client);
237241
self.initSet.delete(key);
238242
}
@@ -247,8 +251,8 @@ export class LanguageService implements Disposable {
247251
const documentSelector: DocumentFilter[] = [
248252
{ scheme: 'file', pattern: document.uri.fsPath },
249253
];
250-
const client = await self.createClient(config, documentSelector,
251-
dirname(document.uri.fsPath), undefined, outputChannel);
254+
const client = await self.createClient(self.config, documentSelector,
255+
dirname(document.uri.fsPath), undefined, self.outputChannel);
252256
self.clients.set(key, client);
253257
self.initSet.delete(key);
254258
}
@@ -301,8 +305,26 @@ export class LanguageService implements Disposable {
301305
});
302306
}
303307

308+
private async startLanguageService(self: LanguageService): Promise<void> {
309+
if (self.config.get<boolean>('r.lsp.multiServer')) {
310+
return this.startMultiLanguageService(self);
311+
} else {
312+
const documentSelector: DocumentFilter[] = [
313+
{ language: 'r' },
314+
{ language: 'rmd' },
315+
];
316+
317+
const workspaceFolder = workspace.workspaceFolders?.[0];
318+
const cwd = workspaceFolder ? workspaceFolder.uri.fsPath : os.homedir();
319+
self.client = await self.createClient(self.config, documentSelector, cwd, workspaceFolder, self.outputChannel);
320+
}
321+
}
322+
304323
private stopLanguageService(): Thenable<void> {
305324
const promises: Thenable<void>[] = [];
325+
if (this.client) {
326+
promises.push(this.client.stop());
327+
}
306328
for (const client of this.clients.values()) {
307329
promises.push(client.stop());
308330
}

0 commit comments

Comments
 (0)