@@ -10,6 +10,8 @@ use ide_db::{
1010 defs:: { Definition , NameClass , NameRefClass } ,
1111 search:: { FileReference , SearchScope } ,
1212} ;
13+ use itertools:: Itertools ;
14+ use smallvec:: SmallVec ;
1315use stdx:: format_to;
1416use syntax:: {
1517 algo:: find_node_at_range,
@@ -657,28 +659,23 @@ impl Module {
657659
658660fn check_intersection_and_push (
659661 import_paths_to_be_removed : & mut Vec < TextRange > ,
660- import_path : TextRange ,
662+ mut import_path : TextRange ,
661663) {
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) ;
681677 }
678+ import_paths_to_be_removed. push ( import_path) ;
682679}
683680
684681fn does_source_exists_outside_sel_in_same_mod (
@@ -1766,4 +1763,49 @@ mod modname {
17661763 " ,
17671764 )
17681765 }
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+ }
17691811}
0 commit comments