Fix meld_with_next_inline_fragment and add meld_with_prev_inline_fragment

Factor out a new `meld_with_prev_inline_fragment` method that mirrors the
existing `meld_with_next_inline_fragment`.

This also fixes a bug in `meld_with_next` that was already fixed in the
`meld_with_prev` by @notriddle in #10419.  The bug is that it was traversing
the inline context nodes in the wrong order.  It should start at the outermost
enclosing node, since the fragments might be at different nesting levels under
some common ancestor.
This commit is contained in:
Matt Brubeck 2016-04-15 15:36:32 -07:00
parent 587314e52b
commit b607b3a932
2 changed files with 32 additions and 30 deletions

View file

@ -1779,28 +1779,7 @@ pub fn strip_ignorable_whitespace_from_start(this: &mut LinkedList<Fragment>) {
WhitespaceStrippingResult::FragmentContainedOnlyWhitespace => { WhitespaceStrippingResult::FragmentContainedOnlyWhitespace => {
let removed_fragment = this.pop_front().unwrap(); let removed_fragment = this.pop_front().unwrap();
if let Some(ref mut remaining_fragment) = this.front_mut() { if let Some(ref mut remaining_fragment) = this.front_mut() {
if let Some(ref mut inline_context_of_remaining_fragment) = remaining_fragment.meld_with_prev_inline_fragment(&removed_fragment);
remaining_fragment.inline_context {
if let Some(ref inline_context_of_removed_fragment) =
removed_fragment.inline_context {
for (inline_context_node_from_removed_fragment,
inline_context_node_from_remaining_fragment) in
inline_context_of_removed_fragment.nodes.iter().rev().zip(
inline_context_of_remaining_fragment.nodes.iter_mut().rev()
) {
if !inline_context_node_from_removed_fragment.flags.contains(
FIRST_FRAGMENT_OF_ELEMENT) {
continue
}
if inline_context_node_from_removed_fragment.address !=
inline_context_node_from_remaining_fragment.address {
continue
}
inline_context_node_from_remaining_fragment.flags.insert(
FIRST_FRAGMENT_OF_ELEMENT);
}
}
}
} }
} }
} }

View file

@ -2497,26 +2497,49 @@ impl Fragment {
pub fn meld_with_next_inline_fragment(&mut self, next_fragment: &Fragment) { pub fn meld_with_next_inline_fragment(&mut self, next_fragment: &Fragment) {
if let Some(ref mut inline_context_of_this_fragment) = self.inline_context { if let Some(ref mut inline_context_of_this_fragment) = self.inline_context {
if let Some(ref inline_context_of_next_fragment) = next_fragment.inline_context { if let Some(ref inline_context_of_next_fragment) = next_fragment.inline_context {
for (i, inline_context_node_from_next_fragment) in for (inline_context_node_from_this_fragment,
inline_context_of_next_fragment.nodes.iter().enumerate() { inline_context_node_from_next_fragment)
if i >= inline_context_of_this_fragment.nodes.len() { in inline_context_of_this_fragment.nodes.iter_mut().rev()
continue .zip(inline_context_of_next_fragment.nodes.iter().rev())
} {
if !inline_context_node_from_next_fragment.flags.contains( if !inline_context_node_from_next_fragment.flags.contains(
LAST_FRAGMENT_OF_ELEMENT) { LAST_FRAGMENT_OF_ELEMENT) {
continue continue
} }
if inline_context_node_from_next_fragment.address != if inline_context_node_from_next_fragment.address !=
inline_context_of_this_fragment.nodes[i].address { inline_context_node_from_this_fragment.address {
continue continue
} }
inline_context_of_this_fragment.nodes[i].flags.insert( inline_context_node_from_this_fragment.flags.insert(LAST_FRAGMENT_OF_ELEMENT);
LAST_FRAGMENT_OF_ELEMENT);
} }
} }
} }
} }
pub fn meld_with_prev_inline_fragment(&mut self, prev_fragment: &Fragment) {
if let Some(ref mut inline_context_of_this_fragment) = self.inline_context {
if let Some(ref inline_context_of_prev_fragment) = prev_fragment.inline_context {
for (inline_context_node_from_prev_fragment,
inline_context_node_from_this_fragment)
in inline_context_of_prev_fragment.nodes.iter().rev().zip(
inline_context_of_this_fragment.nodes.iter_mut().rev())
{
if !inline_context_node_from_prev_fragment.flags.contains(
FIRST_FRAGMENT_OF_ELEMENT) {
continue
}
if inline_context_node_from_prev_fragment.address !=
inline_context_node_from_this_fragment.address {
continue
}
inline_context_node_from_this_fragment.flags.insert(
FIRST_FRAGMENT_OF_ELEMENT);
}
}
}
}
pub fn fragment_id(&self) -> usize { pub fn fragment_id(&self) -> usize {
return self as *const Fragment as usize; return self as *const Fragment as usize;
} }