Skip to content

Commit 152c544

Browse files
committed
feat: make r.lsp.multiServer accept auto, true, or false
- Updates configuration to allow 'auto', true, or false. - 'auto' uses single server mode for languageserver >= 0.3.18, and multi-server otherwise. - Introduces compareVersions utility to avoid external dependency. - Backward compatible with existing boolean settings.
1 parent 01a62f6 commit 152c544

3 files changed

Lines changed: 43 additions & 5 deletions

File tree

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,9 +1388,10 @@
13881388
"description": "Use STDIO connection instead of TCP. (Unix/macOS users only)"
13891389
},
13901390
"r.lsp.multiServer": {
1391-
"type": "boolean",
1392-
"default": false,
1393-
"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. Disabling this is recommended if you have the R `languageserver` package version >= 0.3.18 installed."
1391+
"type": ["string", "boolean"],
1392+
"enum": ["auto", true, false],
1393+
"default": "auto",
1394+
"markdownDescription": "Use multiple language servers for [multi-root workspaces](https://code.visualstudio.com/docs/editor/multi-root-workspaces). When set to `auto`, it will use a single server if the R `languageserver` package version is >= 0.3.18, and multiple servers otherwise. Disabling this (or using `auto` with a recent version) is recommended for better performance."
13941395
},
13951396
"r.rmarkdown.codeLensCommands": {
13961397
"type": "array",

src/languageService.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as net from 'net';
44
import { URL } from 'url';
55
import { LanguageClient, LanguageClientOptions, StreamInfo, DocumentFilter, ErrorAction, CloseAction, RevealOutputChannelOn } from 'vscode-languageclient/node';
66
import { Disposable, workspace, Uri, TextDocument, WorkspaceConfiguration, OutputChannel, window, WorkspaceFolder } from 'vscode';
7-
import { DisposableProcess, getRLibPaths, getRpath, promptToInstallRPackage, spawn, substituteVariables } from './util';
7+
import { DisposableProcess, getRLibPaths, getRpath, promptToInstallRPackage, spawn, substituteVariables, getRPackageVersion, compareVersions } from './util';
88
import { extensionContext } from './extension';
99
import { CommonOptions } from 'child_process';
1010

@@ -309,7 +309,23 @@ export class LanguageService implements Disposable {
309309
}
310310

311311
private async startLanguageService(): Promise<void> {
312-
if (this.config.get<boolean>('lsp.multiServer')) {
312+
let useMultiServer = false;
313+
const multiServerConfig = this.config.get<string | boolean>('lsp.multiServer');
314+
315+
if (multiServerConfig === 'auto') {
316+
const version = await getRPackageVersion('languageserver');
317+
if (version && compareVersions(version, '0.3.18') < 0) {
318+
console.log(`languageserver version is ${version}, using multi-server.`);
319+
useMultiServer = true;
320+
} else {
321+
console.log(`languageserver version is ${version || 'unknown'}, using single-server.`);
322+
useMultiServer = false;
323+
}
324+
} else if (multiServerConfig === true || multiServerConfig === 'true') {
325+
useMultiServer = true;
326+
}
327+
328+
if (useMultiServer) {
313329
this.startMultiLanguageService();
314330
} else {
315331
const documentSelector: DocumentFilter[] = [

src/util.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,27 @@ export async function getCranUrl(path: string = '', cwd?: string | URL): Promise
328328
return url;
329329
}
330330

331+
export async function getRVersion(cwd?: string | URL): Promise<string | undefined> {
332+
return await executeRCommand('cat(as.character(getRversion()))', cwd);
333+
}
334+
335+
export async function getRPackageVersion(name: string, cwd?: string | URL): Promise<string | undefined> {
336+
return await executeRCommand(`cat(as.character(utils::packageVersion('${name}')))`, cwd);
337+
}
338+
339+
export function compareVersions(v1: string, v2: string): number {
340+
const parts1 = v1.split('.').map(Number);
341+
const parts2 = v2.split('.').map(Number);
342+
const len = Math.max(parts1.length, parts2.length);
343+
for (let i = 0; i < len; i++) {
344+
const num1 = parts1[i] || 0;
345+
const num2 = parts2[i] || 0;
346+
if (num1 > num2) return 1;
347+
if (num1 < num2) return -1;
348+
}
349+
return 0;
350+
}
351+
331352
export function getRLibPaths(): string | undefined {
332353
return config().get<string[]>('libPaths')?.map(substituteVariables).join('\n');
333354
}

0 commit comments

Comments
 (0)