diff options
Diffstat (limited to 'crates/syntax/src/ast/edit.rs')
-rw-r--r-- | crates/syntax/src/ast/edit.rs | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs index 823475333..1ccb4de6a 100644 --- a/crates/syntax/src/ast/edit.rs +++ b/crates/syntax/src/ast/edit.rs | |||
@@ -459,6 +459,72 @@ impl ast::MatchArmList { | |||
459 | } | 459 | } |
460 | } | 460 | } |
461 | 461 | ||
462 | impl ast::GenericParamList { | ||
463 | #[must_use] | ||
464 | pub fn append_params(&self, params: impl IntoIterator<Item = ast::GenericParam>) -> Self { | ||
465 | let mut res = self.clone(); | ||
466 | params.into_iter().for_each(|it| res = res.append_param(it)); | ||
467 | res | ||
468 | } | ||
469 | |||
470 | #[must_use] | ||
471 | pub fn append_param(&self, item: ast::GenericParam) -> Self { | ||
472 | let is_multiline = self.syntax().text().contains_char('\n'); | ||
473 | let ws; | ||
474 | let space = if is_multiline { | ||
475 | ws = tokens::WsBuilder::new(&format!( | ||
476 | "\n{} ", | ||
477 | leading_indent(self.syntax()).unwrap_or_default() | ||
478 | )); | ||
479 | ws.ws() | ||
480 | } else { | ||
481 | tokens::single_space() | ||
482 | }; | ||
483 | |||
484 | let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new(); | ||
485 | to_insert.push(space.into()); | ||
486 | to_insert.push(item.syntax().clone().into()); | ||
487 | to_insert.push(make::token(T![,]).into()); | ||
488 | |||
489 | macro_rules! after_l_angle { | ||
490 | () => {{ | ||
491 | let anchor = match self.l_angle_token() { | ||
492 | Some(it) => it.into(), | ||
493 | None => return self.clone(), | ||
494 | }; | ||
495 | InsertPosition::After(anchor) | ||
496 | }}; | ||
497 | } | ||
498 | |||
499 | macro_rules! after_field { | ||
500 | ($anchor:expr) => { | ||
501 | if let Some(comma) = $anchor | ||
502 | .syntax() | ||
503 | .siblings_with_tokens(Direction::Next) | ||
504 | .find(|it| it.kind() == T![,]) | ||
505 | { | ||
506 | InsertPosition::After(comma) | ||
507 | } else { | ||
508 | to_insert.insert(0, make::token(T![,]).into()); | ||
509 | InsertPosition::After($anchor.syntax().clone().into()) | ||
510 | } | ||
511 | }; | ||
512 | }; | ||
513 | |||
514 | if !is_multiline { | ||
515 | // don't insert comma before angle | ||
516 | to_insert.pop(); | ||
517 | } | ||
518 | |||
519 | let position = match self.generic_params().last() { | ||
520 | Some(it) => after_field!(it), | ||
521 | None => after_l_angle!(), | ||
522 | }; | ||
523 | |||
524 | self.insert_children(position, to_insert) | ||
525 | } | ||
526 | } | ||
527 | |||
462 | #[must_use] | 528 | #[must_use] |
463 | pub fn remove_attrs_and_docs<N: ast::AttrsOwner>(node: &N) -> N { | 529 | pub fn remove_attrs_and_docs<N: ast::AttrsOwner>(node: &N) -> N { |
464 | N::cast(remove_attrs_and_docs_inner(node.syntax().clone())).unwrap() | 530 | N::cast(remove_attrs_and_docs_inner(node.syntax().clone())).unwrap() |