diff options
Diffstat (limited to 'crates/ide_db/src')
-rw-r--r-- | crates/ide_db/src/helpers/insert_use.rs | 17 | ||||
-rw-r--r-- | crates/ide_db/src/helpers/insert_use/tests.rs | 23 |
2 files changed, 39 insertions, 1 deletions
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs index 498d76f72..a43504a27 100644 --- a/crates/ide_db/src/helpers/insert_use.rs +++ b/crates/ide_db/src/helpers/insert_use.rs | |||
@@ -38,13 +38,18 @@ impl ImportScope { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | /// Determines the containing syntax node in which to insert a `use` statement affecting `position`. | 40 | /// Determines the containing syntax node in which to insert a `use` statement affecting `position`. |
41 | pub fn find_insert_use_container( | 41 | pub fn find_insert_use_container_with_macros( |
42 | position: &SyntaxNode, | 42 | position: &SyntaxNode, |
43 | sema: &Semantics<'_, RootDatabase>, | 43 | sema: &Semantics<'_, RootDatabase>, |
44 | ) -> Option<Self> { | 44 | ) -> Option<Self> { |
45 | sema.ancestors_with_macros(position.clone()).find_map(Self::from) | 45 | sema.ancestors_with_macros(position.clone()).find_map(Self::from) |
46 | } | 46 | } |
47 | 47 | ||
48 | /// Determines the containing syntax node in which to insert a `use` statement affecting `position`. | ||
49 | pub fn find_insert_use_container(position: &SyntaxNode) -> Option<Self> { | ||
50 | std::iter::successors(Some(position.clone()), SyntaxNode::parent).find_map(Self::from) | ||
51 | } | ||
52 | |||
48 | pub fn as_syntax_node(&self) -> &SyntaxNode { | 53 | pub fn as_syntax_node(&self) -> &SyntaxNode { |
49 | match self { | 54 | match self { |
50 | ImportScope::File(file) => file.syntax(), | 55 | ImportScope::File(file) => file.syntax(), |
@@ -446,8 +451,10 @@ fn insert_use_( | |||
446 | 451 | ||
447 | if !group_imports { | 452 | if !group_imports { |
448 | if let Some((_, _, node)) = path_node_iter.last() { | 453 | if let Some((_, _, node)) = path_node_iter.last() { |
454 | cov_mark::hit!(insert_no_grouping_last); | ||
449 | ted::insert(ted::Position::after(node), use_item.syntax()); | 455 | ted::insert(ted::Position::after(node), use_item.syntax()); |
450 | } else { | 456 | } else { |
457 | cov_mark::hit!(insert_no_grouping_last2); | ||
451 | ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line()); | 458 | ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line()); |
452 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()); | 459 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()); |
453 | } | 460 | } |
@@ -471,10 +478,12 @@ fn insert_use_( | |||
471 | }); | 478 | }); |
472 | 479 | ||
473 | if let Some((.., node)) = post_insert { | 480 | if let Some((.., node)) = post_insert { |
481 | cov_mark::hit!(insert_group); | ||
474 | // insert our import before that element | 482 | // insert our import before that element |
475 | return ted::insert(ted::Position::before(node), use_item.syntax()); | 483 | return ted::insert(ted::Position::before(node), use_item.syntax()); |
476 | } | 484 | } |
477 | if let Some(node) = last { | 485 | if let Some(node) = last { |
486 | cov_mark::hit!(insert_group_last); | ||
478 | // there is no element after our new import, so append it to the end of the group | 487 | // there is no element after our new import, so append it to the end of the group |
479 | return ted::insert(ted::Position::after(node), use_item.syntax()); | 488 | return ted::insert(ted::Position::after(node), use_item.syntax()); |
480 | } | 489 | } |
@@ -487,6 +496,7 @@ fn insert_use_( | |||
487 | .inspect(|(.., node)| last = Some(node.clone())) | 496 | .inspect(|(.., node)| last = Some(node.clone())) |
488 | .find(|(p, ..)| ImportGroup::new(p) > group); | 497 | .find(|(p, ..)| ImportGroup::new(p) > group); |
489 | if let Some((.., node)) = post_group { | 498 | if let Some((.., node)) = post_group { |
499 | cov_mark::hit!(insert_group_new_group); | ||
490 | ted::insert(ted::Position::before(&node), use_item.syntax()); | 500 | ted::insert(ted::Position::before(&node), use_item.syntax()); |
491 | if let Some(node) = algo::non_trivia_sibling(node.into(), Direction::Prev) { | 501 | if let Some(node) = algo::non_trivia_sibling(node.into(), Direction::Prev) { |
492 | ted::insert(ted::Position::after(node), make::tokens::single_newline()); | 502 | ted::insert(ted::Position::after(node), make::tokens::single_newline()); |
@@ -495,6 +505,7 @@ fn insert_use_( | |||
495 | } | 505 | } |
496 | // there is no such group, so append after the last one | 506 | // there is no such group, so append after the last one |
497 | if let Some(node) = last { | 507 | if let Some(node) = last { |
508 | cov_mark::hit!(insert_group_no_group); | ||
498 | ted::insert(ted::Position::after(&node), use_item.syntax()); | 509 | ted::insert(ted::Position::after(&node), use_item.syntax()); |
499 | ted::insert(ted::Position::after(node), make::tokens::single_newline()); | 510 | ted::insert(ted::Position::after(node), make::tokens::single_newline()); |
500 | return; | 511 | return; |
@@ -508,22 +519,26 @@ fn insert_use_( | |||
508 | }) | 519 | }) |
509 | .last() | 520 | .last() |
510 | { | 521 | { |
522 | cov_mark::hit!(insert_group_empty_inner_attr); | ||
511 | ted::insert(ted::Position::after(&last_inner_element), use_item.syntax()); | 523 | ted::insert(ted::Position::after(&last_inner_element), use_item.syntax()); |
512 | ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline()); | 524 | ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline()); |
513 | return; | 525 | return; |
514 | } | 526 | } |
515 | match scope { | 527 | match scope { |
516 | ImportScope::File(_) => { | 528 | ImportScope::File(_) => { |
529 | cov_mark::hit!(insert_group_empty_file); | ||
517 | ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line()); | 530 | ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line()); |
518 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()) | 531 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()) |
519 | } | 532 | } |
520 | // don't insert the imports before the item list's opening curly brace | 533 | // don't insert the imports before the item list's opening curly brace |
521 | ImportScope::Module(item_list) => match item_list.l_curly_token() { | 534 | ImportScope::Module(item_list) => match item_list.l_curly_token() { |
522 | Some(b) => { | 535 | Some(b) => { |
536 | cov_mark::hit!(insert_group_empty_module); | ||
523 | ted::insert(ted::Position::after(&b), make::tokens::single_newline()); | 537 | ted::insert(ted::Position::after(&b), make::tokens::single_newline()); |
524 | ted::insert(ted::Position::after(&b), use_item.syntax()); | 538 | ted::insert(ted::Position::after(&b), use_item.syntax()); |
525 | } | 539 | } |
526 | None => { | 540 | None => { |
541 | // This should never happens, broken module syntax node | ||
527 | ted::insert( | 542 | ted::insert( |
528 | ted::Position::first_child_of(scope_syntax), | 543 | ted::Position::first_child_of(scope_syntax), |
529 | make::tokens::blank_line(), | 544 | make::tokens::blank_line(), |
diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs index a3464d606..048c213e2 100644 --- a/crates/ide_db/src/helpers/insert_use/tests.rs +++ b/crates/ide_db/src/helpers/insert_use/tests.rs | |||
@@ -5,6 +5,7 @@ use test_utils::assert_eq_text; | |||
5 | 5 | ||
6 | #[test] | 6 | #[test] |
7 | fn insert_not_group() { | 7 | fn insert_not_group() { |
8 | cov_mark::check!(insert_no_grouping_last); | ||
8 | check( | 9 | check( |
9 | "use external_crate2::bar::A", | 10 | "use external_crate2::bar::A", |
10 | r" | 11 | r" |
@@ -27,6 +28,21 @@ use external_crate2::bar::A;", | |||
27 | } | 28 | } |
28 | 29 | ||
29 | #[test] | 30 | #[test] |
31 | fn insert_not_group_empty() { | ||
32 | cov_mark::check!(insert_no_grouping_last2); | ||
33 | check( | ||
34 | "use external_crate2::bar::A", | ||
35 | r"", | ||
36 | r"use external_crate2::bar::A; | ||
37 | |||
38 | ", | ||
39 | None, | ||
40 | false, | ||
41 | false, | ||
42 | ); | ||
43 | } | ||
44 | |||
45 | #[test] | ||
30 | fn insert_existing() { | 46 | fn insert_existing() { |
31 | check_full("std::fs", "use std::fs;", "use std::fs;") | 47 | check_full("std::fs", "use std::fs;", "use std::fs;") |
32 | } | 48 | } |
@@ -65,6 +81,7 @@ fn insert_start_indent() { | |||
65 | 81 | ||
66 | #[test] | 82 | #[test] |
67 | fn insert_middle() { | 83 | fn insert_middle() { |
84 | cov_mark::check!(insert_group); | ||
68 | check_none( | 85 | check_none( |
69 | "std::bar::EE", | 86 | "std::bar::EE", |
70 | r" | 87 | r" |
@@ -101,6 +118,7 @@ fn insert_middle_indent() { | |||
101 | 118 | ||
102 | #[test] | 119 | #[test] |
103 | fn insert_end() { | 120 | fn insert_end() { |
121 | cov_mark::check!(insert_group_last); | ||
104 | check_none( | 122 | check_none( |
105 | "std::bar::ZZ", | 123 | "std::bar::ZZ", |
106 | r" | 124 | r" |
@@ -199,6 +217,7 @@ fn insert_first_matching_group() { | |||
199 | 217 | ||
200 | #[test] | 218 | #[test] |
201 | fn insert_missing_group_std() { | 219 | fn insert_missing_group_std() { |
220 | cov_mark::check!(insert_group_new_group); | ||
202 | check_none( | 221 | check_none( |
203 | "std::fmt", | 222 | "std::fmt", |
204 | r" | 223 | r" |
@@ -214,6 +233,7 @@ fn insert_missing_group_std() { | |||
214 | 233 | ||
215 | #[test] | 234 | #[test] |
216 | fn insert_missing_group_self() { | 235 | fn insert_missing_group_self() { |
236 | cov_mark::check!(insert_group_no_group); | ||
217 | check_none( | 237 | check_none( |
218 | "self::fmt", | 238 | "self::fmt", |
219 | r" | 239 | r" |
@@ -240,6 +260,7 @@ fn main() {}", | |||
240 | 260 | ||
241 | #[test] | 261 | #[test] |
242 | fn insert_empty_file() { | 262 | fn insert_empty_file() { |
263 | cov_mark::check!(insert_group_empty_file); | ||
243 | // empty files will get two trailing newlines | 264 | // empty files will get two trailing newlines |
244 | // this is due to the test case insert_no_imports above | 265 | // this is due to the test case insert_no_imports above |
245 | check_full( | 266 | check_full( |
@@ -253,6 +274,7 @@ fn insert_empty_file() { | |||
253 | 274 | ||
254 | #[test] | 275 | #[test] |
255 | fn insert_empty_module() { | 276 | fn insert_empty_module() { |
277 | cov_mark::check!(insert_group_empty_module); | ||
256 | check( | 278 | check( |
257 | "foo::bar", | 279 | "foo::bar", |
258 | "mod x {}", | 280 | "mod x {}", |
@@ -267,6 +289,7 @@ fn insert_empty_module() { | |||
267 | 289 | ||
268 | #[test] | 290 | #[test] |
269 | fn insert_after_inner_attr() { | 291 | fn insert_after_inner_attr() { |
292 | cov_mark::check!(insert_group_empty_inner_attr); | ||
270 | check_full( | 293 | check_full( |
271 | "foo::bar", | 294 | "foo::bar", |
272 | r"#![allow(unused_imports)]", | 295 | r"#![allow(unused_imports)]", |