diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/libsyntax2/src/lib.rs | 49 |
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 | ||
64 | impl File { | 64 | impl 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 | |||
176 | fn 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 | |||
183 | fn 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 | } | ||