diff --git a/cli/src/tests/node_test.rs b/cli/src/tests/node_test.rs index 20686a4a..7217ee27 100644 --- a/cli/src/tests/node_test.rs +++ b/cli/src/tests/node_test.rs @@ -306,6 +306,33 @@ fn test_parent_of_zero_width_node() { assert_eq!(parent, script_element); } +#[test] +fn test_next_sibling_of_zero_width_node() { + let grammar_json = load_grammar_file( + &fixtures_dir() + .join("test_grammars") + .join("next_sibling_from_zwt") + .join("grammar.js"), + None, + ) + .unwrap(); + + let (parser_name, parser_code) = generate_parser_for_grammar(&grammar_json).unwrap(); + + let mut parser = Parser::new(); + let language = get_test_language(&parser_name, &parser_code, None); + parser.set_language(&language).unwrap(); + + let tree = parser.parse("abdef", None).unwrap(); + + let root_node = tree.root_node(); + let missing_c = root_node.child(2).unwrap(); + assert!(missing_c.is_missing()); + assert_eq!(missing_c.kind(), "c"); + let node_d = root_node.child(3).unwrap(); + assert_eq!(missing_c.next_sibling().unwrap(), node_d); +} + #[test] fn test_node_field_name_for_child() { let mut parser = Parser::new(); diff --git a/lib/src/node.c b/lib/src/node.c index 203b98c8..c5500ba4 100644 --- a/lib/src/node.c +++ b/lib/src/node.c @@ -263,8 +263,8 @@ static inline TSNode ts_node__next_sibling(TSNode self, bool include_anonymous) TSNode child; NodeChildIterator iterator = ts_node_iterate_children(&node); while (ts_node_child_iterator_next(&iterator, &child)) { - if (iterator.position.bytes < target_end_byte) continue; - if (ts_node_start_byte(child) <= ts_node_start_byte(self)) { + if (iterator.position.bytes <= target_end_byte) continue; + if (ts_node_start_byte(child) < ts_node_start_byte(self)) { if (ts_node__subtree(child).ptr != ts_node__subtree(self).ptr) { child_containing_target = child; } @@ -541,8 +541,8 @@ TSNode ts_node_parent(TSNode self) { if (node.id == self.id) return ts_node__null(); while (true) { - TSNode next_node = ts_node_child_containing_descendant(node, self); - if (ts_node_is_null(next_node)) break; + TSNode next_node = ts_node_child_with_descendant(node, self); + if (next_node.id == self.id || ts_node_is_null(next_node)) break; node = next_node; } diff --git a/test/fixtures/test_grammars/next_sibling_from_zwt/corpus.txt b/test/fixtures/test_grammars/next_sibling_from_zwt/corpus.txt new file mode 100644 index 00000000..61c67140 --- /dev/null +++ b/test/fixtures/test_grammars/next_sibling_from_zwt/corpus.txt @@ -0,0 +1,10 @@ +=========================== +missing c node +=========================== + +abdef + +--- + +(source + (MISSING "c")) diff --git a/test/fixtures/test_grammars/next_sibling_from_zwt/grammar.js b/test/fixtures/test_grammars/next_sibling_from_zwt/grammar.js new file mode 100644 index 00000000..857b94ad --- /dev/null +++ b/test/fixtures/test_grammars/next_sibling_from_zwt/grammar.js @@ -0,0 +1,22 @@ +module.exports = grammar({ + name: "next_sibling_from_zwt", + extras: $ => [ + /\s|\\\r?\n/, + ], + + rules: { + source: $ => seq( + 'a', + $._bc, + 'd', + 'e', + 'f', + ), + + _bc: $ => seq( + 'b', + 'c', + ), + } +}); +