aboutsummaryrefslogtreecommitdiff
path: root/crates/libsyntax2/src/lib.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-25 12:45:17 +0100
committerAleksey Kladov <[email protected]>2018-08-25 12:45:17 +0100
commitc3e5987c433cdd0ea95a6b1057b442f4f0fe1ffc (patch)
tree1ef2814a3ddc800ef6976aa0459c6b5cf0c3b621 /crates/libsyntax2/src/lib.rs
parent5211e7d97771aa7f8d7cc99e5131fb3cc71a1627 (diff)
incremental reparse
Diffstat (limited to 'crates/libsyntax2/src/lib.rs')
-rw-r--r--crates/libsyntax2/src/lib.rs41
1 files changed, 37 insertions, 4 deletions
diff --git a/crates/libsyntax2/src/lib.rs b/crates/libsyntax2/src/lib.rs
index bb060cbae..d43d26c4c 100644
--- a/crates/libsyntax2/src/lib.rs
+++ b/crates/libsyntax2/src/lib.rs
@@ -70,13 +70,15 @@ impl File {
70 } 70 }
71 pub fn parse(text: &str) -> File { 71 pub fn parse(text: &str) -> File {
72 let tokens = tokenize(&text); 72 let tokens = tokenize(&text);
73 let (green, errors) = parser_impl::parse::<yellow::GreenBuilder>(text, &tokens); 73 let (green, errors) = parser_impl::parse_with::<yellow::GreenBuilder>(
74 text, &tokens, grammar::root,
75 );
74 File::new(green, errors) 76 File::new(green, errors)
75 } 77 }
76 pub fn reparse(&self, edit: &AtomEdit) -> File { 78 pub fn reparse(&self, edit: &AtomEdit) -> File {
77 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) 79 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
78 } 80 }
79 fn incremental_reparse(&self, edit: &AtomEdit) -> Option<File> { 81 pub fn incremental_reparse(&self, edit: &AtomEdit) -> Option<File> {
80 let (node, reparser) = find_reparsable_node(self.syntax(), edit.delete)?; 82 let (node, reparser) = find_reparsable_node(self.syntax(), edit.delete)?;
81 let text = replace_range( 83 let text = replace_range(
82 node.text(), 84 node.text(),
@@ -87,7 +89,12 @@ impl File {
87 if !is_balanced(&tokens) { 89 if !is_balanced(&tokens) {
88 return None; 90 return None;
89 } 91 }
90 None 92 let (green, new_errors) = parser_impl::parse_with::<yellow::GreenBuilder>(
93 &text, &tokens, reparser,
94 );
95 let green_root = node.replace_with(green);
96 let errors = merge_errors(self.errors(), new_errors, edit, node.range().start());
97 Some(File::new(green_root, errors))
91 } 98 }
92 fn full_reparse(&self, edit: &AtomEdit) -> File { 99 fn full_reparse(&self, edit: &AtomEdit) -> File {
93 let text = replace_range(self.syntax().text(), edit.delete, &edit.insert); 100 let text = replace_range(self.syntax().text(), edit.delete, &edit.insert);
@@ -173,7 +180,7 @@ fn find_reparsable_node(node: SyntaxNodeRef, range: TextRange) -> Option<(Syntax
173 } 180 }
174} 181}
175 182
176fn replace_range(mut text: String, range: TextRange, replace_with: &str) -> String { 183pub /*(meh)*/ fn replace_range(mut text: String, range: TextRange, replace_with: &str) -> String {
177 let start = u32::from(range.start()) as usize; 184 let start = u32::from(range.start()) as usize;
178 let end = u32::from(range.end()) as usize; 185 let end = u32::from(range.end()) as usize;
179 text.replace_range(start..end, replace_with); 186 text.replace_range(start..end, replace_with);
@@ -199,3 +206,29 @@ fn is_balanced(tokens: &[Token]) -> bool {
199 } 206 }
200 balance == 0 207 balance == 0
201} 208}
209
210fn merge_errors(
211 old_errors: Vec<SyntaxError>,
212 new_errors: Vec<SyntaxError>,
213 edit: &AtomEdit,
214 node_offset: TextUnit,
215) -> Vec<SyntaxError> {
216 let mut res = Vec::new();
217 for e in old_errors {
218 if e.offset < edit.delete.start() {
219 res.push(e)
220 } else if e.offset > edit.delete.end() {
221 res.push(SyntaxError {
222 msg: e.msg,
223 offset: e.offset + TextUnit::of_str(&edit.insert) - edit.delete.len(),
224 })
225 }
226 }
227 for e in new_errors {
228 res.push(SyntaxError {
229 msg: e.msg,
230 offset: e.offset + node_offset,
231 })
232 }
233 res
234}