aboutsummaryrefslogtreecommitdiff
path: root/src/tree/mod.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-07-29 12:37:48 +0100
committerAleksey Kladov <[email protected]>2018-07-29 12:37:48 +0100
commitad188d4c3db34f035408afbdd6d2f3c308121f0a (patch)
tree0c6cdea50ab664a361fa4c0f6b99cb53ce00529b /src/tree/mod.rs
parentc12450fb4e30c3418555e47d045bb9fd4318a10a (diff)
kill old tree
Diffstat (limited to 'src/tree/mod.rs')
-rw-r--r--src/tree/mod.rs221
1 files changed, 3 insertions, 218 deletions
diff --git a/src/tree/mod.rs b/src/tree/mod.rs
index 7abe17592..efba82825 100644
--- a/src/tree/mod.rs
+++ b/src/tree/mod.rs
@@ -1,8 +1,8 @@
1mod file_builder; 1mod file_builder;
2 2
3use ::{TextRange, TextUnit}; 3use ::{TextUnit};
4use std::{fmt, cmp}; 4use std::{fmt};
5pub(crate) use self::file_builder::{ErrorMsg, FileBuilder, Sink, GreenBuilder}; 5pub(crate) use self::file_builder::{Sink, GreenBuilder};
6 6
7pub use syntax_kinds::SyntaxKind; 7pub use syntax_kinds::SyntaxKind;
8 8
@@ -25,218 +25,3 @@ pub struct Token {
25 /// The length of the token. 25 /// The length of the token.
26 pub len: TextUnit, 26 pub len: TextUnit,
27} 27}
28
29/// The contents of a Rust source file.
30#[derive(Debug)]
31pub struct File {
32 text: String,
33 nodes: Vec<NodeData>,
34 errors: Vec<SyntaxErrorData>,
35}
36
37impl File {
38 /// The root node of this source file.
39 pub fn root<'f>(&'f self) -> Node<'f> {
40 assert!(!self.nodes.is_empty());
41 Node {
42 file: self,
43 idx: NodeIdx(0),
44 }
45 }
46}
47
48/// A reference to a token in a Rust source file.
49#[derive(Clone, Copy)]
50pub struct Node<'f> {
51 file: &'f File,
52 idx: NodeIdx,
53}
54
55impl<'f> Node<'f> {
56 /// The kind of the token at this node.
57 pub fn kind(&self) -> SyntaxKind {
58 self.data().kind
59 }
60
61 /// The text range covered by the token at this node.
62 pub fn range(&self) -> TextRange {
63 self.data().range
64 }
65
66 /// The text at this node.
67 pub fn text(&self) -> &'f str {
68 &self.file.text.as_str()[self.range()]
69 }
70
71 /// The parent node to this node.
72 pub fn parent(&self) -> Option<Node<'f>> {
73 self.as_node(self.data().parent)
74 }
75
76 /// The children nodes of this node.
77 pub fn children(&self) -> Children<'f> {
78 Children {
79 next: self.as_node(self.data().first_child),
80 }
81 }
82
83 /// Any errors contained in this node.
84 pub fn errors(&self) -> SyntaxErrors<'f> {
85 let pos = self.file.errors.iter().position(|e| e.node == self.idx);
86 let next = pos.map(|i| ErrorIdx(i as u32)).map(|idx| SyntaxError {
87 file: self.file,
88 idx,
89 });
90 SyntaxErrors { next }
91 }
92
93 fn data(&self) -> &'f NodeData {
94 &self.file.nodes[self.idx]
95 }
96
97 fn as_node(&self, idx: Option<NodeIdx>) -> Option<Node<'f>> {
98 idx.map(|idx| Node {
99 file: self.file,
100 idx,
101 })
102 }
103}
104
105impl<'f> fmt::Debug for Node<'f> {
106 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
107 write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
108 if has_short_text(self.kind()) {
109 write!(fmt, " \"{}\"", self.text())?;
110 }
111 Ok(())
112 }
113}
114
115fn has_short_text(kind: SyntaxKind) -> bool {
116 use syntax_kinds::*;
117 match kind {
118 IDENT | LIFETIME => true,
119 _ => false,
120 }
121}
122
123impl<'f> cmp::PartialEq<Node<'f>> for Node<'f> {
124 fn eq(&self, other: &Node<'f>) -> bool {
125 self.idx == other.idx && ::std::ptr::eq(self.file, other.file)
126 }
127}
128
129impl<'f> cmp::Eq for Node<'f> {}
130
131#[derive(Clone, Copy, Debug)]
132pub struct SyntaxError<'f> {
133 file: &'f File,
134 idx: ErrorIdx,
135}
136
137impl<'f> SyntaxError<'f> {
138 pub fn message(&self) -> &'f str {
139 self.data().message.as_str()
140 }
141
142 pub fn after_child(&self) -> Option<Node<'f>> {
143 let idx = self.data().after_child?;
144 Some(Node {
145 file: self.file,
146 idx,
147 })
148 }
149
150 fn data(&self) -> &'f SyntaxErrorData {
151 &self.file.errors[self.idx]
152 }
153
154 fn next(&self) -> Option<SyntaxError<'f>> {
155 let next_idx = self.idx.0 + 1;
156 if !((next_idx as usize) < self.file.errors.len()) {
157 return None;
158 }
159 let result = SyntaxError {
160 file: self.file,
161 idx: ErrorIdx(next_idx),
162 };
163 if result.data().node != self.data().node {
164 return None;
165 }
166 Some(result)
167 }
168}
169
170#[derive(Debug)]
171pub struct Children<'f> {
172 next: Option<Node<'f>>,
173}
174
175impl<'f> Iterator for Children<'f> {
176 type Item = Node<'f>;
177
178 fn next(&mut self) -> Option<Node<'f>> {
179 let next = self.next;
180 self.next = next.and_then(|node| node.as_node(node.data().next_sibling));
181 next
182 }
183}
184
185#[derive(Debug)]
186pub struct SyntaxErrors<'f> {
187 next: Option<SyntaxError<'f>>,
188}
189
190impl<'f> Iterator for SyntaxErrors<'f> {
191 type Item = SyntaxError<'f>;
192
193 fn next(&mut self) -> Option<SyntaxError<'f>> {
194 let next = self.next;
195 self.next = next.as_ref().and_then(SyntaxError::next);
196 next
197 }
198}
199
200#[derive(Clone, Copy, Debug, PartialEq, Eq)]
201struct NodeIdx(u32);
202
203#[derive(Debug)]
204struct NodeData {
205 kind: SyntaxKind,
206 range: TextRange,
207 parent: Option<NodeIdx>,
208 first_child: Option<NodeIdx>,
209 next_sibling: Option<NodeIdx>,
210}
211
212impl ::std::ops::Index<NodeIdx> for Vec<NodeData> {
213 type Output = NodeData;
214
215 fn index(&self, NodeIdx(idx): NodeIdx) -> &NodeData {
216 &self[idx as usize]
217 }
218}
219
220impl ::std::ops::IndexMut<NodeIdx> for Vec<NodeData> {
221 fn index_mut(&mut self, NodeIdx(idx): NodeIdx) -> &mut NodeData {
222 &mut self[idx as usize]
223 }
224}
225
226#[derive(Clone, Copy, Debug)]
227struct ErrorIdx(u32);
228
229#[derive(Debug)]
230struct SyntaxErrorData {
231 node: NodeIdx,
232 message: String,
233 after_child: Option<NodeIdx>,
234}
235
236impl ::std::ops::Index<ErrorIdx> for Vec<SyntaxErrorData> {
237 type Output = SyntaxErrorData;
238
239 fn index(&self, ErrorIdx(idx): ErrorIdx) -> &SyntaxErrorData {
240 &self[idx as usize]
241 }
242}