1 use itertools::Itertools;
3 ast::{self, make, VisibilityOwner},
9 assist_context::{AssistContext, Assists},
13 // Assist: unmerge_use
15 // Extracts single use item from use list.
18 // use std::fmt::{Debug, Display$0};
22 // use std::fmt::{Debug};
23 // use std::fmt::Display;
25 pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 let tree: ast::UseTree = ctx.find_node_at_offset::<ast::UseTree>()?.clone_for_update();
28 let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?;
29 if tree_list.use_trees().count() < 2 {
30 cov_mark::hit!(skip_single_use_item);
34 let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
35 let path = resolve_full_path(&tree)?;
37 let old_parent_range = use_.syntax().parent()?.text_range();
38 let new_parent = use_.syntax().parent()?;
40 let target = tree.syntax().text_range();
42 AssistId("unmerge_use", AssistKind::RefactorRewrite),
46 let new_use = make::use_(
52 tree.star_token().is_some(),
58 ted::insert(Position::after(use_.syntax()), new_use.syntax());
60 builder.replace(old_parent_range, new_parent.to_string());
65 fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> {
69 .take_while(|n| n.kind() != SyntaxKind::USE)
70 .filter_map(ast::UseTree::cast)
71 .filter_map(|t| t.path());
73 let final_path = paths.fold1(|prev, next| make::path_concat(next, prev))?;
74 if final_path.segment().map_or(false, |it| it.self_token().is_some()) {
75 final_path.qualifier()
83 use crate::tests::{check_assist, check_assist_not_applicable};
88 fn skip_single_use_item() {
89 cov_mark::check!(skip_single_use_item);
90 check_assist_not_applicable(
93 use std::fmt::Debug$0;
96 check_assist_not_applicable(
99 use std::fmt::{Debug$0};
102 check_assist_not_applicable(
105 use std::fmt::Debug as Dbg$0;
111 fn skip_single_glob_import() {
112 check_assist_not_applicable(
121 fn unmerge_use_item() {
125 use std::fmt::{Debug, Display$0};
128 use std::fmt::{Debug};
129 use std::fmt::Display;
136 use std::fmt::{Debug, format$0, Display};
139 use std::fmt::{Debug, Display};
140 use std::fmt::format;
146 fn unmerge_glob_import() {
150 use std::fmt::{*$0, Display};
153 use std::fmt::{Display};
160 fn unmerge_renamed_use_item() {
164 use std::fmt::{Debug, Display as Disp$0};
167 use std::fmt::{Debug};
168 use std::fmt::Display as Disp;
174 fn unmerge_indented_use_item() {
179 use std::fmt::{Debug, Display$0 as Disp, format};
184 use std::fmt::{Debug, format};
185 use std::fmt::Display as Disp;
192 fn unmerge_nested_use_item() {
196 use foo::bar::{baz::{qux$0, foobar}, barbaz};
199 use foo::bar::{baz::{foobar}, barbaz};
200 use foo::bar::baz::qux;
206 use foo::bar::{baz$0::{qux, foobar}, barbaz};
209 use foo::bar::{barbaz};
210 use foo::bar::baz::{qux, foobar};
216 fn unmerge_use_item_with_visibility() {
220 pub use std::fmt::{Debug, Display$0};
223 pub use std::fmt::{Debug};
224 pub use std::fmt::Display;
230 fn unmerge_use_item_on_self() {
233 r"use std::process::{Command, self$0};",
234 r"use std::process::{Command};