diff --git a/crates/ide-db/src/imports/insert_use.rs b/crates/ide-db/src/imports/insert_use.rs index 4b0373271c03..53c262eaa8ad 100644 --- a/crates/ide-db/src/imports/insert_use.rs +++ b/crates/ide-db/src/imports/insert_use.rs @@ -436,6 +436,9 @@ fn insert_use_with_editor_( Some((tree, node)) }); + let newline = + |nl, node: &SyntaxNode| make.whitespace(&format!("{nl}{}", IndentLevel::from_node(node))); + if group_imports { // Iterator that discards anything that's not in the required grouping // This implementation allows the user to rearrange their import groups as this only takes the first group that fits @@ -455,16 +458,16 @@ fn insert_use_with_editor_( cov_mark::hit!(insert_group); // insert our import before that element return syntax_editor.insert_all( - Position::before(node), - vec![use_item.syntax().clone().into(), make.whitespace("\n").into()], + Position::before(&node), + vec![use_item.syntax().clone().into(), newline("\n", &node).into()], ); } if let Some(node) = last { cov_mark::hit!(insert_group_last); // there is no element after our new import, so append it to the end of the group return syntax_editor.insert_all( - Position::after(node), - vec![make.whitespace("\n").into(), use_item.syntax().clone().into()], + Position::after(&node), + vec![newline("\n", &node).into(), use_item.syntax().clone().into()], ); } @@ -479,7 +482,7 @@ fn insert_use_with_editor_( cov_mark::hit!(insert_group_new_group); syntax_editor.insert_all( Position::before(&node), - vec![use_item.syntax().clone().into(), make.whitespace("\n\n").into()], + vec![use_item.syntax().clone().into(), newline("\n\n", &node).into()], ); return; } @@ -488,7 +491,7 @@ fn insert_use_with_editor_( cov_mark::hit!(insert_group_no_group); syntax_editor.insert_all( Position::after(&node), - vec![make.whitespace("\n\n").into(), use_item.syntax().clone().into()], + vec![newline("\n\n", &node).into(), use_item.syntax().clone().into()], ); return; } @@ -497,8 +500,8 @@ fn insert_use_with_editor_( if let Some((_, node)) = path_node_iter.last() { cov_mark::hit!(insert_no_grouping_last); syntax_editor.insert_all( - Position::after(node), - vec![make.whitespace("\n").into(), use_item.syntax().clone().into()], + Position::after(&node), + vec![newline("\n", &node).into(), use_item.syntax().clone().into()], ); return; } @@ -545,14 +548,22 @@ fn insert_use_with_editor_( } else { match l_curly { Some(b) => { - cov_mark::hit!(insert_empty_module); + let close_ws = if let Some(next) = syntax::algo::next_non_trivia_token(b.clone()) + && next.kind() == SyntaxKind::R_CURLY + { + cov_mark::hit!(insert_empty_module); + newline("\n", scope_syntax) + } else { + cov_mark::hit!(insert_first_of_module); + make.whitespace("\n") + }; let indent = IndentLevel::from_node(scope_syntax) + 1; syntax_editor.insert_all( Position::after(&b), vec![ make.whitespace(&format!("\n{indent}")).into(), use_item.syntax().clone().into(), - make.whitespace("\n").into(), + close_ws.into(), ], ); } diff --git a/crates/ide-db/src/imports/insert_use/tests.rs b/crates/ide-db/src/imports/insert_use/tests.rs index 4fa05c460346..9e84c03f8a61 100644 --- a/crates/ide-db/src/imports/insert_use/tests.rs +++ b/crates/ide-db/src/imports/insert_use/tests.rs @@ -22,6 +22,83 @@ struct Struct; ); } +#[test] +fn insert_in_module_indent() { + cov_mark::check!(insert_group); + check( + "foo::bar", + r#" +mod tests { + $0use xxx; +} +"#, + r#" +mod tests { + use foo::bar; + use xxx; +} +"#, + ImportGranularity::Crate, + ); + + cov_mark::check!(insert_group_last); + check( + "foo::bar", + r#" +mod tests { + $0use aaa; +} +"#, + r#" +mod tests { + use aaa; + use foo::bar; +} +"#, + ImportGranularity::Crate, + ); + + cov_mark::check!(insert_group_new_group); + check_none( + "std::fmt", + r#" +mod tests { + $0use foo::bar::A; + use foo::bar::D; +} +"#, + r#" +mod tests { + use std::fmt; + + use foo::bar::A; + use foo::bar::D; +} +"#, + ); + + cov_mark::check!(insert_first_of_module); + check_none( + "baz::Baz", + r#" +mod foo { + mod bar { + const _: Baz$0 = (); + } +} +"#, + r#" +mod foo { + mod bar { + use baz::Baz; + + const _: Baz = (); + } +} +"#, + ); +} + #[test] fn respects_cfg_attr_fn_body() { check( @@ -473,11 +550,15 @@ fn insert_empty_module() { check( "foo::bar", r" -mod x {$0} +mod indent { + mod x {$0} +} ", r" -mod x { - use foo::bar; +mod indent { + mod x { + use foo::bar; + } } ", ImportGranularity::Item, @@ -549,6 +630,7 @@ fn main() {}", #[test] fn inserts_after_single_line_inner_comments() { + cov_mark::check_count!(insert_empty_inner_attr, 2); check_none( "foo::bar::Baz", "//! Single line inner comments do not allow any code before them.",