Skip to content
This repository was archived by the owner on Nov 18, 2022. It is now read-only.

Commit fe0fc55

Browse files
authored
Merge pull request #763 from rust-lang/workspaces
Fix support for multiple VSCode workspaces
2 parents f52b2f6 + a54c78f commit fe0fc55

File tree

3 files changed

+56
-65
lines changed

3 files changed

+56
-65
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
### Unreleased
22

3+
* Fix support for multiple VSCode workspaces
4+
35
### 0.7.2 - 2020-04-17
46

57
* Fix a bug where rustup didn't install all of the required components for the RLS

src/extension.ts

Lines changed: 53 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,24 @@ interface ProgressParams {
4444

4545
export async function activate(context: ExtensionContext) {
4646
context.subscriptions.push(configureLanguage());
47+
context.subscriptions.push(...registerCommands());
4748

48-
workspace.onDidOpenTextDocument(doc => whenOpeningTextDocument(doc, context));
49-
workspace.textDocuments.forEach(doc => whenOpeningTextDocument(doc, context));
50-
workspace.onDidChangeWorkspaceFolders(e =>
51-
whenChangingWorkspaceFolders(e, context),
49+
workspace.onDidOpenTextDocument(doc => whenOpeningTextDocument(doc));
50+
workspace.onDidChangeWorkspaceFolders(e => whenChangingWorkspaceFolders(e));
51+
window.onDidChangeActiveTextEditor(
52+
ed => ed && whenOpeningTextDocument(ed.document),
5253
);
54+
// Installed listeners don't fire immediately for already opened files, so
55+
// trigger an open event manually to fire up RLS instances where needed
56+
workspace.textDocuments.forEach(whenOpeningTextDocument);
5357
}
5458

5559
export async function deactivate() {
5660
return Promise.all([...workspaces.values()].map(ws => ws.stop()));
5761
}
5862

5963
// Taken from https://github.com/Microsoft/vscode-extension-samples/blob/master/lsp-multi-server-sample/client/src/extension.ts
60-
function whenOpeningTextDocument(
61-
document: TextDocument,
62-
context: ExtensionContext,
63-
) {
64+
function whenOpeningTextDocument(document: TextDocument) {
6465
if (document.languageId !== 'rust' && document.languageId !== 'toml') {
6566
return;
6667
}
@@ -96,7 +97,7 @@ function whenOpeningTextDocument(
9697
const workspace = new ClientWorkspace(folder);
9798
activeWorkspace = workspace;
9899
workspaces.set(folderPath, workspace);
99-
workspace.start(context);
100+
workspace.start();
100101
} else {
101102
const ws = workspaces.get(folderPath);
102103
activeWorkspace = typeof ws === 'undefined' ? null : ws;
@@ -140,10 +141,7 @@ function getOuterMostWorkspaceFolder(folder: WorkspaceFolder): WorkspaceFolder {
140141
return folder;
141142
}
142143

143-
function whenChangingWorkspaceFolders(
144-
e: WorkspaceFoldersChangeEvent,
145-
context: ExtensionContext,
146-
) {
144+
function whenChangingWorkspaceFolders(e: WorkspaceFoldersChangeEvent) {
147145
_sortedWorkspaceFolders = undefined;
148146

149147
// If a VSCode workspace has been added, check to see if it is part of an existing one, and
@@ -157,7 +155,7 @@ function whenChangingWorkspaceFolders(
157155
if (f === 'Cargo.toml') {
158156
const workspace = new ClientWorkspace(folder);
159157
workspaces.set(folder.uri.toString(), workspace);
160-
workspace.start(context);
158+
workspace.start();
161159
break;
162160
}
163161
}
@@ -175,8 +173,6 @@ function whenChangingWorkspaceFolders(
175173

176174
// Don't use URI as it's unreliable the same path might not become the same URI.
177175
const workspaces: Map<string, ClientWorkspace> = new Map();
178-
let activeWorkspace: ClientWorkspace | null;
179-
let commandsRegistered: boolean = false;
180176

181177
// We run one RLS and one corresponding language client per workspace folder
182178
// (VSCode workspace, not Cargo workspace). This class contains all the per-client
@@ -195,7 +191,7 @@ class ClientWorkspace {
195191
this.disposables = [];
196192
}
197193

198-
public async start(context: ExtensionContext) {
194+
public async start() {
199195
if (!this.config.multiProjectEnabled) {
200196
warnOnMissingCargoToml();
201197
}
@@ -213,13 +209,9 @@ class ClientWorkspace {
213209
const isWin = process.platform === 'win32';
214210
const windowsHack = isWin ? '**' : '';
215211

216-
const pattern = this.config.multiProjectEnabled
217-
? `${windowsHack}${this.folder.uri.path}/**`
218-
: undefined;
212+
const pattern = `${windowsHack}${this.folder.uri.path}/**`;
219213

220-
const collectionName = this.config.multiProjectEnabled
221-
? `rust ${this.folder.uri.toString()}`
222-
: 'rust';
214+
const collectionName = `rust (${this.folder.uri.toString()})`;
223215
const clientOptions: LanguageClientOptions = {
224216
// Register the server for Rust files
225217

@@ -263,12 +255,9 @@ class ClientWorkspace {
263255
clientOptions,
264256
);
265257

266-
const selector = this.config.multiProjectEnabled
267-
? { language: 'rust', scheme: 'file', pattern }
268-
: { language: 'rust' };
258+
const selector = { language: 'rust', scheme: 'file', pattern };
269259

270260
this.setupProgressCounter();
271-
this.registerCommands(context, this.config.multiProjectEnabled);
272261
this.disposables.push(activateTaskProvider(this.folder));
273262
this.disposables.push(this.lc.start());
274263
this.disposables.push(
@@ -287,47 +276,19 @@ class ClientWorkspace {
287276
}
288277

289278
this.disposables.forEach(d => d.dispose());
290-
commandsRegistered = false;
291279
}
292280

293-
private registerCommands(
294-
context: ExtensionContext,
295-
multiProjectEnabled: boolean,
296-
) {
297-
if (!this.lc) {
298-
return;
299-
}
300-
if (multiProjectEnabled && commandsRegistered) {
301-
return;
302-
}
281+
public async restart() {
282+
await this.stop();
283+
return this.start();
284+
}
303285

304-
commandsRegistered = true;
305-
const rustupUpdateDisposable = commands.registerCommand(
306-
'rls.update',
307-
() => {
308-
const ws =
309-
multiProjectEnabled && activeWorkspace ? activeWorkspace : this;
310-
return rustupUpdate(ws.config.rustupConfig());
311-
},
312-
);
313-
this.disposables.push(rustupUpdateDisposable);
314-
315-
const restartServer = commands.registerCommand('rls.restart', async () => {
316-
const ws =
317-
multiProjectEnabled && activeWorkspace ? activeWorkspace : this;
318-
await ws.stop();
319-
commandsRegistered = true;
320-
return ws.start(context);
321-
});
322-
this.disposables.push(restartServer);
286+
public runRlsCommand(cmd: Execution) {
287+
return runRlsCommand(this.folder, cmd);
288+
}
323289

324-
this.disposables.push(
325-
commands.registerCommand('rls.run', (cmd: Execution) => {
326-
const ws =
327-
multiProjectEnabled && activeWorkspace ? activeWorkspace : this;
328-
runRlsCommand(ws.folder, cmd);
329-
}),
330-
);
290+
public rustupUpdate() {
291+
return rustupUpdate(this.config.rustupConfig());
331292
}
332293

333294
private async setupProgressCounter() {
@@ -499,6 +460,34 @@ async function warnOnMissingCargoToml() {
499460
}
500461
}
501462

463+
/**
464+
* Tracks the most current VSCode workspace as opened by the user. Used by the
465+
* commands to know in which workspace these should be executed.
466+
*/
467+
let activeWorkspace: ClientWorkspace | null;
468+
469+
/**
470+
* Registers the VSCode [commands] used by the extension.
471+
*
472+
* [commands]: https://code.visualstudio.com/api/extension-guides/command
473+
*/
474+
function registerCommands(): Disposable[] {
475+
return [
476+
commands.registerCommand(
477+
'rls.update',
478+
() => activeWorkspace && activeWorkspace.rustupUpdate(),
479+
),
480+
commands.registerCommand(
481+
'rls.restart',
482+
async () => activeWorkspace && activeWorkspace.restart(),
483+
),
484+
commands.registerCommand(
485+
'rls.run',
486+
(cmd: Execution) => activeWorkspace && activeWorkspace.runRlsCommand(cmd),
487+
),
488+
];
489+
}
490+
502491
/**
503492
* Sets up additional language configuration that's impossible to do via a
504493
* separate language-configuration.json file. See [1] for more information.

src/tasks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ function detectCargoTasks(target: WorkspaceFolder): Task[] {
7676
]
7777
.map(({ subcommand, group }) => ({
7878
definition: { subcommand, type: TASK_TYPE },
79-
label: `cargo ${subcommand}`,
79+
label: `cargo ${subcommand} - ${target.name}`,
8080
execution: createShellExecution({
8181
command: 'cargo',
8282
args: [subcommand],

0 commit comments

Comments
 (0)