diff options
author | Aleksey Kladov <[email protected]> | 2018-07-29 12:37:48 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-07-29 12:37:48 +0100 |
commit | ad188d4c3db34f035408afbdd6d2f3c308121f0a (patch) | |
tree | 0c6cdea50ab664a361fa4c0f6b99cb53ce00529b /src/tree/mod.rs | |
parent | c12450fb4e30c3418555e47d045bb9fd4318a10a (diff) |
kill old tree
Diffstat (limited to 'src/tree/mod.rs')
-rw-r--r-- | src/tree/mod.rs | 221 |
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 @@ | |||
1 | mod file_builder; | 1 | mod file_builder; |
2 | 2 | ||
3 | use ::{TextRange, TextUnit}; | 3 | use ::{TextUnit}; |
4 | use std::{fmt, cmp}; | 4 | use std::{fmt}; |
5 | pub(crate) use self::file_builder::{ErrorMsg, FileBuilder, Sink, GreenBuilder}; | 5 | pub(crate) use self::file_builder::{Sink, GreenBuilder}; |
6 | 6 | ||
7 | pub use syntax_kinds::SyntaxKind; | 7 | pub 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)] | ||
31 | pub struct File { | ||
32 | text: String, | ||
33 | nodes: Vec<NodeData>, | ||
34 | errors: Vec<SyntaxErrorData>, | ||
35 | } | ||
36 | |||
37 | impl 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)] | ||
50 | pub struct Node<'f> { | ||
51 | file: &'f File, | ||
52 | idx: NodeIdx, | ||
53 | } | ||
54 | |||
55 | impl<'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 | |||
105 | impl<'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 | |||
115 | fn has_short_text(kind: SyntaxKind) -> bool { | ||
116 | use syntax_kinds::*; | ||
117 | match kind { | ||
118 | IDENT | LIFETIME => true, | ||
119 | _ => false, | ||
120 | } | ||
121 | } | ||
122 | |||
123 | impl<'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 | |||
129 | impl<'f> cmp::Eq for Node<'f> {} | ||
130 | |||
131 | #[derive(Clone, Copy, Debug)] | ||
132 | pub struct SyntaxError<'f> { | ||
133 | file: &'f File, | ||
134 | idx: ErrorIdx, | ||
135 | } | ||
136 | |||
137 | impl<'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)] | ||
171 | pub struct Children<'f> { | ||
172 | next: Option<Node<'f>>, | ||
173 | } | ||
174 | |||
175 | impl<'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)] | ||
186 | pub struct SyntaxErrors<'f> { | ||
187 | next: Option<SyntaxError<'f>>, | ||
188 | } | ||
189 | |||
190 | impl<'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)] | ||
201 | struct NodeIdx(u32); | ||
202 | |||
203 | #[derive(Debug)] | ||
204 | struct NodeData { | ||
205 | kind: SyntaxKind, | ||
206 | range: TextRange, | ||
207 | parent: Option<NodeIdx>, | ||
208 | first_child: Option<NodeIdx>, | ||
209 | next_sibling: Option<NodeIdx>, | ||
210 | } | ||
211 | |||
212 | impl ::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 | |||
220 | impl ::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)] | ||
227 | struct ErrorIdx(u32); | ||
228 | |||
229 | #[derive(Debug)] | ||
230 | struct SyntaxErrorData { | ||
231 | node: NodeIdx, | ||
232 | message: String, | ||
233 | after_child: Option<NodeIdx>, | ||
234 | } | ||
235 | |||
236 | impl ::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 | } | ||