aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/syntax_node.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/syntax_node.rs')
-rw-r--r--crates/ra_syntax/src/syntax_node.rs223
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 @@
1mod builder;
2pub mod syntax_error;
3mod syntax_text;
4
5use std::{fmt, borrow::Borrow};
6
7use self::syntax_text::SyntaxText;
8use crate::{SmolStr, SyntaxKind, TextRange};
9use rowan::{Types, TransparentNewType};
10
11pub(crate) use self::builder::GreenBuilder;
12pub use self::syntax_error::{SyntaxError, SyntaxErrorKind, Location};
13pub use rowan::WalkEvent;
14
15#[derive(Debug, Clone, Copy)]
16pub enum RaTypes {}
17impl Types for RaTypes {
18 type Kind = SyntaxKind;
19 type RootData = Vec<SyntaxError>;
20}
21
22pub type GreenNode = rowan::GreenNode<RaTypes>;
23
24#[derive(PartialEq, Eq, Hash)]
25pub struct TreeArc<T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>>(
26 pub(crate) rowan::TreeArc<RaTypes, T>,
27);
28
29impl<T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>> Borrow<T> for TreeArc<T> {
30 fn borrow(&self) -> &T {
31 &*self
32 }
33}
34
35impl<T> TreeArc<T>
36where
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
47impl<T> std::ops::Deref for TreeArc<T>
48where
49 T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
50{
51 type Target = T;
52 fn deref(&self) -> &T {
53 self.0.deref()
54 }
55}
56
57impl<T> PartialEq<T> for TreeArc<T>
58where
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
68impl<T> Clone for TreeArc<T>
69where
70 T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
71{
72 fn clone(&self) -> TreeArc<T> {
73 TreeArc(self.0.clone())
74 }
75}
76
77impl<T> fmt::Debug for TreeArc<T>
78where
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)]
89pub struct SyntaxNode(pub(crate) rowan::SyntaxNode<RaTypes>);
90unsafe impl TransparentNewType for SyntaxNode {
91 type Repr = rowan::SyntaxNode<RaTypes>;
92}
93
94impl 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)]
102pub enum Direction {
103 Next,
104 Prev,
105}
106
107impl 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
134impl 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
142impl 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
196impl 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)]
207pub struct SyntaxNodeChildren<'a>(rowan::SyntaxNodeChildren<'a, RaTypes>);
208
209impl<'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
217fn 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}