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

Allow having Cargo.toml in a subdirectory with rust-client.cargoSubdir #334

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
"postinstall": "node ./node_modules/vscode/bin/install"
},
"dependencies": {
"vscode-languageclient": "^4.1.4"
"vscode-languageclient": "^4.1.4",
"path": "^0.12.0"
},
"devDependencies": {
"@types/mocha": "^2.2.43",
Expand Down Expand Up @@ -191,6 +192,11 @@
"default": "rls-preview",
"description": "Name of the RLS rustup component."
},
"rust-client.cargoSubdir": {
"type": "string",
"default": "",
"description": "Relative path to Cargo.toml. By default, it is workspace root."
},
"rust.sysroot": {
"type": [
"string",
Expand Down
2 changes: 2 additions & 0 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class RLSConfiguration {
* If specified, RLS will be spawned by executing a file at the given path.
*/
public readonly rlsPath: string | null;
public readonly cargoSubdir: string | null;

public static loadFromWorkspace(): RLSConfiguration {
const configuration = workspace.getConfiguration();
Expand All @@ -66,6 +67,7 @@ export class RLSConfiguration {
if (!this.rlsPath) {
this.rlsPath = rlsPath;
}
this.cargoSubdir = configuration.get('rust-client.cargoSubdir', null);
}

private static readRevealOutputChannelOn(configuration: WorkspaceConfiguration) {
Expand Down
54 changes: 44 additions & 10 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ import { activateTaskProvider, deactivateTaskProvider } from './tasks';

import * as child_process from 'child_process';
import * as fs from 'fs';
import * as path from 'path';

import { commands, ExtensionContext, IndentAction, languages, TextEditor,
TextEditorEdit, window, workspace } from 'vscode';
TextEditorEdit, window, workspace, Uri } from 'vscode';
import { LanguageClient, LanguageClientOptions, Location, NotificationType,
ServerOptions } from 'vscode-languageclient';
import { execFile, ExecChildProcessResult } from './utils/child_process';
Expand Down Expand Up @@ -82,14 +83,19 @@ async function makeRlsProcess(): Promise<child_process.ChildProcess> {
const rls_path = CONFIGURATION.rlsPath;

let childProcessPromise: Promise<child_process.ChildProcess>;
const cargoSubdir = workspace.getConfiguration().get('rust-client.cargoSubdir');
const cargo_toml_path = workspace.rootPath + ( cargoSubdir ? '/'+cargoSubdir : '');
if (rls_path) {
const env = await makeRlsEnv(true);
console.info('running ' + rls_path);
childProcessPromise = Promise.resolve(child_process.spawn(rls_path, [], { env }));
console.info('running ' + rls_path + ' using CWD "'+cargo_toml_path+'"');
childProcessPromise = Promise.resolve(child_process.spawn(rls_path, [], { cwd: cargo_toml_path, env }));
} else {
const env = await makeRlsEnv();
console.info('running with rustup');
childProcessPromise = runRlsViaRustup(env);
console.info('running with rustup using CWD "'+cargo_toml_path+'"');
const env_2 = {...env, cwd: cargo_toml_path};
console.info(env_2);
console.info(cargo_toml_path);
childProcessPromise = runRlsViaRustup(env_2);
}
try {
const childProcess = await childProcessPromise;
Expand Down Expand Up @@ -134,7 +140,7 @@ export async function activate(context: ExtensionContext) {
}

async function startLanguageClient(context: ExtensionContext) {
if (workspace.rootPath === undefined) {
if (workspace.rootPath === undefined || !workspace.workspaceFolders) {
window.showWarningMessage('Startup error: the RLS can only operate on a folder, not a single file');
return;
}
Expand All @@ -154,6 +160,8 @@ async function startLanguageClient(context: ExtensionContext) {
await autoUpdate();
return makeRlsProcess();
};
const cargoSubdir = workspace.getConfiguration().get('rust-client.cargoSubdir');
const workspaceFolder = workspace.workspaceFolders[0];
const clientOptions: LanguageClientOptions = {
// Register the server for Rust files
documentSelector: [
Expand All @@ -164,6 +172,8 @@ async function startLanguageClient(context: ExtensionContext) {
// Controls when to focus the channel rather than when to reveal it in the drop-down list
revealOutputChannelOn: CONFIGURATION.revealOutputChannelOn,
initializationOptions: { omitInitBuild: true },
workspaceFolder: {...workspaceFolder,
uri: Uri.parse('file://' + workspace.rootPath + (cargoSubdir ? '/'+cargoSubdir : ''))}
};

// Create the language client and start the client.
Expand All @@ -186,10 +196,34 @@ export function deactivate(): Promise<void> {
}

async function warnOnMissingCargoToml() {
const files = await workspace.findFiles('Cargo.toml');

if (files.length < 1) {
window.showWarningMessage('A Cargo.toml file must be at the root of the workspace in order to support all features');
const setting_section = 'rust-client.cargoSubdir';
const root_toml_files = await workspace.findFiles('Cargo.toml');

if (root_toml_files.length < 1) {
const subdir_toml_files = await workspace.findFiles('**/Cargo.toml');
const setting_value = workspace.getConfiguration().get(setting_section);
if (subdir_toml_files.length < 1) {
window.showWarningMessage(`The Cargo.toml file has not been found at
the root of the workspace or anywhere else. In order to support all
RLS features, some Cargo.toml must be present.`);

} else if (! setting_value) {
const subdir = path.dirname(workspace.asRelativePath(subdir_toml_files[0]));
const item_save_to_settings = `Save to '.vscode/settings.json'`;
window.showWarningMessage(`A Cargo.toml has been found in the sudirectory '${subdir}/'.
Although RLS expects Cargo.toml to be at the root of the workspace,
we can set this path using the '${setting_section}' setting in your
'.vscode/settings.json'`, ...[item_save_to_settings])
.then(v => {
switch (v) {
case item_save_to_settings:
workspace.getConfiguration().update(setting_section, subdir);
break;
default:
break;
}
});
}
}
}

Expand Down