Repository navigation
Rowan upgrade to 0.16.0 breaks prev_sibling behaviour #175
Description
Discovered by MalteJanz/ludtwig#122
The failed test pipeline contains a bunch of issues related to the rowan upgrade that might need further investigation. But I think the easiest failing test is the following:
#[test]
fn it_should_not_panic_on_prev_sibling_call() {
let parse = parse("<div>a<hr/></div>");
let root = SyntaxNode::new_root(parse.green_node);
// println!("{}", debug_tree(&root));
let prev = root.prev_sibling();
// println!("prev sibling: {:?}", prev);
assert!(prev.is_none());
let child: HtmlTag = support::child(&root).unwrap();
let prev = child.syntax().prev_sibling();
// println!("{:?} prev sibling: {:?}", child, prev);
assert!(prev.is_none());
let child: HtmlTag = support::child(child.body().unwrap().syntax()).unwrap();
let prev = child.syntax().prev_sibling();
// println!("{:?} prev sibling: {:?}", child, prev);
assert!(prev.is_some());
}Btw: I wrote this test while fixing my previous rowan contribution, see #143 . It basically came down to a off-by-one error which might regressed with the latest version, see initial issue: #139
Test output:
---- tests::it_should_not_panic_on_prev_sibling_call stdout ----
thread 'tests::it_should_not_panic_on_prev_sibling_call' panicked at crates/ludtwig-parser/src/lib.rs:152:9:
assertion failed: prev.is_some()
Which points to the last assertion and last line of the test above. Seems like the sibling somehow got lost 🤔
Test explaination
The parsing input:
<div>a<hr/></div>produces the following tree:
ROOT@0..17
HTML_TAG@0..17
HTML_STARTING_TAG@0..5
TK_LESS_THAN@0..1 "<"
TK_WORD@1..4 "div"
HTML_ATTRIBUTE_LIST@4..4
TK_GREATER_THAN@4..5 ">"
BODY@5..11
HTML_TEXT@5..6
TK_WORD@5..6 "a"
HTML_TAG@6..11
HTML_STARTING_TAG@6..11
TK_LESS_THAN@6..7 "<"
TK_WORD@7..9 "hr"
HTML_ATTRIBUTE_LIST@9..9
TK_SLASH_GREATER_THAN@9..11 "/>"
HTML_ENDING_TAG@11..17
TK_LESS_THAN_SLASH@11..13 "</"
TK_WORD@13..16 "div"
TK_GREATER_THAN@16..17 ">"
Note: remember the HTML_TEXT node with the "a" word token next to the HTML_TAG node ("hr" tag)
The first declaration of child ends up as the following tree (the outer div):
HTML_TAG@0..17
HTML_STARTING_TAG@0..5
TK_LESS_THAN@0..1 "<"
TK_WORD@1..4 "div"
HTML_ATTRIBUTE_LIST@4..4
TK_GREATER_THAN@4..5 ">"
BODY@5..11
HTML_TEXT@5..6
TK_WORD@5..6 "a"
HTML_TAG@6..11
HTML_STARTING_TAG@6..11
TK_LESS_THAN@6..7 "<"
TK_WORD@7..9 "hr"
HTML_ATTRIBUTE_LIST@9..9
TK_SLASH_GREATER_THAN@9..11 "/>"
HTML_ENDING_TAG@11..17
TK_LESS_THAN_SLASH@11..13 "</"
TK_WORD@13..16 "div"
TK_GREATER_THAN@16..17 ">"
And doesn't have a previous sibling as expected.
Next up it get's the body of that div tag (isn't stored in a variable), which also looks like expected:
BODY@5..11
HTML_TEXT@5..6
TK_WORD@5..6 "a"
HTML_TAG@6..11
HTML_STARTING_TAG@6..11
TK_LESS_THAN@6..7 "<"
TK_WORD@7..9 "hr"
HTML_ATTRIBUTE_LIST@9..9
TK_SLASH_GREATER_THAN@9..11 "/>"
And inside that it get's the first tag which ends up in the second declared child variable:
HTML_TAG@6..11
HTML_STARTING_TAG@6..11
TK_LESS_THAN@6..7 "<"
TK_WORD@7..9 "hr"
HTML_ATTRIBUTE_LIST@9..9
TK_SLASH_GREATER_THAN@9..11 "/>"
As expected that's the <hr/> tag. And now comes the previously working call to prev_sibling on that exact node, which surprisingly ends up with none instead of the HTML_TEXT node.
The same test and parser implementation was succeeding in rowan 0.15.16
Activity
MalteJanz commentedon Nov 21, 2024
@milianw Might be related to your PR #171 as it slightly changed the
prev_siblingimplementation 🤔https://github.com/rust-analyzer/rowan/pull/171/files#diff-d652bc172cf95622c9c34f43bd6ed9a6c27f042945f710cb9025cae7b12dd579L393
milianw commentedon Nov 22, 2024
Hey @MalteJanz, sorry for that if it's my patch. Quite the pity that rowan doesn't have these test cases in its own repository :( I ran the tests we have in slint, and supposedly it worked for rust-analyzer too (or @Veykril?)
Have you tried reverting my patch to verify that it is to blame? If that is the case, maybe it should be reverted for now?
How can I reproduce the failure, can you write down the required steps for me to run? Then I might be able to find some time the next days to investigate.
MalteJanz commentedon Nov 22, 2024
Hi, thanks for the quick response. I didn't investigate further yet if it is really related to your change, it was just a guess based on the commits of the new version. I also find it unfortunate that the rowan repository itself doesn't have a proper test suite 🙈
For reproducing it, feel free to:
cargo test -p ludtwig-parser(in that crate only the above mentionend test case fails)crates/ludtwig-parser/src/lib.rsFix prev_sibling indexing off-by-one
Fix prev_sibling indexing off-by-one
milianw commentedon Nov 22, 2024
Thanks for spotting this @MalteJanz, seems like the issue lurked in #119 and my new PR should handle that
Fix prev_sibling indexing off-by-one