1
- use std:: iter:: successors;
1
+ use std:: iter:: { once , successors} ;
2
2
3
- use ra_syntax:: { ast, AstNode , TextUnit , T } ;
3
+ use ra_syntax:: {
4
+ ast:: { self , make} ,
5
+ AstNode , T ,
6
+ } ;
4
7
5
8
use crate :: { Assist , AssistCtx , AssistId } ;
6
9
@@ -17,39 +20,50 @@ use crate::{Assist, AssistCtx, AssistId};
17
20
// ```
18
21
pub ( crate ) fn split_import ( ctx : AssistCtx ) -> Option < Assist > {
19
22
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 ( ) ?;
22
25
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) ?;
27
27
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 ( ) ;
33
30
34
31
ctx. add_assist ( AssistId ( "split_import" ) , "Split import" , |edit| {
35
32
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) ;
39
35
} )
40
36
}
41
37
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
+
42
55
#[ cfg( test) ]
43
56
mod tests {
44
- use super :: * ;
45
57
use crate :: helpers:: { check_assist, check_assist_target} ;
46
58
59
+ use super :: * ;
60
+
47
61
#[ test]
48
62
fn test_split_import ( ) {
49
63
check_assist (
50
64
split_import,
51
65
"use crate::<|>db::RootDatabase;" ,
52
- "use crate::{ <|>db::RootDatabase};" ,
66
+ "use crate::<|>{ db::RootDatabase};" ,
53
67
)
54
68
}
55
69
@@ -58,7 +72,7 @@ mod tests {
58
72
check_assist (
59
73
split_import,
60
74
"use crate:<|>:db::{RootDatabase, FileSymbol}" ,
61
- "use crate::{ <|>db::{RootDatabase, FileSymbol}}" ,
75
+ "use crate:<|>:{ db::{RootDatabase, FileSymbol}}" ,
62
76
)
63
77
}
64
78
0 commit comments