@@ -10,6 +10,8 @@ use ide_db::{
10
10
defs::{Definition, NameClass, NameRefClass},
11
11
search::{FileReference, SearchScope},
12
12
};
13
+ use itertools::Itertools;
14
+ use smallvec::SmallVec;
13
15
use stdx::format_to;
14
16
use syntax::{
15
17
algo::find_node_at_range,
@@ -657,28 +659,23 @@ impl Module {
657
659
658
660
fn check_intersection_and_push(
659
661
import_paths_to_be_removed: &mut Vec<TextRange>,
660
- import_path: TextRange,
662
+ mut import_path: TextRange,
661
663
) {
662
- if import_paths_to_be_removed.len() > 0 {
663
- // Text ranges received here for imports are extended to the
664
- // next/previous comma which can cause intersections among them
665
- // and later deletion of these can cause panics similar
666
- // to reported in #11766. So to mitigate it, we
667
- // check for intersection between all current members
668
- // and if it exists we combine both text ranges into
669
- // one
670
- let r = import_paths_to_be_removed
671
- .into_iter()
672
- .position(|it| it.intersect(import_path).is_some());
673
- match r {
674
- Some(it) => {
675
- import_paths_to_be_removed[it] = import_paths_to_be_removed[it].cover(import_path)
676
- }
677
- None => import_paths_to_be_removed.push(import_path),
678
- }
679
- } else {
680
- import_paths_to_be_removed.push(import_path);
664
+ // Text ranges received here for imports are extended to the
665
+ // next/previous comma which can cause intersections among them
666
+ // and later deletion of these can cause panics similar
667
+ // to reported in #11766. So to mitigate it, we
668
+ // check for intersection between all current members
669
+ // and combine all such ranges into one.
670
+ let s: SmallVec<[_; 2]> = import_paths_to_be_removed
671
+ .into_iter()
672
+ .positions(|it| it.intersect(import_path).is_some())
673
+ .collect();
674
+ for pos in s.into_iter().rev() {
675
+ let intersecting_path = import_paths_to_be_removed.swap_remove(pos);
676
+ import_path = import_path.cover(intersecting_path);
681
677
}
678
+ import_paths_to_be_removed.push(import_path);
682
679
}
683
680
684
681
fn does_source_exists_outside_sel_in_same_mod(
@@ -1766,4 +1763,49 @@ mod modname {
1766
1763
",
1767
1764
)
1768
1765
}
1766
+
1767
+ #[test]
1768
+ fn test_merge_multiple_intersections() {
1769
+ check_assist(
1770
+ extract_module,
1771
+ r#"
1772
+ mod dep {
1773
+ pub struct A;
1774
+ pub struct B;
1775
+ pub struct C;
1776
+ }
1777
+
1778
+ use dep::{A, B, C};
1779
+
1780
+ $0struct S {
1781
+ inner: A,
1782
+ state: C,
1783
+ condvar: B,
1784
+ }$0
1785
+ "#,
1786
+ r#"
1787
+ mod dep {
1788
+ pub struct A;
1789
+ pub struct B;
1790
+ pub struct C;
1791
+ }
1792
+
1793
+ use dep::{};
1794
+
1795
+ mod modname {
1796
+ use super::dep::B;
1797
+
1798
+ use super::dep::C;
1799
+
1800
+ use super::dep::A;
1801
+
1802
+ pub(crate) struct S {
1803
+ pub(crate) inner: A,
1804
+ pub(crate) state: C,
1805
+ pub(crate) condvar: B,
1806
+ }
1807
+ }
1808
+ "#,
1809
+ );
1810
+ }
1769
1811
}
0 commit comments