public static SyntaxNode FindNode( this SyntaxNode node, int position, Func <SyntaxNode, bool> descendIntoChildren = null) { if (node == null) { throw new ArgumentNullException(nameof(node)); } int offset = position; bool searchChildren = true; while (searchChildren) { if (descendIntoChildren?.Invoke(node) == false) { break; } // set to false, so loop will only continue if explicitly // specified in a later stage searchChildren = false; int index; node.GetIndexAndOffset(offset, out index, out offset); if (index > 0) { index--; } var slotCount = node.GetSlotCountIncludingTrivia(); for (int i = index; i < slotCount; i++) { var child = node.GetSlotIncludingTrivia(i); if (child != null) { if (child.Start > position) { // child is after position break; } else if ((child.Start + child.FullWidth) <= position) { // child ends before position, go to next child continue; } else { node = child; searchChildren = true; break; } } } } return(node); }
public static int VisitRecursive( SyntaxNode node, int windowStart, int windowLength, Action <int, int, SyntaxNode, XmlClassificationTypes> resultCollector, int start = 0) { if (node == null) { return(0); } XmlClassificationTypes[] childTypes = null; kindMap.TryGetValue(node.Kind, out childTypes); int visitedCount = 0; int windowEnd = windowStart + windowLength; var targetOffset = windowStart - start; int offset; int index; node.GetIndexAndOffset(targetOffset, out index, out offset); start += offset; for (int i = index; i < node.SlotCount; i++) { if (start > windowEnd) { break; } var child = node.GetNodeSlot(i); visitedCount++; if (child == null) { continue; } var currentStart = Math.Max(start, windowStart); var currentLength = Math.Min(windowEnd, start + child.FullWidth) - currentStart; if (currentLength >= 0) { var childType = childTypes == null ? XmlClassificationTypes.None : childTypes[i]; if (childType == XmlClassificationTypes.None) { if (child.Kind == SyntaxKind.XmlTextLiteralToken) { childType = XmlClassificationTypes.XmlText; } else if (child.Kind == SyntaxKind.XmlEntityLiteralToken) { childType = XmlClassificationTypes.XmlEntityReference; } } if (childType == XmlClassificationTypes.None) { visitedCount += VisitRecursive(child, windowStart, windowLength, resultCollector, start); } else { if (currentLength > 0) { resultCollector(currentStart, currentLength, child, childType); } } } start += child.FullWidth; } return(visitedCount); }
private static int VisitChildren( SyntaxNode syntaxNode, int windowStart, int windowLength, Action<int, int, SyntaxNode, XmlClassificationTypes> resultCollector, int start, XmlClassificationTypes[] childTypes) { int visitedCount = 0; int windowEnd = windowStart + windowLength; var targetOffset = windowStart - start; int offset; int index; syntaxNode.GetIndexAndOffset(targetOffset, out index, out offset); start += offset; for (int i = index; i < syntaxNode.SlotCount; i++) { if (start > windowEnd) { break; } var child = syntaxNode.GetSlot(i); visitedCount++; if (child == null) { continue; } var currentStart = Math.Max(start, windowStart); var currentLength = Math.Min(windowEnd, start + child.FullWidth) - currentStart; if (currentLength >= 0) { var childType = childTypes == null ? XmlClassificationTypes.None : childTypes[i]; if (childType == XmlClassificationTypes.None) { if (child.Kind == SyntaxKind.XmlTextLiteralToken) { childType = XmlClassificationTypes.XmlText; } else if (child.Kind == SyntaxKind.XmlEntityLiteralToken) { childType = XmlClassificationTypes.XmlEntityReference; } } if (childType == XmlClassificationTypes.None) { visitedCount += Visit(child, windowStart, windowLength, resultCollector, start); } else { if (currentLength > 0) { resultCollector(currentStart, currentLength, child, childType); } } } start += child.FullWidth; } return visitedCount; }