1- use std:: iter:: successors;
1+ use std:: iter:: { once , successors} ;
22
3- use ra_syntax:: { ast, AstNode , TextUnit , T } ;
3+ use ra_syntax:: {
4+ ast:: { self , make} ,
5+ AstNode , T ,
6+ } ;
47
58use crate :: { Assist , AssistCtx , AssistId } ;
69
@@ -17,39 +20,50 @@ use crate::{Assist, AssistCtx, AssistId};
1720// ```
1821pub ( crate ) fn split_import ( ctx : AssistCtx ) -> Option < Assist > {
1922 let colon_colon = ctx. find_token_at_offset ( T ! [ :: ] ) ?;
20- let path = ast:: Path :: cast ( colon_colon. parent ( ) ) ?;
21- let top_path = successors ( Some ( path) , |it| it. parent_path ( ) ) . last ( ) ?;
23+ let path = ast:: Path :: cast ( colon_colon. parent ( ) ) ?. qualifier ( ) ? ;
24+ let top_path = successors ( Some ( path. clone ( ) ) , |it| it. parent_path ( ) ) . last ( ) ?;
2225
23- let use_tree = top_path. syntax ( ) . ancestors ( ) . find_map ( ast:: UseTree :: cast) ;
24- if use_tree. is_none ( ) {
25- return None ;
26- }
26+ let use_tree = top_path. syntax ( ) . ancestors ( ) . find_map ( ast:: UseTree :: cast) ?;
2727
28- let l_curly = colon_colon. text_range ( ) . end ( ) ;
29- let r_curly = match top_path. syntax ( ) . parent ( ) . and_then ( ast:: UseTree :: cast) {
30- Some ( tree) => tree. syntax ( ) . text_range ( ) . end ( ) ,
31- None => top_path. syntax ( ) . text_range ( ) . end ( ) ,
32- } ;
28+ let new_tree = split_use_tree_prefix ( & use_tree, & path) ?;
29+ let cursor = ctx. frange . range . start ( ) ;
3330
3431 ctx. add_assist ( AssistId ( "split_import" ) , "Split import" , |edit| {
3532 edit. target ( colon_colon. text_range ( ) ) ;
36- edit. insert ( l_curly, "{" ) ;
37- edit. insert ( r_curly, "}" ) ;
38- edit. set_cursor ( l_curly + TextUnit :: of_str ( "{" ) ) ;
33+ edit. replace_ast ( use_tree, new_tree) ;
34+ edit. set_cursor ( cursor) ;
3935 } )
4036}
4137
38+ fn split_use_tree_prefix ( use_tree : & ast:: UseTree , prefix : & ast:: Path ) -> Option < ast:: UseTree > {
39+ let suffix = split_path_prefix ( & prefix) ?;
40+ let use_tree = make:: use_tree ( suffix. clone ( ) , use_tree. use_tree_list ( ) , use_tree. alias ( ) ) ;
41+ let nested = make:: use_tree_list ( once ( use_tree) ) ;
42+ let res = make:: use_tree ( prefix. clone ( ) , Some ( nested) , None ) ;
43+ Some ( res)
44+ }
45+
46+ fn split_path_prefix ( prefix : & ast:: Path ) -> Option < ast:: Path > {
47+ let parent = prefix. parent_path ( ) ?;
48+ let mut res = make:: path_unqualified ( parent. segment ( ) ?) ;
49+ for p in successors ( parent. parent_path ( ) , |it| it. parent_path ( ) ) {
50+ res = make:: path_qualified ( res, p. segment ( ) ?) ;
51+ }
52+ Some ( res)
53+ }
54+
4255#[ cfg( test) ]
4356mod tests {
44- use super :: * ;
4557 use crate :: helpers:: { check_assist, check_assist_target} ;
4658
59+ use super :: * ;
60+
4761 #[ test]
4862 fn test_split_import ( ) {
4963 check_assist (
5064 split_import,
5165 "use crate::<|>db::RootDatabase;" ,
52- "use crate::{ <|>db::RootDatabase};" ,
66+ "use crate::<|>{ db::RootDatabase};" ,
5367 )
5468 }
5569
@@ -58,7 +72,7 @@ mod tests {
5872 check_assist (
5973 split_import,
6074 "use crate:<|>:db::{RootDatabase, FileSymbol}" ,
61- "use crate::{ <|>db::{RootDatabase, FileSymbol}}" ,
75+ "use crate:<|>:{ db::{RootDatabase, FileSymbol}}" ,
6276 )
6377 }
6478
0 commit comments