diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/assists/src/utils/insert_use.rs | 133 | ||||
-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 |
6 files changed, 121 insertions, 48 deletions
diff --git a/crates/assists/src/utils/insert_use.rs b/crates/assists/src/utils/insert_use.rs index 8dd4fe607..f6025c99a 100644 --- a/crates/assists/src/utils/insert_use.rs +++ b/crates/assists/src/utils/insert_use.rs | |||
@@ -4,13 +4,14 @@ use std::{ | |||
4 | iter::{self, successors}, | 4 | iter::{self, successors}, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use ast::{ | 7 | use itertools::{EitherOrBoth, Itertools}; |
8 | edit::{AstNodeEdit, IndentLevel}, | ||
9 | PathSegmentKind, VisibilityOwner, | ||
10 | }; | ||
11 | use syntax::{ | 8 | use syntax::{ |
12 | algo, | 9 | algo, |
13 | ast::{self, make, AstNode}, | 10 | ast::{ |
11 | self, | ||
12 | edit::{AstNodeEdit, IndentLevel}, | ||
13 | make, AstNode, PathSegmentKind, VisibilityOwner, | ||
14 | }, | ||
14 | InsertPosition, SyntaxElement, SyntaxNode, | 15 | InsertPosition, SyntaxElement, SyntaxNode, |
15 | }; | 16 | }; |
16 | 17 | ||
@@ -193,13 +194,13 @@ fn recursive_merge( | |||
193 | false => None, | 194 | false => None, |
194 | }) | 195 | }) |
195 | .collect::<Option<Vec<_>>>()?; | 196 | .collect::<Option<Vec<_>>>()?; |
196 | use_trees.sort_unstable_by(|a, b| path_cmp_opt(a.path(), b.path())); | 197 | use_trees.sort_unstable_by(|a, b| path_cmp_for_sort(a.path(), b.path())); |
197 | for rhs_t in rhs.use_tree_list().into_iter().flat_map(|list| list.use_trees()) { | 198 | for rhs_t in rhs.use_tree_list().into_iter().flat_map(|list| list.use_trees()) { |
198 | if !merge.is_tree_allowed(&rhs_t) { | 199 | if !merge.is_tree_allowed(&rhs_t) { |
199 | return None; | 200 | return None; |
200 | } | 201 | } |
201 | let rhs_path = rhs_t.path(); | 202 | let rhs_path = rhs_t.path(); |
202 | match use_trees.binary_search_by(|p| path_cmp_opt(p.path(), rhs_path.clone())) { | 203 | match use_trees.binary_search_by(|p| path_cmp_bin_search(p.path(), rhs_path.clone())) { |
203 | Ok(idx) => { | 204 | Ok(idx) => { |
204 | let lhs_t = &mut use_trees[idx]; | 205 | let lhs_t = &mut use_trees[idx]; |
205 | let lhs_path = lhs_t.path()?; | 206 | let lhs_path = lhs_t.path()?; |
@@ -307,39 +308,77 @@ fn path_len(path: ast::Path) -> usize { | |||
307 | 308 | ||
308 | /// Orders paths in the following way: | 309 | /// Orders paths in the following way: |
309 | /// the sole self token comes first, after that come uppercase identifiers, then lowercase identifiers | 310 | /// the sole self token comes first, after that come uppercase identifiers, then lowercase identifiers |
310 | // FIXME: rustfmt sort lowercase idents before uppercase, in general we want to have the same ordering rustfmt has | 311 | // FIXME: rustfmt sorts lowercase idents before uppercase, in general we want to have the same ordering rustfmt has |
311 | // which is `self` and `super` first, then identifier imports with lowercase ones first, then glob imports and at last list imports. | 312 | // which is `self` and `super` first, then identifier imports with lowercase ones first, then glob imports and at last list imports. |
312 | // Example foo::{self, foo, baz, Baz, Qux, *, {Bar}} | 313 | // Example foo::{self, foo, baz, Baz, Qux, *, {Bar}} |
313 | fn path_cmp(a: &ast::Path, b: &ast::Path) -> Ordering { | 314 | fn path_cmp_for_sort(a: Option<ast::Path>, b: Option<ast::Path>) -> Ordering { |
314 | match (path_is_self(a), path_is_self(b)) { | 315 | match (a, b) { |
315 | (true, true) => Ordering::Equal, | 316 | (None, None) => Ordering::Equal, |
316 | (true, false) => Ordering::Less, | 317 | (None, Some(_)) => Ordering::Less, |
317 | (false, true) => Ordering::Greater, | 318 | (Some(_), None) => Ordering::Greater, |
318 | (false, false) => { | 319 | (Some(ref a), Some(ref b)) => match (path_is_self(a), path_is_self(b)) { |
319 | let a = segment_iter(a); | 320 | (true, true) => Ordering::Equal, |
320 | let b = segment_iter(b); | 321 | (true, false) => Ordering::Less, |
321 | // cmp_by would be useful for us here but that is currently unstable | 322 | (false, true) => Ordering::Greater, |
322 | // cmp doesnt work due the lifetimes on text's return type | 323 | (false, false) => path_cmp_short(a, b), |
323 | a.zip(b) | 324 | }, |
324 | .flat_map(|(seg, seg2)| seg.name_ref().zip(seg2.name_ref())) | ||
325 | .find_map(|(a, b)| match a.text().cmp(b.text()) { | ||
326 | ord @ Ordering::Greater | ord @ Ordering::Less => Some(ord), | ||
327 | Ordering::Equal => None, | ||
328 | }) | ||
329 | .unwrap_or(Ordering::Equal) | ||
330 | } | ||
331 | } | 325 | } |
332 | } | 326 | } |
333 | 327 | ||
334 | fn path_cmp_opt(a: Option<ast::Path>, b: Option<ast::Path>) -> Ordering { | 328 | /// Path comparison func for binary searching for merging. |
335 | match (a, b) { | 329 | fn path_cmp_bin_search(lhs: Option<ast::Path>, rhs: Option<ast::Path>) -> Ordering { |
330 | match (lhs, rhs) { | ||
336 | (None, None) => Ordering::Equal, | 331 | (None, None) => Ordering::Equal, |
337 | (None, Some(_)) => Ordering::Less, | 332 | (None, Some(_)) => Ordering::Less, |
338 | (Some(_), None) => Ordering::Greater, | 333 | (Some(_), None) => Ordering::Greater, |
339 | (Some(a), Some(b)) => path_cmp(&a, &b), | 334 | (Some(ref a), Some(ref b)) => path_cmp_short(a, b), |
340 | } | 335 | } |
341 | } | 336 | } |
342 | 337 | ||
338 | /// Short circuiting comparison, if both paths are equal until one of them ends they are considered | ||
339 | /// equal | ||
340 | fn path_cmp_short(a: &ast::Path, b: &ast::Path) -> Ordering { | ||
341 | let a = segment_iter(a); | ||
342 | let b = segment_iter(b); | ||
343 | // cmp_by would be useful for us here but that is currently unstable | ||
344 | // cmp doesnt work due the lifetimes on text's return type | ||
345 | a.zip(b) | ||
346 | .find_map(|(a, b)| match path_segment_cmp(&a, &b) { | ||
347 | Ordering::Equal => None, | ||
348 | ord => Some(ord), | ||
349 | }) | ||
350 | .unwrap_or(Ordering::Equal) | ||
351 | } | ||
352 | |||
353 | /// Compares to paths, if one ends earlier than the other the has_tl parameters decide which is | ||
354 | /// greater as a a path that has a tree list should be greater, while one that just ends without | ||
355 | /// a tree list should be considered less. | ||
356 | fn use_tree_path_cmp(a: &ast::Path, a_has_tl: bool, b: &ast::Path, b_has_tl: bool) -> Ordering { | ||
357 | let a_segments = segment_iter(a); | ||
358 | let b_segments = segment_iter(b); | ||
359 | // cmp_by would be useful for us here but that is currently unstable | ||
360 | // cmp doesnt work due the lifetimes on text's return type | ||
361 | a_segments | ||
362 | .zip_longest(b_segments) | ||
363 | .find_map(|zipped| match zipped { | ||
364 | EitherOrBoth::Both(ref a, ref b) => match path_segment_cmp(a, b) { | ||
365 | Ordering::Equal => None, | ||
366 | ord => Some(ord), | ||
367 | }, | ||
368 | EitherOrBoth::Left(_) if !b_has_tl => Some(Ordering::Greater), | ||
369 | EitherOrBoth::Left(_) => Some(Ordering::Less), | ||
370 | EitherOrBoth::Right(_) if !a_has_tl => Some(Ordering::Less), | ||
371 | EitherOrBoth::Right(_) => Some(Ordering::Greater), | ||
372 | }) | ||
373 | .unwrap_or(Ordering::Equal) | ||
374 | } | ||
375 | |||
376 | fn path_segment_cmp(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { | ||
377 | let a = a.name_ref(); | ||
378 | let b = b.name_ref(); | ||
379 | a.as_ref().map(ast::NameRef::text).cmp(&b.as_ref().map(ast::NameRef::text)) | ||
380 | } | ||
381 | |||
343 | /// What type of merges are allowed. | 382 | /// What type of merges are allowed. |
344 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | 383 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
345 | pub enum MergeBehaviour { | 384 | pub enum MergeBehaviour { |
@@ -389,7 +428,6 @@ impl ImportGroup { | |||
389 | PathSegmentKind::Name(name) => match name.text().as_str() { | 428 | PathSegmentKind::Name(name) => match name.text().as_str() { |
390 | "std" => ImportGroup::Std, | 429 | "std" => ImportGroup::Std, |
391 | "core" => ImportGroup::Std, | 430 | "core" => ImportGroup::Std, |
392 | // FIXME: can be ThisModule as well | ||
393 | _ => ImportGroup::ExternCrate, | 431 | _ => ImportGroup::ExternCrate, |
394 | }, | 432 | }, |
395 | PathSegmentKind::Type { .. } => unreachable!(), | 433 | PathSegmentKind::Type { .. } => unreachable!(), |
@@ -415,30 +453,30 @@ fn find_insert_position( | |||
415 | .as_syntax_node() | 453 | .as_syntax_node() |
416 | .children() | 454 | .children() |
417 | .filter_map(|node| ast::Use::cast(node.clone()).zip(Some(node))) | 455 | .filter_map(|node| ast::Use::cast(node.clone()).zip(Some(node))) |
418 | .flat_map(|(use_, node)| use_.use_tree().and_then(|tree| tree.path()).zip(Some(node))); | 456 | .flat_map(|(use_, node)| { |
457 | let tree = use_.use_tree()?; | ||
458 | let path = tree.path()?; | ||
459 | let has_tl = tree.use_tree_list().is_some(); | ||
460 | Some((path, has_tl, node)) | ||
461 | }); | ||
419 | // Iterator that discards anything thats not in the required grouping | 462 | // Iterator that discards anything thats not in the required grouping |
420 | // This implementation allows the user to rearrange their import groups as this only takes the first group that fits | 463 | // This implementation allows the user to rearrange their import groups as this only takes the first group that fits |
421 | let group_iter = path_node_iter | 464 | let group_iter = path_node_iter |
422 | .clone() | 465 | .clone() |
423 | .skip_while(|(path, _)| ImportGroup::new(path) != group) | 466 | .skip_while(|(path, ..)| ImportGroup::new(path) != group) |
424 | .take_while(|(path, _)| ImportGroup::new(path) == group); | 467 | .take_while(|(path, ..)| ImportGroup::new(path) == group); |
425 | 468 | ||
426 | let segments = segment_iter(&insert_path); | ||
427 | // track the last element we iterated over, if this is still None after the iteration then that means we never iterated in the first place | 469 | // track the last element we iterated over, if this is still None after the iteration then that means we never iterated in the first place |
428 | let mut last = None; | 470 | let mut last = None; |
429 | // find the element that would come directly after our new import | 471 | // find the element that would come directly after our new import |
430 | let post_insert = | 472 | let post_insert = group_iter.inspect(|(.., node)| last = Some(node.clone())).find( |
431 | group_iter.inspect(|(_, node)| last = Some(node.clone())).find(|(path, _)| { | 473 | |&(ref path, has_tl, _)| { |
432 | let check_segments = segment_iter(&path); | 474 | use_tree_path_cmp(&insert_path, false, path, has_tl) != Ordering::Greater |
433 | segments | 475 | }, |
434 | .clone() | 476 | ); |
435 | .zip(check_segments) | ||
436 | .flat_map(|(seg, seg2)| seg.name_ref().zip(seg2.name_ref())) | ||
437 | .all(|(l, r)| l.text() <= r.text()) | ||
438 | }); | ||
439 | match post_insert { | 477 | match post_insert { |
440 | // insert our import before that element | 478 | // insert our import before that element |
441 | Some((_, node)) => (InsertPosition::Before(node.into()), AddBlankLine::After), | 479 | Some((.., node)) => (InsertPosition::Before(node.into()), AddBlankLine::After), |
442 | // there is no element after our new import, so append it to the end of the group | 480 | // there is no element after our new import, so append it to the end of the group |
443 | None => match last { | 481 | None => match last { |
444 | Some(node) => (InsertPosition::After(node.into()), AddBlankLine::Before), | 482 | Some(node) => (InsertPosition::After(node.into()), AddBlankLine::Before), |
@@ -448,10 +486,10 @@ fn find_insert_position( | |||
448 | let mut last = None; | 486 | let mut last = None; |
449 | // find the group that comes after where we want to insert | 487 | // find the group that comes after where we want to insert |
450 | let post_group = path_node_iter | 488 | let post_group = path_node_iter |
451 | .inspect(|(_, node)| last = Some(node.clone())) | 489 | .inspect(|(.., node)| last = Some(node.clone())) |
452 | .find(|(p, _)| ImportGroup::new(p) > group); | 490 | .find(|(p, ..)| ImportGroup::new(p) > group); |
453 | match post_group { | 491 | match post_group { |
454 | Some((_, node)) => { | 492 | Some((.., node)) => { |
455 | (InsertPosition::Before(node.into()), AddBlankLine::AfterTwice) | 493 | (InsertPosition::Before(node.into()), AddBlankLine::AfterTwice) |
456 | } | 494 | } |
457 | // there is no such group, so append after the last one | 495 | // there is no such group, so append after the last one |
@@ -844,7 +882,6 @@ use foo::bar::baz::Qux;", | |||
844 | } | 882 | } |
845 | 883 | ||
846 | #[test] | 884 | #[test] |
847 | #[ignore] // FIXME: Order changes when switching lhs and rhs | ||
848 | fn skip_merge_last_too_long2() { | 885 | fn skip_merge_last_too_long2() { |
849 | check_last( | 886 | check_last( |
850 | "foo::bar::baz::Qux", | 887 | "foo::bar::baz::Qux", |
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", |