Skip to content

Commit d8e5265

Browse files
bors[bot]popzxc
andauthored
Merge #5954
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 <[email protected]>
2 parents 40a028c + 4ebacf9 commit d8e5265

File tree

10 files changed

+67
-2
lines changed

10 files changed

+67
-2
lines changed

crates/rust-analyzer/src/config.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub struct Config {
3838
pub cargo: CargoConfig,
3939
pub rustfmt: RustfmtConfig,
4040
pub flycheck: Option<FlycheckConfig>,
41+
pub runnables: RunnablesConfig,
4142

4243
pub inlay_hints: InlayHintsConfig,
4344
pub completion: CompletionConfig,
@@ -124,6 +125,15 @@ pub enum RustfmtConfig {
124125
CustomCommand { command: String, args: Vec<String> },
125126
}
126127

128+
/// Configuration for runnable items, such as `main` function or tests.
129+
#[derive(Debug, Clone, Default)]
130+
pub struct RunnablesConfig {
131+
/// Custom command to be executed instead of `cargo` for runnables.
132+
pub override_cargo: Option<String>,
133+
/// Additional arguments for the `cargo`, e.g. `--release`.
134+
pub cargo_extra_args: Vec<String>,
135+
}
136+
127137
#[derive(Debug, Clone, Default)]
128138
pub struct ClientCapsConfig {
129139
pub location_link: bool,
@@ -164,6 +174,7 @@ impl Config {
164174
extra_args: Vec::new(),
165175
features: Vec::new(),
166176
}),
177+
runnables: RunnablesConfig::default(),
167178

168179
inlay_hints: InlayHintsConfig {
169180
type_hints: true,
@@ -220,6 +231,10 @@ impl Config {
220231
load_out_dirs_from_check: data.cargo_loadOutDirsFromCheck,
221232
target: data.cargo_target.clone(),
222233
};
234+
self.runnables = RunnablesConfig {
235+
override_cargo: data.runnables_overrideCargo,
236+
cargo_extra_args: data.runnables_cargoExtraArgs,
237+
};
223238

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

492+
runnables_overrideCargo: Option<String> = None,
493+
runnables_cargoExtraArgs: Vec<String> = Vec::new(),
494+
477495
rustfmt_extraArgs: Vec<String> = Vec::new(),
478496
rustfmt_overrideCommand: Option<Vec<String>> = None,
479497

crates/rust-analyzer/src/handlers.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ pub(crate) fn handle_runnables(
491491
}
492492

493493
// Add `cargo check` and `cargo test` for all targets of the whole package
494+
let config = &snap.config.runnables;
494495
match cargo_spec {
495496
Some(spec) => {
496497
for &cmd in ["check", "test"].iter() {
@@ -500,12 +501,14 @@ pub(crate) fn handle_runnables(
500501
kind: lsp_ext::RunnableKind::Cargo,
501502
args: lsp_ext::CargoRunnable {
502503
workspace_root: Some(spec.workspace_root.clone().into()),
504+
override_cargo: config.override_cargo.clone(),
503505
cargo_args: vec![
504506
cmd.to_string(),
505507
"--package".to_string(),
506508
spec.package.clone(),
507509
"--all-targets".to_string(),
508510
],
511+
cargo_extra_args: config.cargo_extra_args.clone(),
509512
executable_args: Vec::new(),
510513
expect_test: None,
511514
},
@@ -519,7 +522,9 @@ pub(crate) fn handle_runnables(
519522
kind: lsp_ext::RunnableKind::Cargo,
520523
args: lsp_ext::CargoRunnable {
521524
workspace_root: None,
525+
override_cargo: config.override_cargo.clone(),
522526
cargo_args: vec!["check".to_string(), "--workspace".to_string()],
527+
cargo_extra_args: config.cargo_extra_args.clone(),
523528
executable_args: Vec::new(),
524529
expect_test: None,
525530
},

crates/rust-analyzer/src/lsp_ext.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,14 @@ pub enum RunnableKind {
171171
#[derive(Deserialize, Serialize, Debug)]
172172
#[serde(rename_all = "camelCase")]
173173
pub struct CargoRunnable {
174+
// command to be executed instead of cargo
175+
pub override_cargo: Option<String>,
174176
#[serde(skip_serializing_if = "Option::is_none")]
175177
pub workspace_root: Option<PathBuf>,
176178
// command, --package and --lib stuff
177179
pub cargo_args: Vec<String>,
180+
// user-specified additional cargo args, like `--release`.
181+
pub cargo_extra_args: Vec<String>,
178182
// stuff after --
179183
pub executable_args: Vec<String>,
180184
#[serde(skip_serializing_if = "Option::is_none")]

crates/rust-analyzer/src/to_proto.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,7 @@ pub(crate) fn runnable(
740740
file_id: FileId,
741741
runnable: Runnable,
742742
) -> Result<lsp_ext::Runnable> {
743+
let config = &snap.config.runnables;
743744
let spec = CargoTargetSpec::for_file(snap, file_id)?;
744745
let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone());
745746
let target = spec.as_ref().map(|s| s.target.clone());
@@ -754,7 +755,9 @@ pub(crate) fn runnable(
754755
kind: lsp_ext::RunnableKind::Cargo,
755756
args: lsp_ext::CargoRunnable {
756757
workspace_root: workspace_root.map(|it| it.into()),
758+
override_cargo: config.override_cargo.clone(),
757759
cargo_args,
760+
cargo_extra_args: config.cargo_extra_args.clone(),
758761
executable_args,
759762
expect_test: None,
760763
},

crates/rust-analyzer/tests/rust-analyzer/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ fn main() {}
107107
"args": {
108108
"cargoArgs": ["test", "--package", "foo", "--test", "spam"],
109109
"executableArgs": ["test_eggs", "--exact", "--nocapture"],
110+
"cargoExtraArgs": [],
111+
"overrideCargo": null,
110112
"workspaceRoot": server.path().join("foo")
111113
},
112114
"kind": "cargo",
@@ -127,6 +129,8 @@ fn main() {}
127129
"args": {
128130
"cargoArgs": ["check", "--package", "foo", "--all-targets"],
129131
"executableArgs": [],
132+
"cargoExtraArgs": [],
133+
"overrideCargo": null,
130134
"workspaceRoot": server.path().join("foo")
131135
},
132136
"kind": "cargo",
@@ -136,6 +140,8 @@ fn main() {}
136140
"args": {
137141
"cargoArgs": ["test", "--package", "foo", "--all-targets"],
138142
"executableArgs": [],
143+
"cargoExtraArgs": [],
144+
"overrideCargo": null,
139145
"workspaceRoot": server.path().join("foo")
140146
},
141147
"kind": "cargo",

editors/code/package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,22 @@
651651
],
652652
"default": "full",
653653
"description": "The strategy to use when inserting new imports or merging imports."
654+
},
655+
"rust-analyzer.runnables.overrideCargo": {
656+
"type": [
657+
"null",
658+
"string"
659+
],
660+
"default": null,
661+
"description": "Command to be executed instead of 'cargo' for runnables."
662+
},
663+
"rust-analyzer.runnables.cargoExtraArgs": {
664+
"type": "array",
665+
"items": {
666+
"type": "string"
667+
},
668+
"default": [],
669+
"description": "Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be '--release'"
654670
}
655671
}
656672
},

editors/code/src/lsp_ext.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@ export interface Runnable {
6969
args: {
7070
workspaceRoot?: string;
7171
cargoArgs: string[];
72+
cargoExtraArgs: string[];
7273
executableArgs: string[];
7374
expectTest?: boolean;
75+
overrideCargo?: string;
7476
};
7577
}
7678
export const runnables = new lc.RequestType<RunnablesParams, Runnable[], void>("experimental/runnables");

editors/code/src/run.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise
129129
}
130130

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

144146
const target = vscode.workspace.workspaceFolders![0]; // safe, see main activate()

editors/code/src/tasks.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface CargoTaskDefinition extends vscode.TaskDefinition {
1313
args?: string[];
1414
cwd?: string;
1515
env?: { [key: string]: string };
16+
overrideCargo?: string;
1617
}
1718

1819
class CargoTaskProvider implements vscode.TaskProvider {
@@ -98,7 +99,14 @@ export async function buildCargoTask(
9899
}
99100

100101
if (!exec) {
101-
exec = new vscode.ShellExecution(toolchain.cargoPath(), args, definition);
102+
// Check whether we must use a user-defined substitute for cargo.
103+
const cargoCommand = definition.overrideCargo ? definition.overrideCargo : toolchain.cargoPath();
104+
105+
// Prepare the whole command as one line. It is required if user has provided override command which contains spaces,
106+
// for example "wrapper cargo". Without manual preparation the overridden command will be quoted and fail to execute.
107+
const fullCommand = [cargoCommand, ...args].join(" ");
108+
109+
exec = new vscode.ShellExecution(fullCommand, definition);
102110
}
103111

104112
return new vscode.Task(

editors/code/tests/unit/runnable_env.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ function makeRunnable(label: string): ra.Runnable {
99
kind: "cargo",
1010
args: {
1111
cargoArgs: [],
12-
executableArgs: []
12+
executableArgs: [],
13+
cargoExtraArgs: []
1314
}
1415
};
1516
}

0 commit comments

Comments
 (0)