@@ -3,7 +3,7 @@ use std::iter::successors;
33use ra_syntax:: {
44 algo:: neighbor,
55 ast:: { self , edit:: AstNodeEdit , make} ,
6- AstNode , AstToken , Direction , InsertPosition , SyntaxElement , T ,
6+ AstNode , AstToken , Direction , InsertPosition , SyntaxElement , TextRange , T ,
77} ;
88
99use crate :: { Assist , AssistCtx , AssistId } ;
@@ -22,18 +22,15 @@ use crate::{Assist, AssistCtx, AssistId};
2222// ```
2323pub ( crate ) fn merge_imports ( ctx : AssistCtx ) -> Option < Assist > {
2424 let tree: ast:: UseTree = ctx. find_node_at_offset ( ) ?;
25- let use_item = tree. syntax ( ) . parent ( ) . and_then ( ast:: UseItem :: cast) ?;
26- let ( merged, to_delete) = [ Direction :: Prev , Direction :: Next ]
27- . iter ( )
28- . copied ( )
29- . filter_map ( |dir| neighbor ( & use_item, dir) )
30- . filter_map ( |it| Some ( ( it. clone ( ) , it. use_tree ( ) ?) ) )
31- . find_map ( |( use_item, use_tree) | {
32- Some ( ( try_merge_trees ( & tree, & use_tree) ?, use_item. clone ( ) ) )
33- } ) ?;
34- let mut offset = ctx. frange . range . start ( ) ;
35- ctx. add_assist ( AssistId ( "merge_imports" ) , "Merge imports" , |edit| {
36- edit. replace_ast ( tree, merged) ;
25+ let ( new_tree, to_delete) = if let Some ( use_item) =
26+ tree. syntax ( ) . parent ( ) . and_then ( ast:: UseItem :: cast)
27+ {
28+ let ( merged, to_delete) = next_prev ( )
29+ . filter_map ( |dir| neighbor ( & use_item, dir) )
30+ . filter_map ( |it| Some ( ( it. clone ( ) , it. use_tree ( ) ?) ) )
31+ . find_map ( |( use_item, use_tree) | {
32+ Some ( ( try_merge_trees ( & tree, & use_tree) ?, use_item. clone ( ) ) )
33+ } ) ?;
3734
3835 let mut range = to_delete. syntax ( ) . text_range ( ) ;
3936 let next_ws = to_delete
@@ -44,14 +41,41 @@ pub(crate) fn merge_imports(ctx: AssistCtx) -> Option<Assist> {
4441 if let Some ( ws) = next_ws {
4542 range = range. extend_to ( & ws. syntax ( ) . text_range ( ) )
4643 }
47- edit. delete ( range) ;
48- if range. end ( ) <= offset {
49- offset -= range. len ( ) ;
44+ ( merged, range)
45+ } else {
46+ let ( merged, to_delete) = next_prev ( )
47+ . filter_map ( |dir| neighbor ( & tree, dir) )
48+ . find_map ( |use_tree| Some ( ( try_merge_trees ( & tree, & use_tree) ?, use_tree. clone ( ) ) ) ) ?;
49+
50+ let mut range = to_delete. syntax ( ) . text_range ( ) ;
51+ if let Some ( ( dir, nb) ) = next_prev ( ) . find_map ( |dir| Some ( ( dir, neighbor ( & to_delete, dir) ?) ) )
52+ {
53+ let nb_range = nb. syntax ( ) . text_range ( ) ;
54+ if dir == Direction :: Prev {
55+ range = TextRange :: from_to ( nb_range. end ( ) , range. end ( ) ) ;
56+ } else {
57+ range = TextRange :: from_to ( range. start ( ) , nb_range. start ( ) ) ;
58+ }
59+ }
60+ ( merged, range)
61+ } ;
62+
63+ let mut offset = ctx. frange . range . start ( ) ;
64+ ctx. add_assist ( AssistId ( "merge_imports" ) , "Merge imports" , |edit| {
65+ edit. replace_ast ( tree, new_tree) ;
66+ edit. delete ( to_delete) ;
67+
68+ if to_delete. end ( ) <= offset {
69+ offset -= to_delete. len ( ) ;
5070 }
5171 edit. set_cursor ( offset) ;
5272 } )
5373}
5474
75+ fn next_prev ( ) -> impl Iterator < Item = Direction > {
76+ [ Direction :: Next , Direction :: Prev ] . iter ( ) . copied ( )
77+ }
78+
5579fn try_merge_trees ( old : & ast:: UseTree , new : & ast:: UseTree ) -> Option < ast:: UseTree > {
5680 let lhs_path = old. path ( ) ?;
5781 let rhs_path = new. path ( ) ?;
@@ -134,20 +158,28 @@ use std::fmt<|>::Display;
134158 r"
135159use std::fmt<|>::{Display, Debug};
136160" ,
137- )
161+ ) ;
138162 }
139163
140164 #[ test]
141- #[ ignore]
142165 fn test_merge_nested ( ) {
143166 check_assist (
144167 merge_imports,
145168 r"
146169use std::{fmt<|>::Debug, fmt::Display};
147170" ,
148171 r"
149- use std::{fmt::{Debug, Display}};
172+ use std::{fmt<|> ::{Debug, Display}};
150173" ,
151- )
174+ ) ;
175+ check_assist (
176+ merge_imports,
177+ r"
178+ use std::{fmt::Debug, fmt<|>::Display};
179+ " ,
180+ r"
181+ use std::{fmt<|>::{Display, Debug}};
182+ " ,
183+ ) ;
152184 }
153185}
0 commit comments