diff options
Diffstat (limited to 'crates/ra_syntax/src/syntax_node.rs')
-rw-r--r-- | crates/ra_syntax/src/syntax_node.rs | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs new file mode 100644 index 000000000..ed48739f8 --- /dev/null +++ b/crates/ra_syntax/src/syntax_node.rs | |||
@@ -0,0 +1,223 @@ | |||
1 | mod builder; | ||
2 | pub mod syntax_error; | ||
3 | mod syntax_text; | ||
4 | |||
5 | use std::{fmt, borrow::Borrow}; | ||
6 | |||
7 | use self::syntax_text::SyntaxText; | ||
8 | use crate::{SmolStr, SyntaxKind, TextRange}; | ||
9 | use rowan::{Types, TransparentNewType}; | ||
10 | |||
11 | pub(crate) use self::builder::GreenBuilder; | ||
12 | pub use self::syntax_error::{SyntaxError, SyntaxErrorKind, Location}; | ||
13 | pub use rowan::WalkEvent; | ||
14 | |||
15 | #[derive(Debug, Clone, Copy)] | ||
16 | pub enum RaTypes {} | ||
17 | impl Types for RaTypes { | ||
18 | type Kind = SyntaxKind; | ||
19 | type RootData = Vec<SyntaxError>; | ||
20 | } | ||
21 | |||
22 | pub type GreenNode = rowan::GreenNode<RaTypes>; | ||
23 | |||
24 | #[derive(PartialEq, Eq, Hash)] | ||
25 | pub struct TreeArc<T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>>( | ||
26 | pub(crate) rowan::TreeArc<RaTypes, T>, | ||
27 | ); | ||
28 | |||
29 | impl<T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>> Borrow<T> for TreeArc<T> { | ||
30 | fn borrow(&self) -> &T { | ||
31 | &*self | ||
32 | } | ||
33 | } | ||
34 | |||
35 | impl<T> TreeArc<T> | ||
36 | where | ||
37 | T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>, | ||
38 | { | ||
39 | pub(crate) fn cast<U>(this: TreeArc<T>) -> TreeArc<U> | ||
40 | where | ||
41 | U: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>, | ||
42 | { | ||
43 | TreeArc(rowan::TreeArc::cast(this.0)) | ||
44 | } | ||
45 | } | ||
46 | |||
47 | impl<T> std::ops::Deref for TreeArc<T> | ||
48 | where | ||
49 | T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>, | ||
50 | { | ||
51 | type Target = T; | ||
52 | fn deref(&self) -> &T { | ||
53 | self.0.deref() | ||
54 | } | ||
55 | } | ||
56 | |||
57 | impl<T> PartialEq<T> for TreeArc<T> | ||
58 | where | ||
59 | T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>, | ||
60 | T: PartialEq<T>, | ||
61 | { | ||
62 | fn eq(&self, other: &T) -> bool { | ||
63 | let t: &T = self; | ||
64 | t == other | ||
65 | } | ||
66 | } | ||
67 | |||
68 | impl<T> Clone for TreeArc<T> | ||
69 | where | ||
70 | T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>, | ||
71 | { | ||
72 | fn clone(&self) -> TreeArc<T> { | ||
73 | TreeArc(self.0.clone()) | ||
74 | } | ||
75 | } | ||
76 | |||
77 | impl<T> fmt::Debug for TreeArc<T> | ||
78 | where | ||
79 | T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>, | ||
80 | T: fmt::Debug, | ||
81 | { | ||
82 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||
83 | fmt::Debug::fmt(&self.0, fmt) | ||
84 | } | ||
85 | } | ||
86 | |||
87 | #[derive(PartialEq, Eq, Hash)] | ||
88 | #[repr(transparent)] | ||
89 | pub struct SyntaxNode(pub(crate) rowan::SyntaxNode<RaTypes>); | ||
90 | unsafe impl TransparentNewType for SyntaxNode { | ||
91 | type Repr = rowan::SyntaxNode<RaTypes>; | ||
92 | } | ||
93 | |||
94 | impl SyntaxNode { | ||
95 | pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> TreeArc<SyntaxNode> { | ||
96 | let ptr = TreeArc(rowan::SyntaxNode::new(green, errors)); | ||
97 | TreeArc::cast(ptr) | ||
98 | } | ||
99 | } | ||
100 | |||
101 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
102 | pub enum Direction { | ||
103 | Next, | ||
104 | Prev, | ||
105 | } | ||
106 | |||
107 | impl SyntaxNode { | ||
108 | pub fn leaf_text(&self) -> Option<&SmolStr> { | ||
109 | self.0.leaf_text() | ||
110 | } | ||
111 | pub fn ancestors(&self) -> impl Iterator<Item = &SyntaxNode> { | ||
112 | crate::algo::generate(Some(self), |&node| node.parent()) | ||
113 | } | ||
114 | pub fn descendants(&self) -> impl Iterator<Item = &SyntaxNode> { | ||
115 | self.preorder().filter_map(|event| match event { | ||
116 | WalkEvent::Enter(node) => Some(node), | ||
117 | WalkEvent::Leave(_) => None, | ||
118 | }) | ||
119 | } | ||
120 | pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = &SyntaxNode> { | ||
121 | crate::algo::generate(Some(self), move |&node| match direction { | ||
122 | Direction::Next => node.next_sibling(), | ||
123 | Direction::Prev => node.prev_sibling(), | ||
124 | }) | ||
125 | } | ||
126 | pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<&SyntaxNode>> { | ||
127 | self.0.preorder().map(|event| match event { | ||
128 | WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode::from_repr(n)), | ||
129 | WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxNode::from_repr(n)), | ||
130 | }) | ||
131 | } | ||
132 | } | ||
133 | |||
134 | impl ToOwned for SyntaxNode { | ||
135 | type Owned = TreeArc<SyntaxNode>; | ||
136 | fn to_owned(&self) -> TreeArc<SyntaxNode> { | ||
137 | let ptr = TreeArc(self.0.to_owned()); | ||
138 | TreeArc::cast(ptr) | ||
139 | } | ||
140 | } | ||
141 | |||
142 | impl SyntaxNode { | ||
143 | pub(crate) fn root_data(&self) -> &Vec<SyntaxError> { | ||
144 | self.0.root_data() | ||
145 | } | ||
146 | |||
147 | pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode { | ||
148 | self.0.replace_self(replacement) | ||
149 | } | ||
150 | |||
151 | pub fn kind(&self) -> SyntaxKind { | ||
152 | self.0.kind() | ||
153 | } | ||
154 | |||
155 | pub fn range(&self) -> TextRange { | ||
156 | self.0.range() | ||
157 | } | ||
158 | |||
159 | pub fn text(&self) -> SyntaxText { | ||
160 | SyntaxText::new(self) | ||
161 | } | ||
162 | |||
163 | pub fn is_leaf(&self) -> bool { | ||
164 | self.0.is_leaf() | ||
165 | } | ||
166 | |||
167 | pub fn parent(&self) -> Option<&SyntaxNode> { | ||
168 | self.0.parent().map(SyntaxNode::from_repr) | ||
169 | } | ||
170 | |||
171 | pub fn first_child(&self) -> Option<&SyntaxNode> { | ||
172 | self.0.first_child().map(SyntaxNode::from_repr) | ||
173 | } | ||
174 | |||
175 | pub fn last_child(&self) -> Option<&SyntaxNode> { | ||
176 | self.0.last_child().map(SyntaxNode::from_repr) | ||
177 | } | ||
178 | |||
179 | pub fn next_sibling(&self) -> Option<&SyntaxNode> { | ||
180 | self.0.next_sibling().map(SyntaxNode::from_repr) | ||
181 | } | ||
182 | |||
183 | pub fn prev_sibling(&self) -> Option<&SyntaxNode> { | ||
184 | self.0.prev_sibling().map(SyntaxNode::from_repr) | ||
185 | } | ||
186 | |||
187 | pub fn children(&self) -> SyntaxNodeChildren { | ||
188 | SyntaxNodeChildren(self.0.children()) | ||
189 | } | ||
190 | |||
191 | pub fn memory_size_of_subtree(&self) -> usize { | ||
192 | self.0.memory_size_of_subtree() | ||
193 | } | ||
194 | } | ||
195 | |||
196 | impl fmt::Debug for SyntaxNode { | ||
197 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||
198 | write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; | ||
199 | if has_short_text(self.kind()) { | ||
200 | write!(fmt, " \"{}\"", self.text())?; | ||
201 | } | ||
202 | Ok(()) | ||
203 | } | ||
204 | } | ||
205 | |||
206 | #[derive(Debug)] | ||
207 | pub struct SyntaxNodeChildren<'a>(rowan::SyntaxNodeChildren<'a, RaTypes>); | ||
208 | |||
209 | impl<'a> Iterator for SyntaxNodeChildren<'a> { | ||
210 | type Item = &'a SyntaxNode; | ||
211 | |||
212 | fn next(&mut self) -> Option<&'a SyntaxNode> { | ||
213 | self.0.next().map(SyntaxNode::from_repr) | ||
214 | } | ||
215 | } | ||
216 | |||
217 | fn has_short_text(kind: SyntaxKind) -> bool { | ||
218 | use crate::SyntaxKind::*; | ||
219 | match kind { | ||
220 | IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, | ||
221 | _ => false, | ||
222 | } | ||
223 | } | ||