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 | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/crates/syntax/src/syntax_editor/edits.rs b/crates/syntax/src/syntax_editor/edits.rs new file mode 100644 index 0000000000..73196f5cb1 --- /dev/null +++ b/crates/syntax/src/syntax_editor/edits.rs @@ -0,0 +1,72 @@ +//! Structural editing for ast using `SyntaxEditor` + +use crate::{ + ast::make, ast::AstNode, ast::Fn, ast::GenericParam, ast::HasGenericParams, ast::HasName, + syntax_editor::Position, syntax_editor::SyntaxEditor, SyntaxKind, +}; + +impl SyntaxEditor { + /// Adds a new generic param to the function using `SyntaxEditor` + pub fn add_generic_param(&mut self, function: &Fn, new_param: GenericParam) { + match function.generic_param_list() { + Some(generic_param_list) => match generic_param_list.generic_params().last() { + Some(last_param) => { + // There exists a generic param list and it's not empty + let position = generic_param_list.r_angle_token().map_or_else( + || Position::last_child_of(function.syntax()), + Position::before, + ); + + if last_param + .syntax() + .next_sibling_or_token() + .map_or(false, |it| it.kind() == SyntaxKind::COMMA) + { + self.insert( + Position::after(last_param.syntax()), + new_param.syntax().clone(), + ); + self.insert( + Position::after(last_param.syntax()), + make::token(SyntaxKind::WHITESPACE), + ); + self.insert( + Position::after(last_param.syntax()), + make::token(SyntaxKind::COMMA), + ); + } else { + let elements = vec![ + make::token(SyntaxKind::COMMA).into(), + make::token(SyntaxKind::WHITESPACE).into(), + new_param.syntax().clone().into(), + ]; + self.insert_all(position, elements); + } + } + None => { + // There exists a generic param list but it's empty + let position = Position::after(generic_param_list.l_angle_token().unwrap()); + self.insert(position, new_param.syntax()); + } + }, + None => { + // There was no generic param list + let position = if let Some(name) = function.name() { + Position::after(name.syntax) + } else if let Some(fn_token) = function.fn_token() { + Position::after(fn_token) + } else if let Some(param_list) = function.param_list() { + Position::before(param_list.syntax) + } else { + Position::last_child_of(function.syntax()) + }; + let elements = vec![ + make::token(SyntaxKind::L_ANGLE).into(), + new_param.syntax().clone().into(), + make::token(SyntaxKind::R_ANGLE).into(), + ]; + self.insert_all(position, elements); + } + } + } +} |