1 //! Primitive tree editor, ed for trees.
2 //!
3 //! The `_raw`-suffixed functions insert elements as is, unsuffixed versions fix
4 //! up elements around the edges.
5 use std::{mem, ops::RangeInclusive};
6
7 use parser::T;
8
9 use crate::{
10 ast::{self, edit::IndentLevel, make, AstNode},
11 SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken,
12 };
13
14 /// Utility trait to allow calling `ted` functions with references or owned
15 /// nodes. Do not use outside of this module.
16 pub trait Element {
syntax_element(self) -> SyntaxElement17 fn syntax_element(self) -> SyntaxElement;
18 }
19
20 impl<E: Element + Clone> Element for &'_ E {
syntax_element(self) -> SyntaxElement21 fn syntax_element(self) -> SyntaxElement {
22 self.clone().syntax_element()
23 }
24 }
25 impl Element for SyntaxElement {
syntax_element(self) -> SyntaxElement26 fn syntax_element(self) -> SyntaxElement {
27 self
28 }
29 }
30 impl Element for SyntaxNode {
syntax_element(self) -> SyntaxElement31 fn syntax_element(self) -> SyntaxElement {
32 self.into()
33 }
34 }
35 impl Element for SyntaxToken {
syntax_element(self) -> SyntaxElement36 fn syntax_element(self) -> SyntaxElement {
37 self.into()
38 }
39 }
40
41 #[derive(Debug)]
42 pub struct Position {
43 repr: PositionRepr,
44 }
45
46 #[derive(Debug)]
47 enum PositionRepr {
48 FirstChild(SyntaxNode),
49 After(SyntaxElement),
50 }
51
52 impl Position {
after(elem: impl Element) -> Position53 pub fn after(elem: impl Element) -> Position {
54 let repr = PositionRepr::After(elem.syntax_element());
55 Position { repr }
56 }
before(elem: impl Element) -> Position57 pub fn before(elem: impl Element) -> Position {
58 let elem = elem.syntax_element();
59 let repr = match elem.prev_sibling_or_token() {
60 Some(it) => PositionRepr::After(it),
61 None => PositionRepr::FirstChild(elem.parent().unwrap()),
62 };
63 Position { repr }
64 }
first_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position65 pub fn first_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position {
66 let repr = PositionRepr::FirstChild(node.clone().into());
67 Position { repr }
68 }
last_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position69 pub fn last_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position {
70 let node = node.clone().into();
71 let repr = match node.last_child_or_token() {
72 Some(it) => PositionRepr::After(it),
73 None => PositionRepr::FirstChild(node),
74 };
75 Position { repr }
76 }
77 }
78
insert(position: Position, elem: impl Element)79 pub fn insert(position: Position, elem: impl Element) {
80 insert_all(position, vec![elem.syntax_element()]);
81 }
insert_raw(position: Position, elem: impl Element)82 pub fn insert_raw(position: Position, elem: impl Element) {
83 insert_all_raw(position, vec![elem.syntax_element()]);
84 }
insert_all(position: Position, mut elements: Vec<SyntaxElement>)85 pub fn insert_all(position: Position, mut elements: Vec<SyntaxElement>) {
86 if let Some(first) = elements.first() {
87 if let Some(ws) = ws_before(&position, first) {
88 elements.insert(0, ws.into());
89 }
90 }
91 if let Some(last) = elements.last() {
92 if let Some(ws) = ws_after(&position, last) {
93 elements.push(ws.into());
94 }
95 }
96 insert_all_raw(position, elements);
97 }
insert_all_raw(position: Position, elements: Vec<SyntaxElement>)98 pub fn insert_all_raw(position: Position, elements: Vec<SyntaxElement>) {
99 let (parent, index) = match position.repr {
100 PositionRepr::FirstChild(parent) => (parent, 0),
101 PositionRepr::After(child) => (child.parent().unwrap(), child.index() + 1),
102 };
103 parent.splice_children(index..index, elements);
104 }
105
remove(elem: impl Element)106 pub fn remove(elem: impl Element) {
107 elem.syntax_element().detach();
108 }
remove_all(range: RangeInclusive<SyntaxElement>)109 pub fn remove_all(range: RangeInclusive<SyntaxElement>) {
110 replace_all(range, Vec::new());
111 }
remove_all_iter(range: impl IntoIterator<Item = SyntaxElement>)112 pub fn remove_all_iter(range: impl IntoIterator<Item = SyntaxElement>) {
113 let mut it = range.into_iter();
114 if let Some(mut first) = it.next() {
115 match it.last() {
116 Some(mut last) => {
117 if first.index() > last.index() {
118 mem::swap(&mut first, &mut last);
119 }
120 remove_all(first..=last);
121 }
122 None => remove(first),
123 }
124 }
125 }
126
replace(old: impl Element, new: impl Element)127 pub fn replace(old: impl Element, new: impl Element) {
128 replace_with_many(old, vec![new.syntax_element()]);
129 }
replace_with_many(old: impl Element, new: Vec<SyntaxElement>)130 pub fn replace_with_many(old: impl Element, new: Vec<SyntaxElement>) {
131 let old = old.syntax_element();
132 replace_all(old.clone()..=old, new);
133 }
replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>)134 pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) {
135 let start = range.start().index();
136 let end = range.end().index();
137 let parent = range.start().parent().unwrap();
138 parent.splice_children(start..end + 1, new);
139 }
140
append_child(node: &(impl Into<SyntaxNode> + Clone), child: impl Element)141 pub fn append_child(node: &(impl Into<SyntaxNode> + Clone), child: impl Element) {
142 let position = Position::last_child_of(node);
143 insert(position, child);
144 }
append_child_raw(node: &(impl Into<SyntaxNode> + Clone), child: impl Element)145 pub fn append_child_raw(node: &(impl Into<SyntaxNode> + Clone), child: impl Element) {
146 let position = Position::last_child_of(node);
147 insert_raw(position, child);
148 }
149
ws_before(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken>150 fn ws_before(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> {
151 let prev = match &position.repr {
152 PositionRepr::FirstChild(_) => return None,
153 PositionRepr::After(it) => it,
154 };
155
156 if prev.kind() == T!['{'] && new.kind() == SyntaxKind::USE {
157 if let Some(item_list) = prev.parent().and_then(ast::ItemList::cast) {
158 let mut indent = IndentLevel::from_element(&item_list.syntax().clone().into());
159 indent.0 += 1;
160 return Some(make::tokens::whitespace(&format!("\n{indent}")));
161 }
162 }
163
164 if prev.kind() == T!['{'] && ast::Stmt::can_cast(new.kind()) {
165 if let Some(stmt_list) = prev.parent().and_then(ast::StmtList::cast) {
166 let mut indent = IndentLevel::from_element(&stmt_list.syntax().clone().into());
167 indent.0 += 1;
168 return Some(make::tokens::whitespace(&format!("\n{indent}")));
169 }
170 }
171
172 ws_between(prev, new)
173 }
ws_after(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken>174 fn ws_after(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> {
175 let next = match &position.repr {
176 PositionRepr::FirstChild(parent) => parent.first_child_or_token()?,
177 PositionRepr::After(sibling) => sibling.next_sibling_or_token()?,
178 };
179 ws_between(new, &next)
180 }
ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken>181 fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken> {
182 if left.kind() == SyntaxKind::WHITESPACE || right.kind() == SyntaxKind::WHITESPACE {
183 return None;
184 }
185 if right.kind() == T![;] || right.kind() == T![,] {
186 return None;
187 }
188 if left.kind() == T![<] || right.kind() == T![>] {
189 return None;
190 }
191 if left.kind() == T![&] && right.kind() == SyntaxKind::LIFETIME {
192 return None;
193 }
194 if right.kind() == SyntaxKind::GENERIC_ARG_LIST {
195 return None;
196 }
197
198 if right.kind() == SyntaxKind::USE {
199 let mut indent = IndentLevel::from_element(left);
200 if left.kind() == SyntaxKind::USE {
201 indent.0 = IndentLevel::from_element(right).0.max(indent.0);
202 }
203 return Some(make::tokens::whitespace(&format!("\n{indent}")));
204 }
205 Some(make::tokens::single_space())
206 }
207