Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/syntax/src/syntax_editor/edits.rs')
| -rw-r--r-- | crates/syntax/src/syntax_editor/edits.rs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/crates/syntax/src/syntax_editor/edits.rs b/crates/syntax/src/syntax_editor/edits.rs index d66ea8aa28..9090f7c9eb 100644 --- a/crates/syntax/src/syntax_editor/edits.rs +++ b/crates/syntax/src/syntax_editor/edits.rs @@ -92,6 +92,42 @@ fn get_or_insert_comma_after(editor: &mut SyntaxEditor, syntax: &SyntaxNode) -> } } +impl ast::AssocItemList { + /// Adds a new associated item after all of the existing associated items. + /// + /// Attention! This function does align the first line of `item` with respect to `self`, + /// but it does _not_ change indentation of other lines (if any). + pub fn add_items(&self, editor: &mut SyntaxEditor, items: Vec<ast::AssocItem>) { + let (indent, position, whitespace) = match self.assoc_items().last() { + Some(last_item) => ( + IndentLevel::from_node(last_item.syntax()), + Position::after(last_item.syntax()), + "\n\n", + ), + None => match self.l_curly_token() { + Some(l_curly) => { + normalize_ws_between_braces(editor, self.syntax()); + (IndentLevel::from_token(&l_curly) + 1, Position::after(&l_curly), "\n") + } + None => (IndentLevel::single(), Position::last_child_of(self.syntax()), "\n"), + }, + }; + + let elements: Vec<SyntaxElement> = items + .into_iter() + .enumerate() + .flat_map(|(i, item)| { + let whitespace = if i != 0 { "\n\n" } else { whitespace }; + vec![ + make::tokens::whitespace(&format!("{whitespace}{indent}")).into(), + item.syntax().clone().into(), + ] + }) + .collect(); + editor.insert_all(position, elements); + } +} + impl ast::VariantList { pub fn add_variant(&self, editor: &mut SyntaxEditor, variant: &ast::Variant) { let make = SyntaxFactory::without_mappings(); @@ -117,6 +153,23 @@ impl ast::VariantList { } } +impl ast::Fn { + pub fn replace_or_insert_body(&self, editor: &mut SyntaxEditor, body: ast::BlockExpr) { + if let Some(old_body) = self.body() { + editor.replace(old_body.syntax(), body.syntax()); + } else { + let single_space = make::tokens::single_space(); + let elements = vec![single_space.into(), body.syntax().clone().into()]; + + if let Some(semicolon) = self.semicolon_token() { + editor.replace_with_many(semicolon, elements); + } else { + editor.insert_all(Position::last_child_of(self.syntax()), elements); + } + } + } +} + fn normalize_ws_between_braces(editor: &mut SyntaxEditor, node: &SyntaxNode) -> Option<()> { let make = SyntaxFactory::without_mappings(); let l = node @@ -148,6 +201,15 @@ pub trait Removable: AstNode { fn remove(&self, editor: &mut SyntaxEditor); } +impl Removable for ast::TypeBoundList { + fn remove(&self, editor: &mut SyntaxEditor) { + match self.syntax().siblings_with_tokens(Direction::Prev).find(|it| it.kind() == T![:]) { + Some(colon) => editor.delete_all(colon..=self.syntax().clone().into()), + None => editor.delete(self.syntax()), + } + } +} + impl Removable for ast::Use { fn remove(&self, editor: &mut SyntaxEditor) { let make = SyntaxFactory::without_mappings(); |