internal: use more mutable APIs

This commit is contained in:
Aleksey Kladov 2021-05-14 20:00:35 +03:00
parent 6c21d04307
commit 883dd1568f
3 changed files with 33 additions and 53 deletions

View file

@ -17,7 +17,7 @@ use syntax::{
ast::AttrsOwner,
ast::NameOwner,
ast::{self, edit, make, ArgListOwner, GenericParamsOwner},
AstNode, Direction, SmolStr,
ted, AstNode, Direction, SmolStr,
SyntaxKind::*,
SyntaxNode, TextSize, T,
};
@ -139,34 +139,32 @@ pub fn add_trait_assoc_items_to_impl(
.into_iter()
.map(|it| it.clone_for_update())
.inspect(|it| ast_transform::apply(&*ast_transform, it))
.map(|it| match it {
ast::AssocItem::Fn(def) => ast::AssocItem::Fn(add_body(def)),
ast::AssocItem::TypeAlias(def) => ast::AssocItem::TypeAlias(def.remove_bounds()),
_ => it,
})
.map(|it| edit::remove_attrs_and_docs(&it).clone_subtree().clone_for_update());
let res = impl_.clone_for_update();
let assoc_item_list = res.get_or_create_assoc_item_list();
let mut first_item = None;
for item in items {
if first_item.is_none() {
first_item = Some(item.clone())
}
assoc_item_list.add_item(item)
}
return (res, first_item.unwrap());
fn add_body(fn_def: ast::Fn) -> ast::Fn {
match fn_def.body() {
Some(_) => fn_def,
None => {
first_item.get_or_insert_with(|| item.clone());
match &item {
ast::AssocItem::Fn(fn_) if fn_.body().is_none() => {
let body = make::block_expr(None, Some(make::ext::expr_todo()))
.indent(edit::IndentLevel(1));
fn_def.with_body(body)
ted::replace(fn_.get_or_create_body().syntax(), body.clone_for_update().syntax())
}
ast::AssocItem::TypeAlias(type_alias) => {
if let Some(type_bound_list) = type_alias.type_bound_list() {
type_bound_list.remove()
}
}
_ => {}
}
assoc_item_list.add_item(item)
}
(res, first_item.unwrap())
}
#[derive(Clone, Copy, Debug)]

View file

@ -13,7 +13,7 @@ use crate::{
ast::{
self,
make::{self, tokens},
AstNode, TypeBoundsOwner,
AstNode,
},
ted, AstToken, Direction, InsertPosition, NodeOrToken, SmolStr, SyntaxElement, SyntaxKind,
SyntaxKind::{ATTR, COMMENT, WHITESPACE},
@ -29,25 +29,6 @@ impl ast::BinExpr {
}
}
impl ast::Fn {
#[must_use]
pub fn with_body(&self, body: ast::BlockExpr) -> ast::Fn {
let mut to_insert: ArrayVec<SyntaxElement, 2> = ArrayVec::new();
let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() {
old_body.syntax().clone().into()
} else if let Some(semi) = self.semicolon_token() {
to_insert.push(make::tokens::single_space().into());
semi.into()
} else {
to_insert.push(make::tokens::single_space().into());
to_insert.push(body.syntax().clone().into());
return self.insert_children(InsertPosition::Last, to_insert);
};
to_insert.push(body.syntax().clone().into());
self.replace_children(single_node(old_body_or_semi), to_insert)
}
}
fn make_multiline<N>(node: N) -> N
where
N: AstNode + Clone,
@ -156,21 +137,6 @@ impl ast::RecordExprFieldList {
}
}
impl ast::TypeAlias {
#[must_use]
pub fn remove_bounds(&self) -> ast::TypeAlias {
let colon = match self.colon_token() {
Some(it) => it,
None => return self.clone(),
};
let end = match self.type_bound_list() {
Some(it) => it.syntax().clone().into(),
None => colon.clone().into(),
};
self.replace_children(colon.into()..=end, iter::empty())
}
}
impl ast::Path {
#[must_use]
pub fn with_segment(&self, segment: ast::PathSegment) -> ast::Path {

View file

@ -330,6 +330,22 @@ impl ast::AssocItemList {
}
}
impl ast::Fn {
pub fn get_or_create_body(&self) -> ast::BlockExpr {
if self.body().is_none() {
let body = make::ext::empty_block_expr().clone_for_update();
match self.semicolon_token() {
Some(semi) => {
ted::replace(semi, body.syntax());
ted::insert(Position::before(body.syntax), make::tokens::single_space());
}
None => ted::append_child(self.syntax(), body.syntax()),
}
}
self.body().unwrap()
}
}
#[cfg(test)]
mod tests {
use std::fmt;