11use syntax:: {
22 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 } ,
58} ;
69
710use crate :: {
811 AssistId ,
912 assist_context:: { AssistContext , Assists } ,
1013} ;
1114
12- // Assist: unmerge_use
15+ // Assist: unmerge_imports
1316//
14- // Extracts single use item from use list.
17+ // Extracts a use item from a use list into a standalone use list.
1518//
1619// ```
1720// use std::fmt::{Debug, Display$0};
@@ -21,39 +24,50 @@ use crate::{
2124// use std::fmt::{Debug};
2225// use std::fmt::Display;
2326// ```
24- 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 ( ) ;
27+ pub ( crate ) fn unmerge_imports ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
28+ let tree = ctx. find_node_at_offset :: < ast:: UseTree > ( ) ?;
2629
2730 let tree_list = tree. syntax ( ) . parent ( ) . and_then ( ast:: UseTreeList :: cast) ?;
2831 if tree_list. use_trees ( ) . count ( ) < 2 {
29- cov_mark:: hit!( skip_single_use_item ) ;
32+ cov_mark:: hit!( skip_single_import ) ;
3033 return None ;
3134 }
3235
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) ?;
3437 let path = resolve_full_path ( & tree) ?;
3538
36- let old_parent_range = use_. syntax ( ) . parent ( ) ?. text_range ( ) ;
37- let new_parent = use_. syntax ( ) . parent ( ) ?;
38-
3939 // If possible, explain what is going to be done.
4040 let label = match tree. path ( ) . and_then ( |path| path. first_segment ( ) ) {
4141 Some ( name) => format ! ( "Unmerge use of `{name}`" ) ,
4242 None => "Unmerge use" . into ( ) ,
4343 } ;
4444
4545 let target = tree. syntax ( ) . text_range ( ) ;
46- acc. add ( AssistId :: refactor_rewrite ( "unmerge_use" ) , label, target, |builder| {
47- let new_use = make:: use_ (
46+ acc. add ( AssistId :: refactor_rewrite ( "unmerge_imports" ) , label, target, |builder| {
47+ let make = SyntaxFactory :: with_mappings ( ) ;
48+ let new_use = make. use_ (
4849 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+ } ) ;
5556
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. vfs_file_id ( ) , editor) ;
5771 } )
5872}
5973
@@ -80,22 +94,22 @@ mod tests {
8094 use super :: * ;
8195
8296 #[ test]
83- fn skip_single_use_item ( ) {
84- cov_mark:: check!( skip_single_use_item ) ;
97+ fn skip_single_import ( ) {
98+ cov_mark:: check!( skip_single_import ) ;
8599 check_assist_not_applicable (
86- unmerge_use ,
100+ unmerge_imports ,
87101 r"
88102use std::fmt::Debug$0;
89103" ,
90104 ) ;
91105 check_assist_not_applicable (
92- unmerge_use ,
106+ unmerge_imports ,
93107 r"
94108use std::fmt::{Debug$0};
95109" ,
96110 ) ;
97111 check_assist_not_applicable (
98- unmerge_use ,
112+ unmerge_imports ,
99113 r"
100114use std::fmt::Debug as Dbg$0;
101115" ,
@@ -105,17 +119,17 @@ use std::fmt::Debug as Dbg$0;
105119 #[ test]
106120 fn skip_single_glob_import ( ) {
107121 check_assist_not_applicable (
108- unmerge_use ,
122+ unmerge_imports ,
109123 r"
110124use std::fmt::*$0;
111125" ,
112126 ) ;
113127 }
114128
115129 #[ test]
116- fn unmerge_use_item ( ) {
130+ fn unmerge_import ( ) {
117131 check_assist (
118- unmerge_use ,
132+ unmerge_imports ,
119133 r"
120134use std::fmt::{Debug, Display$0};
121135" ,
@@ -126,7 +140,7 @@ use std::fmt::Display;
126140 ) ;
127141
128142 check_assist (
129- unmerge_use ,
143+ unmerge_imports ,
130144 r"
131145use std::fmt::{Debug, format$0, Display};
132146" ,
@@ -140,7 +154,7 @@ use std::fmt::format;
140154 #[ test]
141155 fn unmerge_glob_import ( ) {
142156 check_assist (
143- unmerge_use ,
157+ unmerge_imports ,
144158 r"
145159use std::fmt::{*$0, Display};
146160" ,
@@ -152,9 +166,9 @@ use std::fmt::*;
152166 }
153167
154168 #[ test]
155- fn unmerge_renamed_use_item ( ) {
169+ fn unmerge_renamed_import ( ) {
156170 check_assist (
157- unmerge_use ,
171+ unmerge_imports ,
158172 r"
159173use std::fmt::{Debug, Display as Disp$0};
160174" ,
@@ -166,9 +180,9 @@ use std::fmt::Display as Disp;
166180 }
167181
168182 #[ test]
169- fn unmerge_indented_use_item ( ) {
183+ fn unmerge_indented_import ( ) {
170184 check_assist (
171- unmerge_use ,
185+ unmerge_imports ,
172186 r"
173187mod format {
174188 use std::fmt::{Debug, Display$0 as Disp, format};
@@ -184,9 +198,9 @@ mod format {
184198 }
185199
186200 #[ test]
187- fn unmerge_nested_use_item ( ) {
201+ fn unmerge_nested_import ( ) {
188202 check_assist (
189- unmerge_use ,
203+ unmerge_imports ,
190204 r"
191205use foo::bar::{baz::{qux$0, foobar}, barbaz};
192206" ,
@@ -196,7 +210,7 @@ use foo::bar::baz::qux;
196210" ,
197211 ) ;
198212 check_assist (
199- unmerge_use ,
213+ unmerge_imports ,
200214 r"
201215use foo::bar::{baz$0::{qux, foobar}, barbaz};
202216" ,
@@ -208,9 +222,9 @@ use foo::bar::baz::{qux, foobar};
208222 }
209223
210224 #[ test]
211- fn unmerge_use_item_with_visibility ( ) {
225+ fn unmerge_import_with_visibility ( ) {
212226 check_assist (
213- unmerge_use ,
227+ unmerge_imports ,
214228 r"
215229pub use std::fmt::{Debug, Display$0};
216230" ,
@@ -222,12 +236,27 @@ pub use std::fmt::Display;
222236 }
223237
224238 #[ test]
225- fn unmerge_use_item_on_self ( ) {
239+ fn unmerge_import_on_self ( ) {
226240 check_assist (
227- unmerge_use ,
241+ unmerge_imports ,
228242 r"use std::process::{Command, self$0};" ,
229243 r"use std::process::{Command};
230244use std::process;" ,
231245 ) ;
232246 }
247+
248+ #[ test]
249+ fn unmerge_import_with_attributes ( ) {
250+ check_assist (
251+ unmerge_imports,
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+ }
233262}
0 commit comments