Beispiel #1
0
        /// <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.GreenNode;
            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
            // the max possible number of slots is 11 (TypeDeclarationSyntax)
            // and typically much less than that
            //
            // 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)
                {
                    int 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 (separated or not), most common case
                return(red.GetNodeSlot(idx));
            }

            // this is a single node or token
            return(red);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        /// <summary>
        /// internal indexer that does not verify index.
        /// Used when caller has already ensured that index is within bounds.
        /// </summary>
        internal static SyntaxNode ItemInternal(SyntaxNode node, int index)
        {
            GreenNode greenChild;
            var       green     = node.GreenNode;
            var       idx       = index;
            var       slotIndex = 0;
            var       position  = node.Start;

            // 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
            // the max possible number of slots is 11 (TypeDeclarationSyntax)
            // and typically much less than that
            //
            // 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
            // 3) slot position - position
            while (true)
            {
                greenChild = green.GetSlot(slotIndex);
                if (greenChild != null)
                {
                    int currentOccupancy = Occupancy(greenChild);
                    if (idx < currentOccupancy)
                    {
                        break;
                    }

                    idx      -= currentOccupancy;
                    position += greenChild.FullWidth;
                }

                slotIndex++;
            }

            // get node that represents this slot
            var red = node.GetNodeSlot(slotIndex);

            if (!greenChild.IsList)
            {
                // this is a single node or token
                // if it is a node, we are done
                // otherwise will have to make a token with current gChild and position
                if (red != null)
                {
                    return(red);
                }
            }
            else if (red != null)
            {
                // it is a red list of nodes (separated or not), most common case
                var redChild = red.GetNodeSlot(idx);
                if (redChild != null)
                {
                    // this is our node
                    return(redChild);
                }

                // must be a separator
                // update gChild and position and let it be handled as a token
                greenChild = greenChild.GetSlot(idx);
                position   = red.GetChildPosition(idx);
            }
            else
            {
                // it is a token from a token list, uncommon case
                // update gChild and position and let it be handled as a token
                position  += greenChild.GetSlotOffset(idx);
                greenChild = greenChild.GetSlot(idx);
            }

            return(node);
        }
Beispiel #4
0
        /// <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 SyntaxNode ChildThatContainsPosition(SyntaxNode node, int targetPosition)
        {
            // The targetPosition must already be within this node
            Debug.Assert(node.FullSpan.Contains(targetPosition));

            var green    = node.GreenNode;
            var position = node.Start;
            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
            // 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)
                {
                    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 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(node);
        }
Beispiel #5
0
 private static SyntaxNode GetNodeAt(SyntaxNode node, int i)
 {
     Debug.Assert(node.IsList || (i == 0 && !node.IsList));
     return(node.IsList ? node.GetNodeSlot(i) : node);
 }
Beispiel #6
0
        public static SyntaxNode FindNode(
            this SyntaxNode node,
            int position,
            Func <SyntaxNode, bool> descendIntoChildren = null,
            bool includeTrivia   = true,
            bool excludeTerminal = false)
        {
            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 = includeTrivia ? node.GetSlotCountIncludingTrivia() : node.SlotCount;

                for (int i = index; i < slotCount; i++)
                {
                    var child = includeTrivia ? node.GetSlotIncludingTrivia(i) : node.GetNodeSlot(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
                        {
                            // We have hit a terminal, maybe we should be returning its non-terminal parent
                            if (child.SlotCount == 0 && excludeTerminal)
                            {
                                return(node);
                            }
                            node           = child;
                            searchChildren = true;
                            break;
                        }
                    }
                }
            }

            return(node);
        }