aboutsummaryrefslogtreecommitdiff
path: root/crates/libsyntax2/src
diff options
context:
space:
mode:
authordarksv <[email protected]>2018-09-13 22:25:05 +0100
committerdarksv <[email protected]>2018-09-13 22:25:05 +0100
commit4356240fa42eebbd17fdb63b2d0e6f86387ca21c (patch)
tree96785c930199eac49a9f48cd1d9c67f0f7c1dc4f /crates/libsyntax2/src
parentb6f8037a6f8fbcb4f127e1d2b518279650b1f5ea (diff)
Incremental reparsing for single tokens (WHITESPACE, COMMENT, DOC_COMMENT, IDENT, STRING, RAW_STRING)
Diffstat (limited to 'crates/libsyntax2/src')
-rw-r--r--crates/libsyntax2/src/lib.rs80
1 files changed, 67 insertions, 13 deletions
diff --git a/crates/libsyntax2/src/lib.rs b/crates/libsyntax2/src/lib.rs
index fd58cb4fa..bae685fb4 100644
--- a/crates/libsyntax2/src/lib.rs
+++ b/crates/libsyntax2/src/lib.rs
@@ -82,22 +82,68 @@ impl File {
82 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) 82 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
83 } 83 }
84 pub fn incremental_reparse(&self, edit: &AtomEdit) -> Option<File> { 84 pub fn incremental_reparse(&self, edit: &AtomEdit) -> Option<File> {
85 let (node, green, new_errors) =
86 self.reparse_leaf(&edit).or_else(|| self.reparse_block(&edit))?;
87
88 let green_root = node.replace_with(green);
89 let errors = merge_errors(self.errors(), new_errors, node, edit);
90 Some(File::new(green_root, errors))
91 }
92 fn reparse_leaf(&self, edit: &AtomEdit) -> Option<(SyntaxNodeRef, GreenNode, Vec<SyntaxError>)> {
93 let node = algo::find_covering_node(self.syntax(), edit.delete);
94 match node.kind() {
95 | WHITESPACE
96 | COMMENT
97 | DOC_COMMENT
98 | IDENT
99 | STRING
100 | RAW_STRING => {
101 let text = get_text_after_edit(node, &edit);
102 let tokens = tokenize(&text);
103 if tokens.len() != 1 || tokens[0].kind != node.kind() {
104 return None;
105 }
106
107 let reparser: fn(&mut Parser) = if node.kind().is_trivia() {
108 // since trivia is omitted by parser when it doesn't have a parent, \
109 // we need to create one for it
110 |p| {
111 p.start().complete(p, ROOT);
112 }
113 } else {
114 |p| {
115 p.bump();
116 }
117 };
118
119 let (green, new_errors) =
120 parser_impl::parse_with::<yellow::GreenBuilder>(
121 &text, &tokens, reparser,
122 );
123
124 let green = if node.kind().is_trivia() {
125 green.children().first().cloned().unwrap()
126 } else {
127 green
128 };
129
130 Some((node, green, new_errors))
131 },
132 _ => None,
133 }
134 }
135 fn reparse_block(&self, edit: &AtomEdit) -> Option<(SyntaxNodeRef, GreenNode, Vec<SyntaxError>)> {
85 let (node, reparser) = find_reparsable_node(self.syntax(), edit.delete)?; 136 let (node, reparser) = find_reparsable_node(self.syntax(), edit.delete)?;
86 let text = replace_range( 137 let text = get_text_after_edit(node, &edit);
87 node.text().to_string(),
88 edit.delete - node.range().start(),
89 &edit.insert,
90 );
91 let tokens = tokenize(&text); 138 let tokens = tokenize(&text);
92 if !is_balanced(&tokens) { 139 if !is_balanced(&tokens) {
93 return None; 140 return None;
94 } 141 }
95 let (green, new_errors) = parser_impl::parse_with::<yellow::GreenBuilder>( 142 let (green, new_errors) =
96 &text, &tokens, reparser, 143 parser_impl::parse_with::<yellow::GreenBuilder>(
97 ); 144 &text, &tokens, reparser,
98 let green_root = node.replace_with(green); 145 );
99 let errors = merge_errors(self.errors(), new_errors, node, edit); 146 Some((node, green, new_errors))
100 Some(File::new(green_root, errors))
101 } 147 }
102 fn full_reparse(&self, edit: &AtomEdit) -> File { 148 fn full_reparse(&self, edit: &AtomEdit) -> File {
103 let text = replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert); 149 let text = replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert);
@@ -134,6 +180,14 @@ impl AtomEdit {
134 } 180 }
135} 181}
136 182
183fn get_text_after_edit(node: SyntaxNodeRef, edit: &AtomEdit) -> String {
184 replace_range(
185 node.text().to_string(),
186 edit.delete - node.range().start(),
187 &edit.insert,
188 )
189}
190
137fn find_reparsable_node(node: SyntaxNodeRef, range: TextRange) -> Option<(SyntaxNodeRef, fn(&mut Parser))> { 191fn find_reparsable_node(node: SyntaxNodeRef, range: TextRange) -> Option<(SyntaxNodeRef, fn(&mut Parser))> {
138 let node = algo::find_covering_node(node, range); 192 let node = algo::find_covering_node(node, range);
139 return algo::ancestors(node) 193 return algo::ancestors(node)
@@ -200,9 +254,9 @@ fn merge_errors(
200) -> Vec<SyntaxError> { 254) -> Vec<SyntaxError> {
201 let mut res = Vec::new(); 255 let mut res = Vec::new();
202 for e in old_errors { 256 for e in old_errors {
203 if e.offset < old_node.range().start() { 257 if e.offset <= old_node.range().start() {
204 res.push(e) 258 res.push(e)
205 } else if e.offset > old_node.range().end() { 259 } else if e.offset >= old_node.range().end() {
206 res.push(SyntaxError { 260 res.push(SyntaxError {
207 msg: e.msg, 261 msg: e.msg,
208 offset: e.offset + TextUnit::of_str(&edit.insert) - edit.delete.len(), 262 offset: e.offset + TextUnit::of_str(&edit.insert) - edit.delete.len(),