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