diff --git a/crates/ide-assists/src/handlers/merge_imports.rs b/crates/ide-assists/src/handlers/merge_imports.rs index 9ba73d23dd24..7f21333a378a 100644 --- a/crates/ide-assists/src/handlers/merge_imports.rs +++ b/crates/ide-assists/src/handlers/merge_imports.rs @@ -106,12 +106,21 @@ trait Merge: AstNode + Clone { ) -> Option> { let mut edits = Vec::new(); let mut merged = self.clone(); + let mut replace = self; + let mut update_replace = |item: Self| { + if item.syntax().text_range().start() < replace.syntax().text_range().start() { + std::mem::replace(&mut replace, item) + } else { + item + } + }; + for item in items { merged = merged.try_merge(&item, cfg)?; - edits.push(Edit::Remove(item.into_either())); + edits.push(Edit::Remove(update_replace(item).into_either())); } if !edits.is_empty() { - edits.push(Edit::replace(self, merged)); + edits.push(Edit::replace(replace, merged)); Some(edits) } else { None @@ -563,6 +572,62 @@ use foo::{bar, baz}; ); } + #[test] + fn mod_indent_whitespace() { + check_assist( + merge_imports, + r" +mod tests { + use foo$0::bar; + use foo::baz; + fn feature() {} +} +", + r" +mod tests { + use foo::{bar, baz}; + fn feature() {} +} +", + ); + check_assist( + merge_imports, + r" +mod tests { + use foo$0::bar; + use foo::baz; + + fn feature() {} +} +", + r" +mod tests { + use foo::{bar, baz}; + + fn feature() {} +} +", + ); + check_assist( + merge_imports, + r" +mod tests { + use foo::bar; + use foo$0::baz; + + fn feature() {} +} +", + r" +mod tests { + use foo::{bar, baz}; + + fn feature() {} +} +", + ); + } + #[test] fn works_with_trailing_comma() { check_assist( diff --git a/crates/syntax/src/syntax_editor/edits.rs b/crates/syntax/src/syntax_editor/edits.rs index 9090f7c9eb14..1f4311a97408 100644 --- a/crates/syntax/src/syntax_editor/edits.rs +++ b/crates/syntax/src/syntax_editor/edits.rs @@ -214,18 +214,18 @@ impl Removable for ast::Use { fn remove(&self, editor: &mut SyntaxEditor) { let make = SyntaxFactory::without_mappings(); - let next_ws = self + let prev_ws = self .syntax() - .next_sibling_or_token() + .prev_sibling_or_token() .and_then(|it| it.into_token()) .and_then(ast::Whitespace::cast); - if let Some(next_ws) = next_ws { - let ws_text = next_ws.syntax().text(); - if let Some(rest) = ws_text.strip_prefix('\n') { + if let Some(prev_ws) = prev_ws { + let ws_text = prev_ws.syntax().text(); + if let Some(rest) = ws_text.trim_end_matches(' ').strip_suffix('\n') { if rest.is_empty() { - editor.delete(next_ws.syntax()); + editor.delete(prev_ws.syntax()); } else { - editor.replace(next_ws.syntax(), make.whitespace(rest)); + editor.replace(prev_ws.syntax(), make.whitespace(rest)); } } }