aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'crates/syntax')
-rw-r--r--crates/syntax/src/ast/edit.rs66
-rw-r--r--crates/syntax/src/ast/make.rs15
2 files changed, 81 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
462impl 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]
463pub fn remove_attrs_and_docs<N: ast::AttrsOwner>(node: &N) -> N { 529pub 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()
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index c2c938ad1..7329e3039 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -294,6 +294,21 @@ pub fn param_list(pats: impl IntoIterator<Item = ast::Param>) -> ast::ParamList
294 ast_from_text(&format!("fn f({}) {{ }}", args)) 294 ast_from_text(&format!("fn f({}) {{ }}", args))
295} 295}
296 296
297pub fn generic_param(name: String, ty: Option<String>) -> ast::GenericParam {
298 let bound = match ty {
299 Some(it) => format!(": {}", it),
300 None => String::new(),
301 };
302 ast_from_text(&format!("fn f<{}{}>() {{ }}", name, bound))
303}
304
305pub fn generic_param_list(
306 pats: impl IntoIterator<Item = ast::GenericParam>,
307) -> ast::GenericParamList {
308 let args = pats.into_iter().join(", ");
309 ast_from_text(&format!("fn f<{}>() {{ }}", args))
310}
311
297pub fn visibility_pub_crate() -> ast::Visibility { 312pub fn visibility_pub_crate() -> ast::Visibility {
298 ast_from_text("pub(crate) struct S") 313 ast_from_text("pub(crate) struct S")
299} 314}