• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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