aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax/src/ast/edit_in_place.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/syntax/src/ast/edit_in_place.rs')
-rw-r--r--crates/syntax/src/ast/edit_in_place.rs105
1 files changed, 105 insertions, 0 deletions
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs
new file mode 100644
index 000000000..06cde591d
--- /dev/null
+++ b/crates/syntax/src/ast/edit_in_place.rs
@@ -0,0 +1,105 @@
1//! Structural editing for ast.
2
3use std::iter::empty;
4
5use ast::{edit::AstNodeEdit, make, GenericParamsOwner, WhereClause};
6use parser::T;
7
8use crate::{
9 ast,
10 ted::{self, Position},
11 AstNode, Direction, SyntaxKind,
12};
13
14use super::NameOwner;
15
16pub trait GenericParamsOwnerEdit: ast::GenericParamsOwner + AstNodeEdit {
17 fn get_or_create_where_clause(&self) -> ast::WhereClause;
18}
19
20impl GenericParamsOwnerEdit for ast::Fn {
21 fn get_or_create_where_clause(&self) -> WhereClause {
22 if self.where_clause().is_none() {
23 let position = if let Some(ty) = self.ret_type() {
24 Position::after(ty.syntax().clone())
25 } else if let Some(param_list) = self.param_list() {
26 Position::after(param_list.syntax().clone())
27 } else {
28 Position::last_child_of(self.syntax().clone())
29 };
30 create_where_clause(position)
31 }
32 self.where_clause().unwrap()
33 }
34}
35
36impl GenericParamsOwnerEdit for ast::Impl {
37 fn get_or_create_where_clause(&self) -> WhereClause {
38 if self.where_clause().is_none() {
39 let position = if let Some(ty) = self.self_ty() {
40 Position::after(ty.syntax().clone())
41 } else {
42 Position::last_child_of(self.syntax().clone())
43 };
44 create_where_clause(position)
45 }
46 self.where_clause().unwrap()
47 }
48}
49impl GenericParamsOwnerEdit for ast::Struct {
50 fn get_or_create_where_clause(&self) -> WhereClause {
51 if self.where_clause().is_none() {
52 let tfl = self.field_list().and_then(|fl| match fl {
53 ast::FieldList::RecordFieldList(_) => None,
54 ast::FieldList::TupleFieldList(it) => Some(it),
55 });
56 let position = if let Some(tfl) = tfl {
57 Position::after(tfl.syntax().clone())
58 } else if let Some(gpl) = self.generic_param_list() {
59 Position::after(gpl.syntax().clone())
60 } else if let Some(name) = self.name() {
61 Position::after(name.syntax().clone())
62 } else {
63 Position::last_child_of(self.syntax().clone())
64 };
65 create_where_clause(position)
66 }
67 self.where_clause().unwrap()
68 }
69}
70
71fn create_where_clause(position: Position) {
72 let elements = vec![
73 make::tokens::single_space().into(),
74 make::where_clause(empty()).clone_for_update().syntax().clone().into(),
75 ];
76 ted::insert_all(position, elements);
77}
78
79impl ast::WhereClause {
80 pub fn add_predicate(&self, predicate: ast::WherePred) {
81 if let Some(pred) = self.predicates().last() {
82 if !pred.syntax().siblings_with_tokens(Direction::Next).any(|it| it.kind() == T![,]) {
83 ted::append_child(self.syntax().clone(), make::token(T![,]));
84 }
85 }
86 if self.syntax().children_with_tokens().last().map(|it| it.kind())
87 != Some(SyntaxKind::WHITESPACE)
88 {
89 ted::append_child(self.syntax().clone(), make::tokens::single_space());
90 }
91 ted::append_child(self.syntax().clone(), predicate.syntax().clone())
92 }
93}
94
95impl ast::TypeBoundList {
96 pub fn remove(&self) {
97 if let Some(colon) =
98 self.syntax().siblings_with_tokens(Direction::Prev).find(|it| it.kind() == T![:])
99 {
100 ted::remove_all(colon..=self.syntax().clone().into())
101 } else {
102 ted::remove(self.syntax().clone())
103 }
104 }
105}