]> git.lizzy.rs Git - rust.git/blob - src/tree/file_builder.rs
Add minimal docs to most public symbols
[rust.git] / src / tree / file_builder.rs
1 // FIXME(CAD97): I don't understand this mod well enough to stub out docs for the public symbols yet
2 #![allow(missing_docs)]
3
4 use {SyntaxKind, TextRange, TextUnit};
5 use super::{File, NodeData, NodeIdx, SyntaxErrorData};
6
7 pub trait Sink {
8     fn leaf(&mut self, kind: SyntaxKind, len: TextUnit);
9     fn start_internal(&mut self, kind: SyntaxKind);
10     fn finish_internal(&mut self);
11     fn error(&mut self) -> ErrorBuilder;
12 }
13
14 #[derive(Debug)]
15 pub struct FileBuilder {
16     text: String,
17     nodes: Vec<NodeData>,
18     errors: Vec<SyntaxErrorData>,
19     in_progress: Vec<(NodeIdx, Option<NodeIdx>)>, // (parent, last_child)
20     pos: TextUnit,
21 }
22
23 impl Sink for FileBuilder {
24     fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) {
25         let leaf = NodeData {
26             kind,
27             range: TextRange::from_len(self.pos, len),
28             parent: None,
29             first_child: None,
30             next_sibling: None,
31         };
32         self.pos += len;
33         let id = self.push_child(leaf);
34         self.add_len(id);
35     }
36
37     fn start_internal(&mut self, kind: SyntaxKind) {
38         let node = NodeData {
39             kind,
40             range: TextRange::from_len(self.pos, 0.into()),
41             parent: None,
42             first_child: None,
43             next_sibling: None,
44         };
45         let id = if self.in_progress.is_empty() {
46             self.new_node(node)
47         } else {
48             self.push_child(node)
49         };
50         self.in_progress.push((id, None))
51     }
52
53     fn finish_internal(&mut self) {
54         let (id, _) = self.in_progress
55             .pop()
56             .expect("trying to complete a node, but there are no in-progress nodes");
57         if !self.in_progress.is_empty() {
58             self.add_len(id);
59         }
60     }
61
62     fn error(&mut self) -> ErrorBuilder {
63         ErrorBuilder::new(self)
64     }
65 }
66
67 impl FileBuilder {
68     pub fn new(text: String) -> FileBuilder {
69         FileBuilder {
70             text,
71             nodes: Vec::new(),
72             errors: Vec::new(),
73             in_progress: Vec::new(),
74             pos: TextUnit::new(0),
75         }
76     }
77
78     pub fn finish(self) -> File {
79         assert!(
80             self.in_progress.is_empty(),
81             "some nodes in FileBuilder are unfinished: {:?}",
82             self.in_progress
83                 .iter()
84                 .map(|&(idx, _)| self.nodes[idx].kind)
85                 .collect::<Vec<_>>()
86         );
87         assert_eq!(
88             self.pos,
89             (self.text.len() as u32).into(),
90             "nodes in FileBuilder do not cover the whole file"
91         );
92         File {
93             text: self.text,
94             nodes: self.nodes,
95             errors: self.errors,
96         }
97     }
98
99     fn new_node(&mut self, data: NodeData) -> NodeIdx {
100         let id = NodeIdx(self.nodes.len() as u32);
101         self.nodes.push(data);
102         id
103     }
104
105     fn push_child(&mut self, mut child: NodeData) -> NodeIdx {
106         child.parent = Some(self.current_id());
107         let id = self.new_node(child);
108         {
109             let (parent, sibling) = *self.in_progress.last().unwrap();
110             let slot = if let Some(idx) = sibling {
111                 &mut self.nodes[idx].next_sibling
112             } else {
113                 &mut self.nodes[parent].first_child
114             };
115             fill(slot, id);
116         }
117         self.in_progress.last_mut().unwrap().1 = Some(id);
118         id
119     }
120
121     fn add_len(&mut self, child: NodeIdx) {
122         let range = self.nodes[child].range;
123         grow(&mut self.current_parent().range, range);
124     }
125
126     fn current_id(&self) -> NodeIdx {
127         self.in_progress.last().unwrap().0
128     }
129
130     fn current_parent(&mut self) -> &mut NodeData {
131         let idx = self.current_id();
132         &mut self.nodes[idx]
133     }
134 }
135
136 fn fill<T>(slot: &mut Option<T>, value: T) {
137     assert!(slot.is_none());
138     *slot = Some(value);
139 }
140
141 fn grow(left: &mut TextRange, right: TextRange) {
142     assert_eq!(left.end(), right.start());
143     *left = TextRange::from_to(left.start(), right.end())
144 }
145
146 #[derive(Debug)]
147 pub struct ErrorBuilder<'f> {
148     message: Option<String>,
149     builder: &'f mut FileBuilder,
150 }
151
152 impl<'f> ErrorBuilder<'f> {
153     fn new(builder: &'f mut FileBuilder) -> Self {
154         ErrorBuilder {
155             message: None,
156             builder,
157         }
158     }
159
160     pub fn message<M: Into<String>>(mut self, m: M) -> Self {
161         self.message = Some(m.into());
162         self
163     }
164
165     pub fn emit(self) {
166         let message = self.message.expect("Error message not set");
167         let &(node, after_child) = self.builder.in_progress.last().unwrap();
168         self.builder.errors.push(SyntaxErrorData {
169             node,
170             message,
171             after_child,
172         })
173     }
174 }