aboutsummaryrefslogtreecommitdiff
path: root/crates/libsyntax2
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libsyntax2')
-rw-r--r--crates/libsyntax2/src/lib.rs49
1 files changed, 41 insertions, 8 deletions
diff --git a/crates/libsyntax2/src/lib.rs b/crates/libsyntax2/src/lib.rs
index 787dc2b5b..bb060cbae 100644
--- a/crates/libsyntax2/src/lib.rs
+++ b/crates/libsyntax2/src/lib.rs
@@ -62,29 +62,35 @@ pub struct File {
62} 62}
63 63
64impl File { 64impl File {
65 fn new(root: GreenNode, errors: Vec<SyntaxError>) -> File { 65 fn new(green: GreenNode, errors: Vec<SyntaxError>) -> File {
66 let root = SyntaxRoot::new(root, errors); 66 let root = SyntaxRoot::new(green, errors);
67 let root = SyntaxNode::new_owned(root); 67 let root = SyntaxNode::new_owned(root);
68 validate_block_structure(root.borrowed()); 68 validate_block_structure(root.borrowed());
69 File { root } 69 File { root }
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 (root, errors) = parser_impl::parse::<yellow::GreenBuilder>(text, &tokens); 73 let (green, errors) = parser_impl::parse::<yellow::GreenBuilder>(text, &tokens);
74 File::new(root, errors) 74 File::new(green, errors)
75 } 75 }
76 pub fn reparse(&self, edit: &AtomEdit) -> File { 76 pub fn reparse(&self, edit: &AtomEdit) -> File {
77 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) 77 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
78 } 78 }
79 fn incremental_reparse(&self, edit: &AtomEdit) -> Option<File> { 79 fn incremental_reparse(&self, edit: &AtomEdit) -> Option<File> {
80 let (node, reparser) = find_reparsable_node(self.syntax(), edit.delete)?; 80 let (node, reparser) = find_reparsable_node(self.syntax(), edit.delete)?;
81 let text = replace_range(
82 node.text(),
83 edit.delete - node.range().start(),
84 &edit.insert,
85 );
86 let tokens = tokenize(&text);
87 if !is_balanced(&tokens) {
88 return None;
89 }
81 None 90 None
82 } 91 }
83 fn full_reparse(&self, edit: &AtomEdit) -> File { 92 fn full_reparse(&self, edit: &AtomEdit) -> File {
84 let start = u32::from(edit.delete.start()) as usize; 93 let text = replace_range(self.syntax().text(), edit.delete, &edit.insert);
85 let end = u32::from(edit.delete.end()) as usize;
86 let mut text = self.syntax().text();
87 text.replace_range(start..end, &edit.insert);
88 File::parse(&text) 94 File::parse(&text)
89 } 95 }
90 pub fn ast(&self) -> ast::Root { 96 pub fn ast(&self) -> ast::Root {
@@ -166,3 +172,30 @@ fn find_reparsable_node(node: SyntaxNodeRef, range: TextRange) -> Option<(Syntax
166 Some(res) 172 Some(res)
167 } 173 }
168} 174}
175
176fn replace_range(mut text: String, range: TextRange, replace_with: &str) -> String {
177 let start = u32::from(range.start()) as usize;
178 let end = u32::from(range.end()) as usize;
179 text.replace_range(start..end, replace_with);
180 text
181}
182
183fn is_balanced(tokens: &[Token]) -> bool {
184 if tokens.len() == 0
185 || tokens.first().unwrap().kind != L_CURLY
186 || tokens.last().unwrap().kind != R_CURLY {
187 return false
188 }
189 let mut balance = 0usize;
190 for t in tokens.iter() {
191 match t.kind {
192 L_CURLY => balance += 1,
193 R_CURLY => balance = match balance.checked_sub(1) {
194 Some(b) => b,
195 None => return false,
196 },
197 _ => (),
198 }
199 }
200 balance == 0
201}