/// <summary> /// Locate the node or token 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 or token that spans the given position.</returns> /// <remarks> /// Assumes that <paramref name="targetPosition"/> is within the span of <paramref name="node"/>. /// </remarks> internal static SyntaxNodeOrToken ChildThatContainsPosition(SyntaxNode node, int targetPosition) { // The targetPosition must already be within this node Debug.Assert(node.FullSpan.Contains(targetPosition)); GreenNode green = node.Green; int position = node.Position; int 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 // The max possible number of slots is 11 (TypeDeclarationSyntax) // and typically much less than that int slot; for (slot = 0; ; slot++) { GreenNode greenChild = green.GetSlot(slot); if (greenChild != null) { int 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) SyntaxNode red = node.GetNodeSlot(slot); if (!green.IsList) { // This is a single node or token. // If it is a node, we are done. if (red != null) { return(red); } // Otherwise will have to make a token with current green and position } else { slot = green.FindSlotIndexContainingOffset(targetPosition - position); // Realize the red node (if any) if (red != null) { // It is a red list of nodes (separated or not) red = red.GetNodeSlot(slot); if (red != null) { return(red); } // Must be a separator } // Otherwise we have a token. position += green.GetSlotOffset(slot); green = green.GetSlot(slot); // Since we can't have "lists of lists", the Occupancy calculation for // child elements in a list is simple. index += slot; } // Make a token with current child and position. return(new SyntaxNodeOrToken(node, green, position, index)); }