diff --git a/crates/ide-assists/src/handlers/remove_unused_imports.rs b/crates/ide-assists/src/handlers/remove_unused_imports.rs index ee44064e7c5e7..482c36d502e61 100644 --- a/crates/ide-assists/src/handlers/remove_unused_imports.rs +++ b/crates/ide-assists/src/handlers/remove_unused_imports.rs @@ -423,7 +423,7 @@ mod z { struct X(); struct Y(); mod z { - use super::{X}; + use super::X; fn w() { let x = X(); @@ -495,7 +495,7 @@ struct X(); mod y { struct Y(); mod z { - use crate::{X}; + use crate::X; fn f() { let x = X(); } @@ -526,7 +526,7 @@ struct X(); mod y { struct Y(); mod z { - use crate::{y::Y}; + use crate::y::Y; fn f() { let y = Y(); } @@ -536,6 +536,79 @@ mod y { ); } + #[test] + fn remove_unused_auto_remove_brace_nested() { + check_assist( + remove_unused_imports, + r#" +mod a { + pub struct A(); +} +mod b { + struct F(); + mod c { + $0use {{super::{{ + {d::{{{{{{{S, U}}}}}}}}, + {{{{e::{H, L, {{{R}}}}}}}}, + F, super::a::A + }}}};$0 + fn f() { + let f = F(); + let l = L(); + let a = A(); + let s = S(); + let h = H(); + } + } + + mod d { + pub struct S(); + pub struct U(); + } + + mod e { + pub struct H(); + pub struct L(); + pub struct R(); + } +} +"#, + r#" +mod a { + pub struct A(); +} +mod b { + struct F(); + mod c { + use super::{ + d::S, + e::{H, L}, + F, super::a::A + }; + fn f() { + let f = F(); + let l = L(); + let a = A(); + let s = S(); + let h = H(); + } + } + + mod d { + pub struct S(); + pub struct U(); + } + + mod e { + pub struct H(); + pub struct L(); + pub struct R(); + } +} +"#, + ); + } + #[test] fn remove_nested_all_unused() { check_assist( diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 37d8212042da0..916bbbad40980 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs @@ -414,6 +414,7 @@ impl ast::UseTree { u.remove_recursive(); } } + u.remove_unnecessary_braces(); } } diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index f81dff8840ccc..cfd919ad6f206 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -11,7 +11,7 @@ use rowan::{GreenNodeData, GreenTokenData}; use crate::{ ast::{self, support, AstNode, AstToken, HasAttrs, HasGenericParams, HasName, SyntaxNode}, - NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, TokenText, T, + ted, NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, TokenText, T, }; impl ast::Lifetime { @@ -323,6 +323,10 @@ impl ast::UseTree { pub fn is_simple_path(&self) -> bool { self.use_tree_list().is_none() && self.star_token().is_none() } + + pub fn parent_use_tree_list(&self) -> Option { + self.syntax().parent().and_then(ast::UseTreeList::cast) + } } impl ast::UseTreeList { @@ -340,6 +344,27 @@ impl ast::UseTreeList { .find_map(ast::Comment::cast) .is_some() } + + /// Remove the unnecessary braces in current `UseTreeList` + pub fn remove_unnecessary_braces(mut self) { + let remove_brace_in_use_tree_list = |u: &ast::UseTreeList| { + let use_tree_count = u.use_trees().count(); + if use_tree_count == 1 { + u.l_curly_token().map(ted::remove); + u.r_curly_token().map(ted::remove); + } + }; + + // take `use crate::{{{{A}}}}` for example + // the below remove the innermost {}, got `use crate::{{{A}}}` + remove_brace_in_use_tree_list(&self); + + // the below remove othe unnecessary {}, got `use crate::A` + while let Some(parent_use_tree_list) = self.parent_use_tree().parent_use_tree_list() { + remove_brace_in_use_tree_list(&parent_use_tree_list); + self = parent_use_tree_list; + } + } } impl ast::Impl {