diff options
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 18 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 5 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_ext.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 3 | ||||
-rw-r--r-- | crates/rust-analyzer/tests/rust-analyzer/main.rs | 6 | ||||
-rw-r--r-- | editors/code/package.json | 16 | ||||
-rw-r--r-- | editors/code/src/lsp_ext.ts | 2 | ||||
-rw-r--r-- | editors/code/src/run.ts | 2 | ||||
-rw-r--r-- | editors/code/src/tasks.ts | 10 | ||||
-rw-r--r-- | editors/code/tests/unit/runnable_env.test.ts | 3 |
10 files changed, 67 insertions, 2 deletions
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 42e1ad376..0ab4c37bf 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -38,6 +38,7 @@ pub struct Config { | |||
38 | pub cargo: CargoConfig, | 38 | pub cargo: CargoConfig, |
39 | pub rustfmt: RustfmtConfig, | 39 | pub rustfmt: RustfmtConfig, |
40 | pub flycheck: Option<FlycheckConfig>, | 40 | pub flycheck: Option<FlycheckConfig>, |
41 | pub runnables: RunnablesConfig, | ||
41 | 42 | ||
42 | pub inlay_hints: InlayHintsConfig, | 43 | pub inlay_hints: InlayHintsConfig, |
43 | pub completion: CompletionConfig, | 44 | pub completion: CompletionConfig, |
@@ -124,6 +125,15 @@ pub enum RustfmtConfig { | |||
124 | CustomCommand { command: String, args: Vec<String> }, | 125 | CustomCommand { command: String, args: Vec<String> }, |
125 | } | 126 | } |
126 | 127 | ||
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 | |||
127 | #[derive(Debug, Clone, Default)] | 137 | #[derive(Debug, Clone, Default)] |
128 | pub struct ClientCapsConfig { | 138 | pub struct ClientCapsConfig { |
129 | pub location_link: bool, | 139 | pub location_link: bool, |
@@ -164,6 +174,7 @@ impl Config { | |||
164 | extra_args: Vec::new(), | 174 | extra_args: Vec::new(), |
165 | features: Vec::new(), | 175 | features: Vec::new(), |
166 | }), | 176 | }), |
177 | runnables: RunnablesConfig::default(), | ||
167 | 178 | ||
168 | inlay_hints: InlayHintsConfig { | 179 | inlay_hints: InlayHintsConfig { |
169 | type_hints: true, | 180 | type_hints: true, |
@@ -220,6 +231,10 @@ impl Config { | |||
220 | load_out_dirs_from_check: data.cargo_loadOutDirsFromCheck, | 231 | load_out_dirs_from_check: data.cargo_loadOutDirsFromCheck, |
221 | target: data.cargo_target.clone(), | 232 | target: data.cargo_target.clone(), |
222 | }; | 233 | }; |
234 | self.runnables = RunnablesConfig { | ||
235 | override_cargo: data.runnables_overrideCargo, | ||
236 | cargo_extra_args: data.runnables_cargoExtraArgs, | ||
237 | }; | ||
223 | 238 | ||
224 | self.proc_macro_srv = if data.procMacro_enable { | 239 | self.proc_macro_srv = if data.procMacro_enable { |
225 | std::env::current_exe().ok().map(|path| (path, vec!["proc-macro".into()])) | 240 | std::env::current_exe().ok().map(|path| (path, vec!["proc-macro".into()])) |
@@ -474,6 +489,9 @@ config_data! { | |||
474 | notifications_cargoTomlNotFound: bool = true, | 489 | notifications_cargoTomlNotFound: bool = true, |
475 | procMacro_enable: bool = false, | 490 | procMacro_enable: bool = false, |
476 | 491 | ||
492 | runnables_overrideCargo: Option<String> = None, | ||
493 | runnables_cargoExtraArgs: Vec<String> = Vec::new(), | ||
494 | |||
477 | rustfmt_extraArgs: Vec<String> = Vec::new(), | 495 | rustfmt_extraArgs: Vec<String> = Vec::new(), |
478 | rustfmt_overrideCommand: Option<Vec<String>> = None, | 496 | rustfmt_overrideCommand: Option<Vec<String>> = None, |
479 | 497 | ||
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index afcec63ad..e970abb7c 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -491,6 +491,7 @@ pub(crate) fn handle_runnables( | |||
491 | } | 491 | } |
492 | 492 | ||
493 | // Add `cargo check` and `cargo test` for all targets of the whole package | 493 | // Add `cargo check` and `cargo test` for all targets of the whole package |
494 | let config = &snap.config.runnables; | ||
494 | match cargo_spec { | 495 | match cargo_spec { |
495 | Some(spec) => { | 496 | Some(spec) => { |
496 | for &cmd in ["check", "test"].iter() { | 497 | for &cmd in ["check", "test"].iter() { |
@@ -500,12 +501,14 @@ pub(crate) fn handle_runnables( | |||
500 | kind: lsp_ext::RunnableKind::Cargo, | 501 | kind: lsp_ext::RunnableKind::Cargo, |
501 | args: lsp_ext::CargoRunnable { | 502 | args: lsp_ext::CargoRunnable { |
502 | workspace_root: Some(spec.workspace_root.clone().into()), | 503 | workspace_root: Some(spec.workspace_root.clone().into()), |
504 | override_cargo: config.override_cargo.clone(), | ||
503 | cargo_args: vec![ | 505 | cargo_args: vec![ |
504 | cmd.to_string(), | 506 | cmd.to_string(), |
505 | "--package".to_string(), | 507 | "--package".to_string(), |
506 | spec.package.clone(), | 508 | spec.package.clone(), |
507 | "--all-targets".to_string(), | 509 | "--all-targets".to_string(), |
508 | ], | 510 | ], |
511 | cargo_extra_args: config.cargo_extra_args.clone(), | ||
509 | executable_args: Vec::new(), | 512 | executable_args: Vec::new(), |
510 | expect_test: None, | 513 | expect_test: None, |
511 | }, | 514 | }, |
@@ -519,7 +522,9 @@ pub(crate) fn handle_runnables( | |||
519 | kind: lsp_ext::RunnableKind::Cargo, | 522 | kind: lsp_ext::RunnableKind::Cargo, |
520 | args: lsp_ext::CargoRunnable { | 523 | args: lsp_ext::CargoRunnable { |
521 | workspace_root: None, | 524 | workspace_root: None, |
525 | override_cargo: config.override_cargo.clone(), | ||
522 | cargo_args: vec!["check".to_string(), "--workspace".to_string()], | 526 | cargo_args: vec!["check".to_string(), "--workspace".to_string()], |
527 | cargo_extra_args: config.cargo_extra_args.clone(), | ||
523 | executable_args: Vec::new(), | 528 | executable_args: Vec::new(), |
524 | expect_test: None, | 529 | expect_test: None, |
525 | }, | 530 | }, |
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 43ff191da..fee0bb69c 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs | |||
@@ -171,10 +171,14 @@ pub enum RunnableKind { | |||
171 | #[derive(Deserialize, Serialize, Debug)] | 171 | #[derive(Deserialize, Serialize, Debug)] |
172 | #[serde(rename_all = "camelCase")] | 172 | #[serde(rename_all = "camelCase")] |
173 | pub struct CargoRunnable { | 173 | pub struct CargoRunnable { |
174 | // command to be executed instead of cargo | ||
175 | pub override_cargo: Option<String>, | ||
174 | #[serde(skip_serializing_if = "Option::is_none")] | 176 | #[serde(skip_serializing_if = "Option::is_none")] |
175 | pub workspace_root: Option<PathBuf>, | 177 | pub workspace_root: Option<PathBuf>, |
176 | // command, --package and --lib stuff | 178 | // command, --package and --lib stuff |
177 | pub cargo_args: Vec<String>, | 179 | pub cargo_args: Vec<String>, |
180 | // user-specified additional cargo args, like `--release`. | ||
181 | pub cargo_extra_args: Vec<String>, | ||
178 | // stuff after -- | 182 | // stuff after -- |
179 | pub executable_args: Vec<String>, | 183 | pub executable_args: Vec<String>, |
180 | #[serde(skip_serializing_if = "Option::is_none")] | 184 | #[serde(skip_serializing_if = "Option::is_none")] |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 59e780b7d..aeacde0f7 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -740,6 +740,7 @@ pub(crate) fn runnable( | |||
740 | file_id: FileId, | 740 | file_id: FileId, |
741 | runnable: Runnable, | 741 | runnable: Runnable, |
742 | ) -> Result<lsp_ext::Runnable> { | 742 | ) -> Result<lsp_ext::Runnable> { |
743 | let config = &snap.config.runnables; | ||
743 | let spec = CargoTargetSpec::for_file(snap, file_id)?; | 744 | let spec = CargoTargetSpec::for_file(snap, file_id)?; |
744 | let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone()); | 745 | let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone()); |
745 | let target = spec.as_ref().map(|s| s.target.clone()); | 746 | let target = spec.as_ref().map(|s| s.target.clone()); |
@@ -754,7 +755,9 @@ pub(crate) fn runnable( | |||
754 | kind: lsp_ext::RunnableKind::Cargo, | 755 | kind: lsp_ext::RunnableKind::Cargo, |
755 | args: lsp_ext::CargoRunnable { | 756 | args: lsp_ext::CargoRunnable { |
756 | workspace_root: workspace_root.map(|it| it.into()), | 757 | workspace_root: workspace_root.map(|it| it.into()), |
758 | override_cargo: config.override_cargo.clone(), | ||
757 | cargo_args, | 759 | cargo_args, |
760 | cargo_extra_args: config.cargo_extra_args.clone(), | ||
758 | executable_args, | 761 | executable_args, |
759 | expect_test: None, | 762 | expect_test: None, |
760 | }, | 763 | }, |
diff --git a/crates/rust-analyzer/tests/rust-analyzer/main.rs b/crates/rust-analyzer/tests/rust-analyzer/main.rs index 06726f957..e51eb2626 100644 --- a/crates/rust-analyzer/tests/rust-analyzer/main.rs +++ b/crates/rust-analyzer/tests/rust-analyzer/main.rs | |||
@@ -107,6 +107,8 @@ fn main() {} | |||
107 | "args": { | 107 | "args": { |
108 | "cargoArgs": ["test", "--package", "foo", "--test", "spam"], | 108 | "cargoArgs": ["test", "--package", "foo", "--test", "spam"], |
109 | "executableArgs": ["test_eggs", "--exact", "--nocapture"], | 109 | "executableArgs": ["test_eggs", "--exact", "--nocapture"], |
110 | "cargoExtraArgs": [], | ||
111 | "overrideCargo": null, | ||
110 | "workspaceRoot": server.path().join("foo") | 112 | "workspaceRoot": server.path().join("foo") |
111 | }, | 113 | }, |
112 | "kind": "cargo", | 114 | "kind": "cargo", |
@@ -127,6 +129,8 @@ fn main() {} | |||
127 | "args": { | 129 | "args": { |
128 | "cargoArgs": ["check", "--package", "foo", "--all-targets"], | 130 | "cargoArgs": ["check", "--package", "foo", "--all-targets"], |
129 | "executableArgs": [], | 131 | "executableArgs": [], |
132 | "cargoExtraArgs": [], | ||
133 | "overrideCargo": null, | ||
130 | "workspaceRoot": server.path().join("foo") | 134 | "workspaceRoot": server.path().join("foo") |
131 | }, | 135 | }, |
132 | "kind": "cargo", | 136 | "kind": "cargo", |
@@ -136,6 +140,8 @@ fn main() {} | |||
136 | "args": { | 140 | "args": { |
137 | "cargoArgs": ["test", "--package", "foo", "--all-targets"], | 141 | "cargoArgs": ["test", "--package", "foo", "--all-targets"], |
138 | "executableArgs": [], | 142 | "executableArgs": [], |
143 | "cargoExtraArgs": [], | ||
144 | "overrideCargo": null, | ||
139 | "workspaceRoot": server.path().join("foo") | 145 | "workspaceRoot": server.path().join("foo") |
140 | }, | 146 | }, |
141 | "kind": "cargo", | 147 | "kind": "cargo", |
diff --git a/editors/code/package.json b/editors/code/package.json index bdd8a0c29..cc2ac3bd2 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -651,6 +651,22 @@ | |||
651 | ], | 651 | ], |
652 | "default": "full", | 652 | "default": "full", |
653 | "description": "The strategy to use when inserting new imports or merging imports." | 653 | "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'" | ||
654 | } | 670 | } |
655 | } | 671 | } |
656 | }, | 672 | }, |
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts index eb422d3e7..f286b68a6 100644 --- a/editors/code/src/lsp_ext.ts +++ b/editors/code/src/lsp_ext.ts | |||
@@ -69,8 +69,10 @@ export interface Runnable { | |||
69 | args: { | 69 | args: { |
70 | workspaceRoot?: string; | 70 | workspaceRoot?: string; |
71 | cargoArgs: string[]; | 71 | cargoArgs: string[]; |
72 | cargoExtraArgs: string[]; | ||
72 | executableArgs: string[]; | 73 | executableArgs: string[]; |
73 | expectTest?: boolean; | 74 | expectTest?: boolean; |
75 | overrideCargo?: string; | ||
74 | }; | 76 | }; |
75 | } | 77 | } |
76 | export const runnables = new lc.RequestType<RunnablesParams, Runnable[], void>("experimental/runnables"); | 78 | export const runnables = new lc.RequestType<RunnablesParams, Runnable[], void>("experimental/runnables"); |
diff --git a/editors/code/src/run.ts b/editors/code/src/run.ts index de68f27ae..459b7f250 100644 --- a/editors/code/src/run.ts +++ b/editors/code/src/run.ts | |||
@@ -129,6 +129,7 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise | |||
129 | } | 129 | } |
130 | 130 | ||
131 | const args = [...runnable.args.cargoArgs]; // should be a copy! | 131 | const args = [...runnable.args.cargoArgs]; // should be a copy! |
132 | args.push(...runnable.args.cargoExtraArgs); // Append user-specified cargo options. | ||
132 | if (runnable.args.executableArgs.length > 0) { | 133 | if (runnable.args.executableArgs.length > 0) { |
133 | args.push('--', ...runnable.args.executableArgs); | 134 | args.push('--', ...runnable.args.executableArgs); |
134 | } | 135 | } |
@@ -139,6 +140,7 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise | |||
139 | args: args.slice(1), | 140 | args: args.slice(1), |
140 | cwd: runnable.args.workspaceRoot || ".", | 141 | cwd: runnable.args.workspaceRoot || ".", |
141 | env: prepareEnv(runnable, config.runnableEnv), | 142 | env: prepareEnv(runnable, config.runnableEnv), |
143 | overrideCargo: runnable.args.overrideCargo, | ||
142 | }; | 144 | }; |
143 | 145 | ||
144 | const target = vscode.workspace.workspaceFolders![0]; // safe, see main activate() | 146 | const target = vscode.workspace.workspaceFolders![0]; // safe, see main activate() |
diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts index 14abbd5b7..a3ff15102 100644 --- a/editors/code/src/tasks.ts +++ b/editors/code/src/tasks.ts | |||
@@ -13,6 +13,7 @@ export interface CargoTaskDefinition extends vscode.TaskDefinition { | |||
13 | args?: string[]; | 13 | args?: string[]; |
14 | cwd?: string; | 14 | cwd?: string; |
15 | env?: { [key: string]: string }; | 15 | env?: { [key: string]: string }; |
16 | overrideCargo?: string; | ||
16 | } | 17 | } |
17 | 18 | ||
18 | class CargoTaskProvider implements vscode.TaskProvider { | 19 | class CargoTaskProvider implements vscode.TaskProvider { |
@@ -98,7 +99,14 @@ export async function buildCargoTask( | |||
98 | } | 99 | } |
99 | 100 | ||
100 | if (!exec) { | 101 | 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); | ||
102 | } | 110 | } |
103 | 111 | ||
104 | return new vscode.Task( | 112 | return new vscode.Task( |
diff --git a/editors/code/tests/unit/runnable_env.test.ts b/editors/code/tests/unit/runnable_env.test.ts index f2f53e91a..c5600cf64 100644 --- a/editors/code/tests/unit/runnable_env.test.ts +++ b/editors/code/tests/unit/runnable_env.test.ts | |||
@@ -9,7 +9,8 @@ function makeRunnable(label: string): ra.Runnable { | |||
9 | kind: "cargo", | 9 | kind: "cargo", |
10 | args: { | 10 | args: { |
11 | cargoArgs: [], | 11 | cargoArgs: [], |
12 | executableArgs: [] | 12 | executableArgs: [], |
13 | cargoExtraArgs: [] | ||
13 | } | 14 | } |
14 | }; | 15 | }; |
15 | } | 16 | } |