/// <summary> /// Removes nodes from the tree collection if node range is /// // partially or entirely within the deleted region. /// This is needed since parsing is asynchronous and without /// removing damaged nodes so intellisense will still be able /// to find them in the tree which actually they are gone. /// Returns true if full parse required. /// </summary> /// <param name="node">Node to start from</param> /// <param name="range">Range to invalidate elements in</param> internal bool InvalidateInRange(IAstNode node, ITextRange range, out bool nodesChanged) { var removedElements = new List <IAstNode>(); bool fullParseRequired = false; int firstToRemove = -1; int lastToRemove = -1; nodesChanged = false; for (int i = 0; i < node.Children.Count; i++) { var child = node.Children[i]; bool removeChild = false; if (range.Start == child.Start && range.Length == 0) { // Change is right before the node break; } if (!removeChild && TextRange.Intersect(range, child)) { bool childElementsChanged; if (child is TokenNode) { childElementsChanged = true; fullParseRequired = true; nodesChanged = true; } else { fullParseRequired |= InvalidateInRange(child, range, out childElementsChanged); if (childElementsChanged) { nodesChanged = true; } } removeChild = true; } if (removeChild) { if (firstToRemove < 0) { firstToRemove = i; } lastToRemove = i; } } if (firstToRemove >= 0) { for (int i = firstToRemove; i <= lastToRemove; i++) { IAstNode child = node.Children[i]; removedElements.Add(child); _astRoot.Errors.RemoveInRange(child); } node.RemoveChildren(firstToRemove, lastToRemove - firstToRemove + 1); } if (removedElements.Count > 0) { nodesChanged = true; FireOnNodesRemoved(removedElements); } return(fullParseRequired); }
/// <summary> /// Removes nodes from the tree collection if node range is /// // partially or entirely within the deleted region. /// This is needed since parsing is asynchronous and without /// removing damaged nodes so intellisense will still be able /// to find them in the tree which actually they are gone. /// Returns true if full parse required. /// </summary> /// <param name="node">Node to start from</param> /// <param name="range">Range to invalidate elements in</param> internal bool InvalidateInRange(IAstNode node, ITextRange range, out bool nodesChanged) { var removedElements = new List<IAstNode>(); bool fullParseRequired = false; int firstToRemove = -1; int lastToRemove = -1; nodesChanged = false; for (int i = 0; i < node.Children.Count; i++) { var child = node.Children[i]; bool removeChild = false; if (range.Start == child.Start && range.Length == 0) { // Change is right before the node break; } if (!removeChild && TextRange.Intersect(range, child)) { bool childElementsChanged; if (child is TokenNode) { childElementsChanged = true; fullParseRequired = true; nodesChanged = true; } else { fullParseRequired |= InvalidateInRange(child, range, out childElementsChanged); if (childElementsChanged) { nodesChanged = true; } } removeChild = true; } if (removeChild) { if (firstToRemove < 0) firstToRemove = i; lastToRemove = i; } } if (firstToRemove >= 0) { for (int i = firstToRemove; i <= lastToRemove; i++) { IAstNode child = node.Children[i]; removedElements.Add(child); _astRoot.Errors.RemoveInRange(child); } node.RemoveChildren(firstToRemove, lastToRemove - firstToRemove + 1); } if (removedElements.Count > 0) { nodesChanged = true; FireOnNodesRemoved(removedElements); } return fullParseRequired; }