1
1
use syntax:: {
2
2
AstNode , SyntaxKind ,
3
- ast:: { self , HasVisibility , edit_in_place:: Removable , make} ,
4
- ted:: { self , Position } ,
3
+ ast:: {
4
+ self , HasAttrs , HasVisibility , edit:: IndentLevel , edit_in_place:: AttrsOwnerEdit , make,
5
+ syntax_factory:: SyntaxFactory ,
6
+ } ,
7
+ syntax_editor:: { Element , Position , Removable } ,
5
8
} ;
6
9
7
10
use crate :: {
@@ -22,20 +25,17 @@ use crate::{
22
25
// use std::fmt::Display;
23
26
// ```
24
27
pub ( crate ) fn unmerge_use ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
25
- let tree: ast :: UseTree = ctx. find_node_at_offset :: < ast:: UseTree > ( ) ?. clone_for_update ( ) ;
28
+ let tree = ctx. find_node_at_offset :: < ast:: UseTree > ( ) ?;
26
29
27
30
let tree_list = tree. syntax ( ) . parent ( ) . and_then ( ast:: UseTreeList :: cast) ?;
28
31
if tree_list. use_trees ( ) . count ( ) < 2 {
29
32
cov_mark:: hit!( skip_single_use_item) ;
30
33
return None ;
31
34
}
32
35
33
- let use_: ast :: Use = tree_list. syntax ( ) . ancestors ( ) . find_map ( ast:: Use :: cast) ?;
36
+ let use_ = tree_list. syntax ( ) . ancestors ( ) . find_map ( ast:: Use :: cast) ?;
34
37
let path = resolve_full_path ( & tree) ?;
35
38
36
- let old_parent_range = use_. syntax ( ) . parent ( ) ?. text_range ( ) ;
37
- let new_parent = use_. syntax ( ) . parent ( ) ?;
38
-
39
39
// If possible, explain what is going to be done.
40
40
let label = match tree. path ( ) . and_then ( |path| path. first_segment ( ) ) {
41
41
Some ( name) => format ! ( "Unmerge use of `{name}`" ) ,
@@ -44,16 +44,30 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
44
44
45
45
let target = tree. syntax ( ) . text_range ( ) ;
46
46
acc. add ( AssistId :: refactor_rewrite ( "unmerge_use" ) , label, target, |builder| {
47
- let new_use = make:: use_ (
47
+ let make = SyntaxFactory :: new ( ) ;
48
+ let new_use = make. use_ (
48
49
use_. visibility ( ) ,
49
- make:: use_tree ( path, tree. use_tree_list ( ) , tree. rename ( ) , tree. star_token ( ) . is_some ( ) ) ,
50
- )
51
- . clone_for_update ( ) ;
52
-
53
- tree . remove ( ) ;
54
- ted :: insert ( Position :: after ( use_ . syntax ( ) ) , new_use . syntax ( ) ) ;
50
+ make. use_tree ( path, tree. use_tree_list ( ) , tree. rename ( ) , tree. star_token ( ) . is_some ( ) ) ,
51
+ ) ;
52
+ // Add any attributes that are present on the use tree
53
+ use_ . attrs ( ) . for_each ( |attr| {
54
+ new_use . add_attr ( attr . clone_for_update ( ) ) ;
55
+ } ) ;
55
56
56
- builder. replace ( old_parent_range, new_parent. to_string ( ) ) ;
57
+ let mut editor = builder. make_editor ( use_. syntax ( ) ) ;
58
+ // Remove the use tree from the current use item
59
+ tree. remove ( & mut editor) ;
60
+ // Insert a newline and indentation, followed by the new use item
61
+ editor. insert_all (
62
+ Position :: after ( use_. syntax ( ) ) ,
63
+ vec ! [
64
+ make. whitespace( & format!( "\n {}" , IndentLevel :: from_node( use_. syntax( ) ) ) )
65
+ . syntax_element( ) ,
66
+ new_use. syntax( ) . syntax_element( ) ,
67
+ ] ,
68
+ ) ;
69
+ editor. add_mappings ( make. finish_with_mappings ( ) ) ;
70
+ builder. add_file_edits ( ctx. file_id ( ) , editor) ;
57
71
} )
58
72
}
59
73
@@ -230,4 +244,19 @@ pub use std::fmt::Display;
230
244
use std::process;" ,
231
245
) ;
232
246
}
247
+
248
+ #[ test]
249
+ fn unmerge_use_item_with_attributes ( ) {
250
+ check_assist (
251
+ unmerge_use,
252
+ r"
253
+ #[allow(deprecated)]
254
+ use foo::{bar, baz$0};" ,
255
+ r"
256
+ #[allow(deprecated)]
257
+ use foo::{bar};
258
+ #[allow(deprecated)]
259
+ use foo::baz;" ,
260
+ ) ;
261
+ }
233
262
}
0 commit comments