Browse Source

XML Parser: Do not remove items from other location during insert - just set parent pointer

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4662 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 16 years ago
parent
commit
98f7ccb611
  1. 42
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/XmlParser/RawObjects.cs

42
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/XmlParser/RawObjects.cs

@ -348,9 +348,10 @@ namespace ICSharpCode.AvalonEdit.XmlParser @@ -348,9 +348,10 @@ namespace ICSharpCode.AvalonEdit.XmlParser
RawDocument document = this.Document;
Assert(document != null);
Assert(item.Parent != this, "Can not own item twice");
// Remove from the old location and set parent
Steal(document, item, true);
SetParentPointersInTree(document, item);
this.Children.InsertItemAt(index, item);
@ -362,39 +363,36 @@ namespace ICSharpCode.AvalonEdit.XmlParser @@ -362,39 +363,36 @@ namespace ICSharpCode.AvalonEdit.XmlParser
/// </summary>
/// <remarks>
/// Cache constraint:
/// If cached item has parent set, then the whole subtree must be consistent
/// If cached item has parent set, then the whole subtree must be consistent
/// </remarks>
void Steal(RawDocument myDocument, RawObject item, bool allowSealFromSelf)
void SetParentPointersInTree(RawDocument myDocument, RawObject item)
{
// All items are in parser cache
// All items come from the parser cache
if (item.Parent == null) {
// Dangling object - either a new parser object or removed tree (still cached)
item.Parent = this;
if (item is RawContainer) {
foreach(RawObject child in ((RawContainer)item).Children) {
// Note: What if node is attached and then detached
// -> the root has null parent, but childs are pointing to it
if (child.Parent != item) {
// Null parent or someone else owns it
((RawContainer)item).Steal(myDocument, child, false);
}
((RawContainer)item).SetParentPointersInTree(myDocument, child);
}
}
} else if (item.Parent == this) {
// If node is attached and then deattached, it will have null parent pointer
// but valid subtree - so its children will alredy have correct parent pointer
// like in this case
item.CheckConsistency();
// Rest of the tree is consistent - do not recurse
} else {
// The object is in the cache and the cache is/was used in the document.
// Verify cache constraint - subtree consistent
// From cache & parent set => consitent subtree
item.CheckConsistency();
// The parent (or any futher parents) can not be part of parsed document
// becuase otherwise this item would be included twice
// -> So it safe to remove it from parent
// - The parent may be even us
if (item.Parent == this && !allowSealFromSelf)
throw new Exception("You can not steal from yourself");
// Maintain cache constraint by removing parents from cache
myDocument.Parser.RemoveFromCache(item.Parent); // Document of the item may be null
// Remove from the other location
var owingList = ((RawContainer)item.Parent).Children;
owingList.RemoveItemAt(owingList.IndexOf(item));
// becuase otherwise this item would be included twice => safe to change parents
Assert(item.Document == null);
// Maintain cache constraint by setting parents to null
foreach(RawObject ancest in item.GetAncestors().ToList()) {
ancest.Parent = null;
}
item.Parent = this;
// Rest of the tree is consistent - do not recurse
}

Loading…
Cancel
Save