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