@@ -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