diff --git a/cli/src/tests/parser_test.rs b/cli/src/tests/parser_test.rs
index 9a04c70d..0384bce8 100644
--- a/cli/src/tests/parser_test.rs
+++ b/cli/src/tests/parser_test.rs
@@ -972,59 +972,73 @@ fn test_parsing_with_a_newly_excluded_range() {
#[test]
fn test_parsing_with_a_newly_included_range() {
- let source_code = "
<%= bar() %>";
- let first_code_start_index = source_code.find(" foo").unwrap();
- let first_code_end_index = first_code_start_index + 7;
- let second_code_start_index = source_code.find(" bar").unwrap();
- let second_code_end_index = second_code_start_index + 7;
- let ranges = [
- Range {
- start_byte: first_code_start_index,
- end_byte: first_code_end_index,
- start_point: Point::new(0, first_code_start_index),
- end_point: Point::new(0, first_code_end_index),
- },
- Range {
- start_byte: second_code_start_index,
- end_byte: second_code_end_index,
- start_point: Point::new(0, second_code_start_index),
- end_point: Point::new(0, second_code_end_index),
- },
- ];
+ let source_code = "
<%= foo() %>
<%= bar() %><%= baz() %>";
+ let range1_start = source_code.find(" foo").unwrap();
+ let range2_start = source_code.find(" bar").unwrap();
+ let range3_start = source_code.find(" baz").unwrap();
+ let range1_end = range1_start + 7;
+ let range2_end = range2_start + 7;
+ let range3_end = range3_start + 7;
// Parse only the first code directive as JavaScript
let mut parser = Parser::new();
parser.set_language(get_language("javascript")).unwrap();
- parser.set_included_ranges(&ranges[0..1]).unwrap();
- let first_tree = parser.parse(source_code, None).unwrap();
+ parser
+ .set_included_ranges(&[simple_range(range1_start, range1_end)])
+ .unwrap();
+ let tree = parser.parse(source_code, None).unwrap();
assert_eq!(
- first_tree.root_node().to_sexp(),
+ tree.root_node().to_sexp(),
concat!(
"(program",
" (expression_statement (call_expression function: (identifier) arguments: (arguments))))",
)
);
- // Parse both the code directives as JavaScript, using the old tree as a reference.
- parser.set_included_ranges(&ranges).unwrap();
- let tree = parser.parse(&source_code, Some(&first_tree)).unwrap();
+ // Parse both the first and third code directives as JavaScript, using the old tree as a
+ // reference.
+ parser
+ .set_included_ranges(&[
+ simple_range(range1_start, range1_end),
+ simple_range(range3_start, range3_end),
+ ])
+ .unwrap();
+ let tree2 = parser.parse(&source_code, Some(&tree)).unwrap();
assert_eq!(
- tree.root_node().to_sexp(),
+ tree2.root_node().to_sexp(),
concat!(
"(program",
" (expression_statement (call_expression function: (identifier) arguments: (arguments)))",
" (expression_statement (call_expression function: (identifier) arguments: (arguments))))",
)
);
-
assert_eq!(
- tree.changed_ranges(&first_tree).collect::
>(),
- vec![Range {
- start_byte: first_code_end_index,
- end_byte: second_code_end_index,
- start_point: Point::new(0, first_code_end_index),
- end_point: Point::new(0, second_code_end_index),
- }]
+ tree2.changed_ranges(&tree).collect::>(),
+ &[simple_range(range1_end, range3_end)]
+ );
+
+ // Parse all three code directives as JavaScript, using the old tree as a
+ // reference.
+ parser
+ .set_included_ranges(&[
+ simple_range(range1_start, range1_end),
+ simple_range(range2_start, range2_end),
+ simple_range(range3_start, range3_end),
+ ])
+ .unwrap();
+ let tree3 = parser.parse(&source_code, Some(&tree)).unwrap();
+ assert_eq!(
+ tree3.root_node().to_sexp(),
+ concat!(
+ "(program",
+ " (expression_statement (call_expression function: (identifier) arguments: (arguments)))",
+ " (expression_statement (call_expression function: (identifier) arguments: (arguments)))",
+ " (expression_statement (call_expression function: (identifier) arguments: (arguments))))",
+ )
+ );
+ assert_eq!(
+ tree3.changed_ranges(&tree2).collect::>(),
+ &[simple_range(range2_start + 1, range2_end - 1)]
);
}
@@ -1088,3 +1102,12 @@ fn test_parsing_with_included_ranges_and_missing_tokens() {
assert_eq!(root.start_byte(), 2);
assert_eq!(root.child(3).unwrap().start_byte(), 4);
}
+
+fn simple_range(start: usize, end: usize) -> Range {
+ Range {
+ start_byte: start,
+ end_byte: end,
+ start_point: Point::new(0, start),
+ end_point: Point::new(0, end),
+ }
+}
diff --git a/lib/src/parser.c b/lib/src/parser.c
index 5671e724..d4b22730 100644
--- a/lib/src/parser.c
+++ b/lib/src/parser.c
@@ -599,6 +599,10 @@ static Subtree ts_parser__reuse_node(
uint32_t byte_offset = reusable_node_byte_offset(&self->reusable_node);
uint32_t end_byte_offset = byte_offset + ts_subtree_total_bytes(result);
+ // Do not reuse an EOF node if the included ranges array has changes
+ // later on in the file.
+ if (ts_subtree_is_eof(result)) end_byte_offset = UINT32_MAX;
+
if (byte_offset > position) {
LOG("before_reusable_node symbol:%s", TREE_NAME(result));
break;
@@ -1611,8 +1615,8 @@ static unsigned ts_parser__condense_stack(TSParser *self) {
static bool ts_parser_has_outstanding_parse(TSParser *self) {
return (
- self->lexer.current_position.bytes > 0 ||
- ts_stack_state(self->stack, 0) != 1
+ ts_stack_state(self->stack, 0) != 1 ||
+ ts_stack_node_count_since_error(self->stack, 0) != 0
);
}