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);
        }
Exemple #2
0
        private static int ComputeFullWidthIterative(SyntaxNode node, int start = 0)
        {
            if (node.fullWidth >= 0)
            {
                return(node.fullWidth);
            }

            node.Start = start;

            Stack <ComputeFullWidthState> nodes = new Stack <ComputeFullWidthState>();

            nodes.Push(new ComputeFullWidthState()
            {
                Node = node
            });

            while (nodes.Count != 0)
            {
                var state = nodes.Pop();

AfterPopState:
                node = state.Node;
                if (node.fullWidth == -1)
                {
                    node.fullWidth = node.GetTextWidth();

                    // Node full width is now zero or the node is a token/trivial
                    // and the full width represents the width of the text
                    // for the token/trivia. Therefore, start is only incremented
                    // for tokens and trivia.
                    start += node.fullWidth;
                }

                var parent = state.Parent;

                var slotCount = node.GetSlotCountIncludingTrivia();
                for (; state.Index < slotCount; state.Index++)
                {
                    var child = node.GetSlotIncludingTrivia(state.Index);
                    if (child == null)
                    {
                        continue;
                    }

                    child.Parent = node;
                    child.Start  = start;

                    if (child.fullWidth == -1)
                    {
                        state.Index++;
                        nodes.Push(state);

                        state = new ComputeFullWidthState()
                        {
                            Node   = child,
                            Parent = node
                        };

                        goto AfterPopState;
                    }
                    else
                    {
                        start          += child.fullWidth;
                        node.fullWidth += child.fullWidth;
                    }
                }

                if (parent != null)
                {
                    if (parent.fullWidth == -1)
                    {
                        parent.fullWidth = 0;
                    }

                    parent.fullWidth += node.fullWidth;
                }
            }

            return(node.fullWidth);
        }