1- use std:: iter:: successors;
2-
31use syntax:: {
4- algo:: { neighbor, skip_trivia_token, SyntaxRewriter } ,
5- ast:: { self , edit:: AstNodeEdit , make} ,
6- AstNode , Direction , InsertPosition , SyntaxElement , T ,
2+ algo:: { neighbor, SyntaxRewriter } ,
3+ ast, AstNode ,
74} ;
85
96use crate :: {
107 assist_context:: { AssistContext , Assists } ,
11- utils:: next_prev,
8+ utils:: {
9+ insert_use:: { try_merge_imports, try_merge_trees} ,
10+ next_prev, MergeBehaviour ,
11+ } ,
1212 AssistId , AssistKind ,
1313} ;
1414
@@ -30,23 +30,22 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()
3030 let mut offset = ctx. offset ( ) ;
3131
3232 if let Some ( use_item) = tree. syntax ( ) . parent ( ) . and_then ( ast:: Use :: cast) {
33- let ( merged, to_delete) = next_prev ( )
34- . filter_map ( |dir| neighbor ( & use_item, dir) )
35- . filter_map ( |it| Some ( ( it. clone ( ) , it. use_tree ( ) ?) ) )
36- . find_map ( |( use_item, use_tree) | {
37- Some ( ( try_merge_trees ( & tree, & use_tree) ?, use_item) )
33+ let ( merged, to_delete) =
34+ next_prev ( ) . filter_map ( |dir| neighbor ( & use_item, dir) ) . find_map ( |use_item2| {
35+ try_merge_imports ( & use_item, & use_item2, MergeBehaviour :: Full ) . zip ( Some ( use_item2) )
3836 } ) ?;
3937
40- rewriter. replace_ast ( & tree , & merged) ;
38+ rewriter. replace_ast ( & use_item , & merged) ;
4139 rewriter += to_delete. remove ( ) ;
4240
4341 if to_delete. syntax ( ) . text_range ( ) . end ( ) < offset {
4442 offset -= to_delete. syntax ( ) . text_range ( ) . len ( ) ;
4543 }
4644 } else {
47- let ( merged, to_delete) = next_prev ( )
48- . filter_map ( |dir| neighbor ( & tree, dir) )
49- . find_map ( |use_tree| Some ( ( try_merge_trees ( & tree, & use_tree) ?, use_tree. clone ( ) ) ) ) ?;
45+ let ( merged, to_delete) =
46+ next_prev ( ) . filter_map ( |dir| neighbor ( & tree, dir) ) . find_map ( |use_tree| {
47+ try_merge_trees ( & tree, & use_tree, MergeBehaviour :: Full ) . zip ( Some ( use_tree) )
48+ } ) ?;
5049
5150 rewriter. replace_ast ( & tree, & merged) ;
5251 rewriter += to_delete. remove ( ) ;
@@ -67,66 +66,6 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()
6766 )
6867}
6968
70- fn try_merge_trees ( old : & ast:: UseTree , new : & ast:: UseTree ) -> Option < ast:: UseTree > {
71- let lhs_path = old. path ( ) ?;
72- let rhs_path = new. path ( ) ?;
73-
74- let ( lhs_prefix, rhs_prefix) = common_prefix ( & lhs_path, & rhs_path) ?;
75-
76- let lhs = old. split_prefix ( & lhs_prefix) ;
77- let rhs = new. split_prefix ( & rhs_prefix) ;
78-
79- let should_insert_comma = lhs
80- . use_tree_list ( ) ?
81- . r_curly_token ( )
82- . and_then ( |it| skip_trivia_token ( it. prev_token ( ) ?, Direction :: Prev ) )
83- . map ( |it| it. kind ( ) != T ! [ , ] )
84- . unwrap_or ( true ) ;
85-
86- let mut to_insert: Vec < SyntaxElement > = Vec :: new ( ) ;
87- if should_insert_comma {
88- to_insert. push ( make:: token ( T ! [ , ] ) . into ( ) ) ;
89- to_insert. push ( make:: tokens:: single_space ( ) . into ( ) ) ;
90- }
91- to_insert. extend (
92- rhs. use_tree_list ( ) ?
93- . syntax ( )
94- . children_with_tokens ( )
95- . filter ( |it| it. kind ( ) != T ! [ '{' ] && it. kind ( ) != T ! [ '}' ] ) ,
96- ) ;
97- let use_tree_list = lhs. use_tree_list ( ) ?;
98- let pos = InsertPosition :: Before ( use_tree_list. r_curly_token ( ) ?. into ( ) ) ;
99- let use_tree_list = use_tree_list. insert_children ( pos, to_insert) ;
100- Some ( lhs. with_use_tree_list ( use_tree_list) )
101- }
102-
103- fn common_prefix ( lhs : & ast:: Path , rhs : & ast:: Path ) -> Option < ( ast:: Path , ast:: Path ) > {
104- let mut res = None ;
105- let mut lhs_curr = first_path ( & lhs) ;
106- let mut rhs_curr = first_path ( & rhs) ;
107- loop {
108- match ( lhs_curr. segment ( ) , rhs_curr. segment ( ) ) {
109- ( Some ( lhs) , Some ( rhs) ) if lhs. syntax ( ) . text ( ) == rhs. syntax ( ) . text ( ) => ( ) ,
110- _ => break ,
111- }
112- res = Some ( ( lhs_curr. clone ( ) , rhs_curr. clone ( ) ) ) ;
113-
114- match ( lhs_curr. parent_path ( ) , rhs_curr. parent_path ( ) ) {
115- ( Some ( lhs) , Some ( rhs) ) => {
116- lhs_curr = lhs;
117- rhs_curr = rhs;
118- }
119- _ => break ,
120- }
121- }
122-
123- res
124- }
125-
126- fn first_path ( path : & ast:: Path ) -> ast:: Path {
127- successors ( Some ( path. clone ( ) ) , |it| it. qualifier ( ) ) . last ( ) . unwrap ( )
128- }
129-
13069#[ cfg( test) ]
13170mod tests {
13271 use crate :: tests:: { check_assist, check_assist_not_applicable} ;
@@ -188,6 +127,78 @@ use std::{fmt::{Display, self}};
188127 ) ;
189128 }
190129
130+ #[ test]
131+ fn skip_pub1 ( ) {
132+ check_assist_not_applicable (
133+ merge_imports,
134+ r"
135+ pub use std::fmt<|>::Debug;
136+ use std::fmt::Display;
137+ " ,
138+ ) ;
139+ }
140+
141+ #[ test]
142+ fn skip_pub_last ( ) {
143+ check_assist_not_applicable (
144+ merge_imports,
145+ r"
146+ use std::fmt<|>::Debug;
147+ pub use std::fmt::Display;
148+ " ,
149+ ) ;
150+ }
151+
152+ #[ test]
153+ fn skip_pub_crate_pub ( ) {
154+ check_assist_not_applicable (
155+ merge_imports,
156+ r"
157+ pub(crate) use std::fmt<|>::Debug;
158+ pub use std::fmt::Display;
159+ " ,
160+ ) ;
161+ }
162+
163+ #[ test]
164+ fn skip_pub_pub_crate ( ) {
165+ check_assist_not_applicable (
166+ merge_imports,
167+ r"
168+ pub use std::fmt<|>::Debug;
169+ pub(crate) use std::fmt::Display;
170+ " ,
171+ ) ;
172+ }
173+
174+ #[ test]
175+ fn merge_pub ( ) {
176+ check_assist (
177+ merge_imports,
178+ r"
179+ pub use std::fmt<|>::Debug;
180+ pub use std::fmt::Display;
181+ " ,
182+ r"
183+ pub use std::fmt::{Debug, Display};
184+ " ,
185+ )
186+ }
187+
188+ #[ test]
189+ fn merge_pub_crate ( ) {
190+ check_assist (
191+ merge_imports,
192+ r"
193+ pub(crate) use std::fmt<|>::Debug;
194+ pub(crate) use std::fmt::Display;
195+ " ,
196+ r"
197+ pub(crate) use std::fmt::{Debug, Display};
198+ " ,
199+ )
200+ }
201+
191202 #[ test]
192203 fn test_merge_nested ( ) {
193204 check_assist (
0 commit comments