1 //! Primitive tree editor, ed for trees.
3 //! The `_raw`-suffixed functions insert elements as is, unsuffixed versions fix
4 //! up elements around the edges.
5 use std::{mem, ops::RangeInclusive};
10 ast::{self, edit::IndentLevel, make, AstNode},
11 SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken,
14 /// Utility trait to allow calling `ted` functions with references or owned
15 /// nodes. Do not use outside of this module.
17 fn syntax_element(self) -> SyntaxElement;
20 impl<E: Element + Clone> Element for &'_ E {
21 fn syntax_element(self) -> SyntaxElement {
22 self.clone().syntax_element()
25 impl Element for SyntaxElement {
26 fn syntax_element(self) -> SyntaxElement {
30 impl Element for SyntaxNode {
31 fn syntax_element(self) -> SyntaxElement {
35 impl Element for SyntaxToken {
36 fn syntax_element(self) -> SyntaxElement {
48 FirstChild(SyntaxNode),
53 pub fn after(elem: impl Element) -> Position {
54 let repr = PositionRepr::After(elem.syntax_element());
57 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()),
65 pub fn first_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position {
66 let repr = PositionRepr::FirstChild(node.clone().into());
69 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),
79 pub fn insert(position: Position, elem: impl Element) {
80 insert_all(position, vec![elem.syntax_element()])
82 pub fn insert_raw(position: Position, elem: impl Element) {
83 insert_all_raw(position, vec![elem.syntax_element()])
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())
91 if let Some(last) = elements.last() {
92 if let Some(ws) = ws_after(&position, last) {
93 elements.push(ws.into())
96 insert_all_raw(position, elements)
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),
103 parent.splice_children(index..index, elements);
106 pub fn remove(elem: impl Element) {
107 elem.syntax_element().detach()
109 pub fn remove_all(range: RangeInclusive<SyntaxElement>) {
110 replace_all(range, Vec::new())
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() {
117 if first.index() > last.index() {
118 mem::swap(&mut first, &mut last)
120 remove_all(first..=last)
122 None => remove(first),
127 pub fn replace(old: impl Element, new: impl Element) {
128 replace_with_many(old, vec![new.syntax_element()])
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)
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)
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)
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)
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) if it.kind() == SyntaxKind::L_CURLY => {
154 if new.kind() == SyntaxKind::USE {
155 if let Some(item_list) = it.parent().and_then(ast::ItemList::cast) {
156 let mut indent = IndentLevel::from_element(&item_list.syntax().clone().into());
158 return Some(make::tokens::whitespace(&format!("\n{}", indent)));
163 PositionRepr::After(it) => it,
165 ws_between(prev, new)
167 fn ws_after(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> {
168 let next = match &position.repr {
169 PositionRepr::FirstChild(parent) => parent.first_child_or_token()?,
170 PositionRepr::After(sibling) => sibling.next_sibling_or_token()?,
172 ws_between(new, &next)
174 fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken> {
175 if left.kind() == SyntaxKind::WHITESPACE || right.kind() == SyntaxKind::WHITESPACE {
178 if right.kind() == T![;] || right.kind() == T![,] {
181 if left.kind() == T![<] || right.kind() == T![>] {
184 if left.kind() == T![&] && right.kind() == SyntaxKind::LIFETIME {
187 if right.kind() == SyntaxKind::GENERIC_ARG_LIST {
191 if right.kind() == SyntaxKind::USE {
192 let mut indent = IndentLevel::from_element(left);
193 if left.kind() == SyntaxKind::USE {
194 indent.0 = IndentLevel::from_element(right).0.max(indent.0);
196 return Some(make::tokens::whitespace(&format!("\n{}", indent)));
198 Some(make::tokens::single_space())