Avoid reusing the root node during incremental parsing

Fixes #712
This commit is contained in:
Max Brunsfeld 2020-09-23 12:59:24 -07:00
parent 4d99e23946
commit cb343cad5e
2 changed files with 28 additions and 9 deletions

View file

@ -395,6 +395,18 @@ fn test_parsing_after_editing_end_of_code() {
assert_eq!(recorder.strings_read(), vec![" * ", "abc.d)",]);
}
#[test]
fn test_parsing_empty_file_with_reused_tree() {
let mut parser = Parser::new();
parser.set_language(get_language("rust")).unwrap();
let tree = parser.parse("", None);
parser.parse("", tree.as_ref());
let tree = parser.parse("\n ", None);
parser.parse("\n ", tree.as_ref());
}
// Thread safety
#[test]

View file

@ -20,15 +20,6 @@ static inline void reusable_node_clear(ReusableNode *self) {
self->last_external_token = NULL_SUBTREE;
}
static inline void reusable_node_reset(ReusableNode *self, Subtree tree) {
reusable_node_clear(self);
array_push(&self->stack, ((StackEntry) {
.tree = tree,
.child_index = 0,
.byte_offset = 0,
}));
}
static inline Subtree reusable_node_tree(ReusableNode *self) {
return self->stack.size > 0
? self->stack.contents[self->stack.size - 1].tree
@ -86,3 +77,19 @@ static inline void reusable_node_advance_past_leaf(ReusableNode *self) {
while (reusable_node_descend(self)) {}
reusable_node_advance(self);
}
static inline void reusable_node_reset(ReusableNode *self, Subtree tree) {
reusable_node_clear(self);
array_push(&self->stack, ((StackEntry) {
.tree = tree,
.child_index = 0,
.byte_offset = 0,
}));
// Never reuse the root node, because it has a non-standard internal structure
// due to transformations that are applied when it is accepted: adding the EOF
// child and any extra children.
if (!reusable_node_descend(self)) {
reusable_node_clear(self);
}
}