diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-03-19 17:54:30 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-03-19 17:54:30 +0000 |
commit | b54e4b87e80a2a9d042c7c9f82abea97a8263f34 (patch) | |
tree | f05ab4767b47b09e739b364dca2ac32641666f1c /crates/syntax | |
parent | 2813afd0592957b327695e77fe75dd956700fd40 (diff) | |
parent | a61691026a169a17f62de9de6ebab197faa7c703 (diff) |
Merge #8109
8109: Make ast editing more ergonomic r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/syntax')
-rw-r--r-- | crates/syntax/src/ast/edit_in_place.rs | 41 | ||||
-rw-r--r-- | crates/syntax/src/ted.rs | 65 |
2 files changed, 66 insertions, 40 deletions
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 449b058fb..b1eed0a2c 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs | |||
@@ -8,7 +8,7 @@ use parser::T; | |||
8 | use crate::{ | 8 | use crate::{ |
9 | ast, | 9 | ast, |
10 | ted::{self, Position}, | 10 | ted::{self, Position}, |
11 | AstNode, Direction, SyntaxElement, | 11 | AstNode, Direction, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | use super::NameOwner; | 14 | use super::NameOwner; |
@@ -21,11 +21,11 @@ impl GenericParamsOwnerEdit for ast::Fn { | |||
21 | fn get_or_create_where_clause(&self) -> WhereClause { | 21 | fn get_or_create_where_clause(&self) -> WhereClause { |
22 | if self.where_clause().is_none() { | 22 | if self.where_clause().is_none() { |
23 | let position = if let Some(ty) = self.ret_type() { | 23 | let position = if let Some(ty) = self.ret_type() { |
24 | Position::after(ty.syntax().clone()) | 24 | Position::after(ty.syntax()) |
25 | } else if let Some(param_list) = self.param_list() { | 25 | } else if let Some(param_list) = self.param_list() { |
26 | Position::after(param_list.syntax().clone()) | 26 | Position::after(param_list.syntax()) |
27 | } else { | 27 | } else { |
28 | Position::last_child_of(self.syntax().clone()) | 28 | Position::last_child_of(self.syntax()) |
29 | }; | 29 | }; |
30 | create_where_clause(position) | 30 | create_where_clause(position) |
31 | } | 31 | } |
@@ -37,9 +37,9 @@ impl GenericParamsOwnerEdit for ast::Impl { | |||
37 | fn get_or_create_where_clause(&self) -> WhereClause { | 37 | fn get_or_create_where_clause(&self) -> WhereClause { |
38 | if self.where_clause().is_none() { | 38 | if self.where_clause().is_none() { |
39 | let position = if let Some(items) = self.assoc_item_list() { | 39 | let position = if let Some(items) = self.assoc_item_list() { |
40 | Position::before(items.syntax().clone()) | 40 | Position::before(items.syntax()) |
41 | } else { | 41 | } else { |
42 | Position::last_child_of(self.syntax().clone()) | 42 | Position::last_child_of(self.syntax()) |
43 | }; | 43 | }; |
44 | create_where_clause(position) | 44 | create_where_clause(position) |
45 | } | 45 | } |
@@ -51,9 +51,9 @@ impl GenericParamsOwnerEdit for ast::Trait { | |||
51 | fn get_or_create_where_clause(&self) -> WhereClause { | 51 | fn get_or_create_where_clause(&self) -> WhereClause { |
52 | if self.where_clause().is_none() { | 52 | if self.where_clause().is_none() { |
53 | let position = if let Some(items) = self.assoc_item_list() { | 53 | let position = if let Some(items) = self.assoc_item_list() { |
54 | Position::before(items.syntax().clone()) | 54 | Position::before(items.syntax()) |
55 | } else { | 55 | } else { |
56 | Position::last_child_of(self.syntax().clone()) | 56 | Position::last_child_of(self.syntax()) |
57 | }; | 57 | }; |
58 | create_where_clause(position) | 58 | create_where_clause(position) |
59 | } | 59 | } |
@@ -69,13 +69,13 @@ impl GenericParamsOwnerEdit for ast::Struct { | |||
69 | ast::FieldList::TupleFieldList(it) => Some(it), | 69 | ast::FieldList::TupleFieldList(it) => Some(it), |
70 | }); | 70 | }); |
71 | let position = if let Some(tfl) = tfl { | 71 | let position = if let Some(tfl) = tfl { |
72 | Position::after(tfl.syntax().clone()) | 72 | Position::after(tfl.syntax()) |
73 | } else if let Some(gpl) = self.generic_param_list() { | 73 | } else if let Some(gpl) = self.generic_param_list() { |
74 | Position::after(gpl.syntax().clone()) | 74 | Position::after(gpl.syntax()) |
75 | } else if let Some(name) = self.name() { | 75 | } else if let Some(name) = self.name() { |
76 | Position::after(name.syntax().clone()) | 76 | Position::after(name.syntax()) |
77 | } else { | 77 | } else { |
78 | Position::last_child_of(self.syntax().clone()) | 78 | Position::last_child_of(self.syntax()) |
79 | }; | 79 | }; |
80 | create_where_clause(position) | 80 | create_where_clause(position) |
81 | } | 81 | } |
@@ -87,11 +87,11 @@ impl GenericParamsOwnerEdit for ast::Enum { | |||
87 | fn get_or_create_where_clause(&self) -> WhereClause { | 87 | fn get_or_create_where_clause(&self) -> WhereClause { |
88 | if self.where_clause().is_none() { | 88 | if self.where_clause().is_none() { |
89 | let position = if let Some(gpl) = self.generic_param_list() { | 89 | let position = if let Some(gpl) = self.generic_param_list() { |
90 | Position::after(gpl.syntax().clone()) | 90 | Position::after(gpl.syntax()) |
91 | } else if let Some(name) = self.name() { | 91 | } else if let Some(name) = self.name() { |
92 | Position::after(name.syntax().clone()) | 92 | Position::after(name.syntax()) |
93 | } else { | 93 | } else { |
94 | Position::last_child_of(self.syntax().clone()) | 94 | Position::last_child_of(self.syntax()) |
95 | }; | 95 | }; |
96 | create_where_clause(position) | 96 | create_where_clause(position) |
97 | } | 97 | } |
@@ -100,19 +100,18 @@ impl GenericParamsOwnerEdit for ast::Enum { | |||
100 | } | 100 | } |
101 | 101 | ||
102 | fn create_where_clause(position: Position) { | 102 | fn create_where_clause(position: Position) { |
103 | let where_clause: SyntaxElement = | 103 | let where_clause = make::where_clause(empty()).clone_for_update(); |
104 | make::where_clause(empty()).clone_for_update().syntax().clone().into(); | 104 | ted::insert(position, where_clause.syntax()); |
105 | ted::insert(position, where_clause); | ||
106 | } | 105 | } |
107 | 106 | ||
108 | impl ast::WhereClause { | 107 | impl ast::WhereClause { |
109 | pub fn add_predicate(&self, predicate: ast::WherePred) { | 108 | pub fn add_predicate(&self, predicate: ast::WherePred) { |
110 | if let Some(pred) = self.predicates().last() { | 109 | if let Some(pred) = self.predicates().last() { |
111 | if !pred.syntax().siblings_with_tokens(Direction::Next).any(|it| it.kind() == T![,]) { | 110 | if !pred.syntax().siblings_with_tokens(Direction::Next).any(|it| it.kind() == T![,]) { |
112 | ted::append_child_raw(self.syntax().clone(), make::token(T![,])); | 111 | ted::append_child_raw(self.syntax(), make::token(T![,])); |
113 | } | 112 | } |
114 | } | 113 | } |
115 | ted::append_child(self.syntax().clone(), predicate.syntax().clone()) | 114 | ted::append_child(self.syntax(), predicate.syntax()) |
116 | } | 115 | } |
117 | } | 116 | } |
118 | 117 | ||
@@ -123,7 +122,7 @@ impl ast::TypeBoundList { | |||
123 | { | 122 | { |
124 | ted::remove_all(colon..=self.syntax().clone().into()) | 123 | ted::remove_all(colon..=self.syntax().clone().into()) |
125 | } else { | 124 | } else { |
126 | ted::remove(self.syntax().clone()) | 125 | ted::remove(self.syntax()) |
127 | } | 126 | } |
128 | } | 127 | } |
129 | } | 128 | } |
diff --git a/crates/syntax/src/ted.rs b/crates/syntax/src/ted.rs index 442dfa14a..be2b846b1 100644 --- a/crates/syntax/src/ted.rs +++ b/crates/syntax/src/ted.rs | |||
@@ -8,6 +8,33 @@ use parser::T; | |||
8 | 8 | ||
9 | use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; | 9 | use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; |
10 | 10 | ||
11 | /// Utility trait to allow calling `ted` functions with references or owned | ||
12 | /// nodes. Do not use outside of this module. | ||
13 | pub trait Element { | ||
14 | fn syntax_element(self) -> SyntaxElement; | ||
15 | } | ||
16 | |||
17 | impl<E: Element + Clone> Element for &'_ E { | ||
18 | fn syntax_element(self) -> SyntaxElement { | ||
19 | self.clone().syntax_element() | ||
20 | } | ||
21 | } | ||
22 | impl Element for SyntaxElement { | ||
23 | fn syntax_element(self) -> SyntaxElement { | ||
24 | self | ||
25 | } | ||
26 | } | ||
27 | impl Element for SyntaxNode { | ||
28 | fn syntax_element(self) -> SyntaxElement { | ||
29 | self.into() | ||
30 | } | ||
31 | } | ||
32 | impl Element for SyntaxToken { | ||
33 | fn syntax_element(self) -> SyntaxElement { | ||
34 | self.into() | ||
35 | } | ||
36 | } | ||
37 | |||
11 | #[derive(Debug)] | 38 | #[derive(Debug)] |
12 | pub struct Position { | 39 | pub struct Position { |
13 | repr: PositionRepr, | 40 | repr: PositionRepr, |
@@ -20,24 +47,24 @@ enum PositionRepr { | |||
20 | } | 47 | } |
21 | 48 | ||
22 | impl Position { | 49 | impl Position { |
23 | pub fn after(elem: impl Into<SyntaxElement>) -> Position { | 50 | pub fn after(elem: impl Element) -> Position { |
24 | let repr = PositionRepr::After(elem.into()); | 51 | let repr = PositionRepr::After(elem.syntax_element()); |
25 | Position { repr } | 52 | Position { repr } |
26 | } | 53 | } |
27 | pub fn before(elem: impl Into<SyntaxElement>) -> Position { | 54 | pub fn before(elem: impl Element) -> Position { |
28 | let elem = elem.into(); | 55 | let elem = elem.syntax_element(); |
29 | let repr = match elem.prev_sibling_or_token() { | 56 | let repr = match elem.prev_sibling_or_token() { |
30 | Some(it) => PositionRepr::After(it), | 57 | Some(it) => PositionRepr::After(it), |
31 | None => PositionRepr::FirstChild(elem.parent().unwrap()), | 58 | None => PositionRepr::FirstChild(elem.parent().unwrap()), |
32 | }; | 59 | }; |
33 | Position { repr } | 60 | Position { repr } |
34 | } | 61 | } |
35 | pub fn first_child_of(node: impl Into<SyntaxNode>) -> Position { | 62 | pub fn first_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position { |
36 | let repr = PositionRepr::FirstChild(node.into()); | 63 | let repr = PositionRepr::FirstChild(node.clone().into()); |
37 | Position { repr } | 64 | Position { repr } |
38 | } | 65 | } |
39 | pub fn last_child_of(node: impl Into<SyntaxNode>) -> Position { | 66 | pub fn last_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position { |
40 | let node = node.into(); | 67 | let node = node.clone().into(); |
41 | let repr = match node.last_child_or_token() { | 68 | let repr = match node.last_child_or_token() { |
42 | Some(it) => PositionRepr::After(it), | 69 | Some(it) => PositionRepr::After(it), |
43 | None => PositionRepr::FirstChild(node), | 70 | None => PositionRepr::FirstChild(node), |
@@ -46,11 +73,11 @@ impl Position { | |||
46 | } | 73 | } |
47 | } | 74 | } |
48 | 75 | ||
49 | pub fn insert(position: Position, elem: impl Into<SyntaxElement>) { | 76 | pub fn insert(position: Position, elem: impl Element) { |
50 | insert_all(position, vec![elem.into()]) | 77 | insert_all(position, vec![elem.syntax_element()]) |
51 | } | 78 | } |
52 | pub fn insert_raw(position: Position, elem: impl Into<SyntaxElement>) { | 79 | pub fn insert_raw(position: Position, elem: impl Element) { |
53 | insert_all_raw(position, vec![elem.into()]) | 80 | insert_all_raw(position, vec![elem.syntax_element()]) |
54 | } | 81 | } |
55 | pub fn insert_all(position: Position, mut elements: Vec<SyntaxElement>) { | 82 | pub fn insert_all(position: Position, mut elements: Vec<SyntaxElement>) { |
56 | if let Some(first) = elements.first() { | 83 | if let Some(first) = elements.first() { |
@@ -73,17 +100,17 @@ pub fn insert_all_raw(position: Position, elements: Vec<SyntaxElement>) { | |||
73 | parent.splice_children(index..index, elements); | 100 | parent.splice_children(index..index, elements); |
74 | } | 101 | } |
75 | 102 | ||
76 | pub fn remove(elem: impl Into<SyntaxElement>) { | 103 | pub fn remove(elem: impl Element) { |
77 | let elem = elem.into(); | 104 | let elem = elem.syntax_element(); |
78 | remove_all(elem.clone()..=elem) | 105 | remove_all(elem.clone()..=elem) |
79 | } | 106 | } |
80 | pub fn remove_all(range: RangeInclusive<SyntaxElement>) { | 107 | pub fn remove_all(range: RangeInclusive<SyntaxElement>) { |
81 | replace_all(range, Vec::new()) | 108 | replace_all(range, Vec::new()) |
82 | } | 109 | } |
83 | 110 | ||
84 | pub fn replace(old: impl Into<SyntaxElement>, new: impl Into<SyntaxElement>) { | 111 | pub fn replace(old: impl Element, new: impl Element) { |
85 | let old = old.into(); | 112 | let old = old.syntax_element(); |
86 | replace_all(old.clone()..=old, vec![new.into()]) | 113 | replace_all(old.clone()..=old, vec![new.syntax_element()]) |
87 | } | 114 | } |
88 | pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) { | 115 | pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) { |
89 | let start = range.start().index(); | 116 | let start = range.start().index(); |
@@ -92,11 +119,11 @@ pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement> | |||
92 | parent.splice_children(start..end + 1, new) | 119 | parent.splice_children(start..end + 1, new) |
93 | } | 120 | } |
94 | 121 | ||
95 | pub fn append_child(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) { | 122 | pub fn append_child(node: &(impl Into<SyntaxNode> + Clone), child: impl Element) { |
96 | let position = Position::last_child_of(node); | 123 | let position = Position::last_child_of(node); |
97 | insert(position, child) | 124 | insert(position, child) |
98 | } | 125 | } |
99 | pub fn append_child_raw(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) { | 126 | pub fn append_child_raw(node: &(impl Into<SyntaxNode> + Clone), child: impl Element) { |
100 | let position = Position::last_child_of(node); | 127 | let position = Position::last_child_of(node); |
101 | insert_raw(position, child) | 128 | insert_raw(position, child) |
102 | } | 129 | } |