protected override SyntaxNode DefaultVisit(SyntaxNode node) { _ancestors.Insert(0, node); try { for (var i = 0; i < node.SlotCount; i++) { var child = node.GetNodeSlot(i); Visit(child); } } finally { _ancestors.RemoveAt(0); } return(node); }
static void AddTokens(SyntaxNode current, SyntaxListBuilder <SyntaxToken> tokens) { if (current.SlotCount == 0 && current is SyntaxToken token) { // Token tokens.Add(token); return; } for (var i = 0; i < current.SlotCount; i++) { var child = current.GetNodeSlot(i); if (child != null) { AddTokens(child, tokens); } } }
/// <summary> /// internal indexer that does not verify index. /// Used when caller has already ensured that index is within bounds. /// </summary> internal static SyntaxNode ItemInternalAsNode(SyntaxNode node, int index) { GreenNode greenChild; var green = node.Green; var idx = index; var slotIndex = 0; // find a slot that contains the node or its parent list (if node is in a list) // we will be skipping whole slots here so we will not loop for long // // at the end of this loop we will have // 1) slot index - slotIdx // 2) if the slot is a list, node index in the list - idx while (true) { greenChild = green.GetSlot(slotIndex); if (greenChild != null) { var currentOccupancy = Occupancy(greenChild); if (idx < currentOccupancy) { break; } idx -= currentOccupancy; } slotIndex++; } // get node that represents this slot var red = node.GetNodeSlot(slotIndex); if (greenChild.IsList && red != null) { // it is a red list of nodes, most common case return(red.GetNodeSlot(idx)); } // this is a single node return(red); }
private static SyntaxNode GetNodeAt(SyntaxNode node, int i) { Debug.Assert(node.IsList || (i == 0 && !node.IsList)); return(node.IsList ? node.GetNodeSlot(i) : node); }
/// <summary> /// Locate the node that is a child of the given <see cref="SyntaxNode"/> and contains the given position. /// </summary> /// <param name="node">The <see cref="SyntaxNode"/> to search.</param> /// <param name="targetPosition">The position.</param> /// <returns>The node that spans the given position.</returns> /// <remarks> /// Assumes that <paramref name="targetPosition"/> is within the span of <paramref name="node"/>. /// </remarks> internal static SyntaxNode ChildThatContainsPosition(SyntaxNode node, int targetPosition) { // The targetPosition must already be within this node Debug.Assert(node.FullSpan.Contains(targetPosition)); var green = node.Green; var position = node.Position; var index = 0; Debug.Assert(!green.IsList); // Find the green node that spans the target position. // We will be skipping whole slots here so we will not loop for long int slot; for (slot = 0; ; slot++) { var greenChild = green.GetSlot(slot); if (greenChild != null) { var endPosition = position + greenChild.FullWidth; if (targetPosition < endPosition) { // Descend into the child element green = greenChild; break; } position = endPosition; index += Occupancy(greenChild); } } // Realize the red node (if any) var red = node.GetNodeSlot(slot); if (!green.IsList) { // This is a single node. // If it is a node, we are done. if (red != null) { return(red); } } else { slot = green.FindSlotIndexContainingOffset(targetPosition - position); // Realize the red node (if any) if (red != null) { // It is a red list of nodes red = red.GetNodeSlot(slot); if (red != null) { return(red); } } // Since we can't have "lists of lists", the Occupancy calculation for // child elements in a list is simple. index += slot; } return(node); }