Skip to content

Commit

Permalink
Merge #5954
Browse files Browse the repository at this point in the history
5954: Add flexible configuration for runnables r=popzxc a=popzxc

This PR introduces two new configuration options for runnables: `overrideCargo` and `cargoExtraArgs`.
These options are applied to all the "run" tasks of rust analyzer, such as binaries and tests.

Overall motivation is that rust-analyzer provides similar options, for example, for `rustfmt`, but not for runnables.

## `overrideCargo`

This option allows user to replace `cargo` command with something else (well, something that is compatible with the cargo arguments).

Motivation is that some projects may have wrappers around cargo (or even whole alternatives to cargo), which do something related to the project, and only then run `cargo`. With this feature, such users will be able to use lens and run tests directly from the IDE rather than from terminal.

![cargo_override](https://user-images.githubusercontent.com/12111581/92306622-2f404f80-ef99-11ea-9bb7-6c6192a2c54a.gif)

## `cargoExtraArgs`

This option allows user to add any additional arguments for `cargo`, such as `--release`.

It may be useful, for example, if project has big integration tests which take too long in debug mode, or if any other `cargo` flag has to be passed.

![cargo_extra_args](https://user-images.githubusercontent.com/12111581/92306658-821a0700-ef99-11ea-8be9-bf0aff78e154.gif)

Co-authored-by: Igor Aleksanov <popzxc@yandex.ru>
  • Loading branch information
bors[bot] and popzxc authored Oct 2, 2020
2 parents 40a028c + 4ebacf9 commit d8e5265
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 2 deletions.
18 changes: 18 additions & 0 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub struct Config {
pub cargo: CargoConfig,
pub rustfmt: RustfmtConfig,
pub flycheck: Option<FlycheckConfig>,
pub runnables: RunnablesConfig,

pub inlay_hints: InlayHintsConfig,
pub completion: CompletionConfig,
Expand Down Expand Up @@ -124,6 +125,15 @@ pub enum RustfmtConfig {
CustomCommand { command: String, args: Vec<String> },
}

/// Configuration for runnable items, such as `main` function or tests.
#[derive(Debug, Clone, Default)]
pub struct RunnablesConfig {
/// Custom command to be executed instead of `cargo` for runnables.
pub override_cargo: Option<String>,
/// Additional arguments for the `cargo`, e.g. `--release`.
pub cargo_extra_args: Vec<String>,
}

#[derive(Debug, Clone, Default)]
pub struct ClientCapsConfig {
pub location_link: bool,
Expand Down Expand Up @@ -164,6 +174,7 @@ impl Config {
extra_args: Vec::new(),
features: Vec::new(),
}),
runnables: RunnablesConfig::default(),

inlay_hints: InlayHintsConfig {
type_hints: true,
Expand Down Expand Up @@ -220,6 +231,10 @@ impl Config {
load_out_dirs_from_check: data.cargo_loadOutDirsFromCheck,
target: data.cargo_target.clone(),
};
self.runnables = RunnablesConfig {
override_cargo: data.runnables_overrideCargo,
cargo_extra_args: data.runnables_cargoExtraArgs,
};

self.proc_macro_srv = if data.procMacro_enable {
std::env::current_exe().ok().map(|path| (path, vec!["proc-macro".into()]))
Expand Down Expand Up @@ -474,6 +489,9 @@ config_data! {
notifications_cargoTomlNotFound: bool = true,
procMacro_enable: bool = false,

runnables_overrideCargo: Option<String> = None,
runnables_cargoExtraArgs: Vec<String> = Vec::new(),

rustfmt_extraArgs: Vec<String> = Vec::new(),
rustfmt_overrideCommand: Option<Vec<String>> = None,

Expand Down
5 changes: 5 additions & 0 deletions crates/rust-analyzer/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ pub(crate) fn handle_runnables(
}

// Add `cargo check` and `cargo test` for all targets of the whole package
let config = &snap.config.runnables;
match cargo_spec {
Some(spec) => {
for &cmd in ["check", "test"].iter() {
Expand All @@ -500,12 +501,14 @@ pub(crate) fn handle_runnables(
kind: lsp_ext::RunnableKind::Cargo,
args: lsp_ext::CargoRunnable {
workspace_root: Some(spec.workspace_root.clone().into()),
override_cargo: config.override_cargo.clone(),
cargo_args: vec![
cmd.to_string(),
"--package".to_string(),
spec.package.clone(),
"--all-targets".to_string(),
],
cargo_extra_args: config.cargo_extra_args.clone(),
executable_args: Vec::new(),
expect_test: None,
},
Expand All @@ -519,7 +522,9 @@ pub(crate) fn handle_runnables(
kind: lsp_ext::RunnableKind::Cargo,
args: lsp_ext::CargoRunnable {
workspace_root: None,
override_cargo: config.override_cargo.clone(),
cargo_args: vec!["check".to_string(), "--workspace".to_string()],
cargo_extra_args: config.cargo_extra_args.clone(),
executable_args: Vec::new(),
expect_test: None,
},
Expand Down
4 changes: 4 additions & 0 deletions crates/rust-analyzer/src/lsp_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,14 @@ pub enum RunnableKind {
#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct CargoRunnable {
// command to be executed instead of cargo
pub override_cargo: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace_root: Option<PathBuf>,
// command, --package and --lib stuff
pub cargo_args: Vec<String>,
// user-specified additional cargo args, like `--release`.
pub cargo_extra_args: Vec<String>,
// stuff after --
pub executable_args: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down
3 changes: 3 additions & 0 deletions crates/rust-analyzer/src/to_proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ pub(crate) fn runnable(
file_id: FileId,
runnable: Runnable,
) -> Result<lsp_ext::Runnable> {
let config = &snap.config.runnables;
let spec = CargoTargetSpec::for_file(snap, file_id)?;
let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone());
let target = spec.as_ref().map(|s| s.target.clone());
Expand All @@ -754,7 +755,9 @@ pub(crate) fn runnable(
kind: lsp_ext::RunnableKind::Cargo,
args: lsp_ext::CargoRunnable {
workspace_root: workspace_root.map(|it| it.into()),
override_cargo: config.override_cargo.clone(),
cargo_args,
cargo_extra_args: config.cargo_extra_args.clone(),
executable_args,
expect_test: None,
},
Expand Down
6 changes: 6 additions & 0 deletions crates/rust-analyzer/tests/rust-analyzer/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ fn main() {}
"args": {
"cargoArgs": ["test", "--package", "foo", "--test", "spam"],
"executableArgs": ["test_eggs", "--exact", "--nocapture"],
"cargoExtraArgs": [],
"overrideCargo": null,
"workspaceRoot": server.path().join("foo")
},
"kind": "cargo",
Expand All @@ -127,6 +129,8 @@ fn main() {}
"args": {
"cargoArgs": ["check", "--package", "foo", "--all-targets"],
"executableArgs": [],
"cargoExtraArgs": [],
"overrideCargo": null,
"workspaceRoot": server.path().join("foo")
},
"kind": "cargo",
Expand All @@ -136,6 +140,8 @@ fn main() {}
"args": {
"cargoArgs": ["test", "--package", "foo", "--all-targets"],
"executableArgs": [],
"cargoExtraArgs": [],
"overrideCargo": null,
"workspaceRoot": server.path().join("foo")
},
"kind": "cargo",
Expand Down
16 changes: 16 additions & 0 deletions editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,22 @@
],
"default": "full",
"description": "The strategy to use when inserting new imports or merging imports."
},
"rust-analyzer.runnables.overrideCargo": {
"type": [
"null",
"string"
],
"default": null,
"description": "Command to be executed instead of 'cargo' for runnables."
},
"rust-analyzer.runnables.cargoExtraArgs": {
"type": "array",
"items": {
"type": "string"
},
"default": [],
"description": "Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be '--release'"
}
}
},
Expand Down
2 changes: 2 additions & 0 deletions editors/code/src/lsp_ext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ export interface Runnable {
args: {
workspaceRoot?: string;
cargoArgs: string[];
cargoExtraArgs: string[];
executableArgs: string[];
expectTest?: boolean;
overrideCargo?: string;
};
}
export const runnables = new lc.RequestType<RunnablesParams, Runnable[], void>("experimental/runnables");
Expand Down
2 changes: 2 additions & 0 deletions editors/code/src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise
}

const args = [...runnable.args.cargoArgs]; // should be a copy!
args.push(...runnable.args.cargoExtraArgs); // Append user-specified cargo options.
if (runnable.args.executableArgs.length > 0) {
args.push('--', ...runnable.args.executableArgs);
}
Expand All @@ -139,6 +140,7 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise
args: args.slice(1),
cwd: runnable.args.workspaceRoot || ".",
env: prepareEnv(runnable, config.runnableEnv),
overrideCargo: runnable.args.overrideCargo,
};

const target = vscode.workspace.workspaceFolders![0]; // safe, see main activate()
Expand Down
10 changes: 9 additions & 1 deletion editors/code/src/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface CargoTaskDefinition extends vscode.TaskDefinition {
args?: string[];
cwd?: string;
env?: { [key: string]: string };
overrideCargo?: string;
}

class CargoTaskProvider implements vscode.TaskProvider {
Expand Down Expand Up @@ -98,7 +99,14 @@ export async function buildCargoTask(
}

if (!exec) {
exec = new vscode.ShellExecution(toolchain.cargoPath(), args, definition);
// Check whether we must use a user-defined substitute for cargo.
const cargoCommand = definition.overrideCargo ? definition.overrideCargo : toolchain.cargoPath();

// Prepare the whole command as one line. It is required if user has provided override command which contains spaces,
// for example "wrapper cargo". Without manual preparation the overridden command will be quoted and fail to execute.
const fullCommand = [cargoCommand, ...args].join(" ");

exec = new vscode.ShellExecution(fullCommand, definition);
}

return new vscode.Task(
Expand Down
3 changes: 2 additions & 1 deletion editors/code/tests/unit/runnable_env.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ function makeRunnable(label: string): ra.Runnable {
kind: "cargo",
args: {
cargoArgs: [],
executableArgs: []
executableArgs: [],
cargoExtraArgs: []
}
};
}
Expand Down

0 comments on commit d8e5265

Please sign in to comment.