예제 #1
0
            protected bool CompareChildren <TNode, TParent>(
                NodeComparison <TNode, TParent> compare,
                IReadOnlyList <TNode> oldChildren,
                IReadOnlyList <TNode> newChildren,
                TParent newNodeParent,
                CodeModelEventType eventType,
                CodeModelEventQueue eventQueue
                )
                where TNode : SyntaxNode
                where TParent : SyntaxNode
            {
                var oldCount = oldChildren.Count;
                var newCount = newChildren.Count;

                if (oldCount == newCount)
                {
                    return(FindDifferentChild(
                               compare,
                               oldChildren,
                               newChildren,
                               newNodeParent,
                               eventQueue
                               ));
                }
                else if (Math.Abs(oldCount - newCount) > MaxChildDelta)
                {
                    // We got two discrepancies, enqueue element changed node for containing node
                    EnqueueChangeEvent(newNodeParent, null, eventType, eventQueue);
                }
                else
                {
                    if (oldCount > newCount)
                    {
                        FindRemovedChild(
                            compare,
                            oldChildren,
                            newChildren,
                            newNodeParent,
                            oldCount - newCount,
                            eventQueue
                            );
                    }
                    else
                    {
                        FindAddedChild(
                            compare,
                            oldChildren,
                            newChildren,
                            newNodeParent,
                            newCount - oldCount,
                            eventQueue
                            );
                    }
                }

                return(false);
            }
예제 #2
0
            private bool FindDifferentChild <TNode, TParent>(
                NodeComparison <TNode, TParent> compare,
                IReadOnlyList <TNode> oldChildren,
                IReadOnlyList <TNode> newChildren,
                TParent newNodeParent,
                CodeModelEventQueue eventQueue
                )
                where TNode : SyntaxNode
                where TParent : SyntaxNode
            {
                Debug.Assert(oldChildren.Count == newChildren.Count);

                var eventCount = eventQueue != null ? eventQueue.Count : 0;

                var hasChanges = false;

                // Find first child that is different.
                int i;

                for (i = 0; i < oldChildren.Count; i++)
                {
                    if (!compare(oldChildren[i], newChildren[i], newNodeParent, eventQueue))
                    {
                        hasChanges = true;
                        i++;
                        break;
                    }
                }

                // Look for a second different child. If there is one, we'll throw away any events from
                // the first different child and enqueue an unknown event on the containing node.
                for (; i < oldChildren.Count; i++)
                {
                    if (!compare(oldChildren[i], newChildren[i], newNodeParent, null))
                    {
                        // rollback any events added by the first difference
                        if (eventQueue != null)
                        {
                            while (eventQueue.Count > eventCount)
                            {
                                eventQueue.Discard();
                            }
                        }

                        EnqueueChangeEvent(
                            newNodeParent,
                            null,
                            CodeModelEventType.Unknown,
                            eventQueue
                            );
                        return(false);
                    }
                }

                return(!hasChanges);
            }
예제 #3
0
            private void FindRemovedChild <TNode, TParent>(
                NodeComparison <TNode, TParent> compare,
                IReadOnlyList <TNode> oldChildren,
                IReadOnlyList <TNode> newChildren,
                TParent newNodeParent,
                CodeModelEventType codeModelEventType,
                int delta,
                CodeModelEventQueue eventQueue)
                where TNode : SyntaxNode
                where TParent : SyntaxNode
            {
                Debug.Assert(oldChildren.Count - delta == newChildren.Count);

                // The strategy is to assume that all of the removed children are contiguous.
                // If that turns out not to be the case, an unknown change event is raised
                // for the containing node.

                var firstRemoved = -1;

                // Look for the first different child. If there is one, track that index as
                // the first added node.
                int oldIndex, newIndex;

                for (oldIndex = 0, newIndex = 0; oldIndex < oldChildren.Count; oldIndex++, newIndex++)
                {
                    if (newIndex >= newChildren.Count || !compare(oldChildren[oldIndex], newChildren[newIndex], newNodeParent, null))
                    {
                        firstRemoved = oldIndex;
                        oldIndex    += delta;
                        break;
                    }
                }

                // Look for a second different child. If there is one, we'll throw away any events from
                // the first different child and enqueue an unknown event on the containing node.
                for (; oldIndex < oldChildren.Count; oldIndex++, newIndex++)
                {
                    if (!compare(oldChildren[oldIndex], newChildren[newIndex], newNodeParent, null))
                    {
                        EnqueueChangeEvent(newNodeParent, null, CodeModelEventType.Unknown, eventQueue);
                        return;
                    }
                }

                if (firstRemoved >= 0)
                {
                    for (var i = 0; i < delta; i++)
                    {
                        EnqueueRemoveEvent(oldChildren[firstRemoved + i], newNodeParent, eventQueue);
                    }
                }
            }
예제 #4
0
            protected DeclarationChange CompareRenamedDeclarations <TNode, TParent>(
                NodeComparison <TNode, TParent> compare,
                IReadOnlyList <TNode> oldChildren,
                IReadOnlyList <TNode> newChildren,
                SyntaxNode oldNode,
                SyntaxNode newNode,
                TParent newNodeParent,
                CodeModelEventQueue eventQueue
                )
                where TNode : SyntaxNode
                where TParent : SyntaxNode
            {
                var oldCount = oldChildren.Count;
                var newCount = newChildren.Count;

                if (oldCount == newCount)
                {
                    // We now check the children of the old and new types against each other. If any of them have changed,
                    // it means that the old type has essentially been removed and a new one added.
                    for (var i = 0; i < oldCount; i++)
                    {
                        if (!compare(oldChildren[i], newChildren[i], newNodeParent, null))
                        {
                            EnqueueRemoveEvent(oldNode, newNodeParent, eventQueue);
                            EnqueueAddEvent(newNode, newNodeParent, eventQueue);

                            // Report that the whole declaration has changed
                            return(DeclarationChange.WholeDeclaration);
                        }
                    }

                    // The children are all the same, so only the name has changed.
                    return(DeclarationChange.NameOnly);
                }
                else
                {
                    // Since the number of members is different, essentially the old type has been removed, and a new one added.
                    EnqueueRemoveEvent(oldNode, newNodeParent, eventQueue);
                    EnqueueAddEvent(newNode, newNodeParent, eventQueue);

                    // Report that the whole declaration has changed
                    return(DeclarationChange.WholeDeclaration);
                }
            }
예제 #5
0
        private static bool PerformRecursive(List <NodeBase> nodes)
        {
            List <NodeBase> valueNodes = new List <NodeBase>();

            NodeBase firstNode        = nodes[0];
            bool     isValueNodeLevel = firstNode is ValueNodeBase;

            List <List <NodeBase> > childNodeArrays = new List <List <NodeBase> >();
            int childNodeCount = firstNode.Children.Count;

            for (int i = 0; i < childNodeCount; i++)
            {
                childNodeArrays.Add(new List <NodeBase>());
                childNodeArrays[i].Add(firstNode.Children[i]);
            }

            for (int i = 1; i < nodes.Count; i++)
            {
                NodeBase       node   = nodes[i];
                NodeComparison result = firstNode.ShallowCompare(node);

                if (result == NodeComparison.Incompatible)
                {
                    return(false);
                }

                if (isValueNodeLevel)
                {
                    valueNodes.Add(node);
                }
                else
                {
                    if (result == NodeComparison.Unequal)
                    {
                        return(false);
                    }

                    // Handle children
                    for (int j = 0; j < childNodeCount; j++)
                    {
                        childNodeArrays[j].Add(node.Children[j]);
                    }
                }
            }

            if (isValueNodeLevel)
            {
                if (s_valueDiscrepancy != null)                 // There is already an existing recorded discrepancy (only one allowed)
                {
                    return(false);
                }

                s_valueDiscrepancy = new ValueDiscrepancy(valueNodes, (firstNode as ValueNodeBase).TypeIndex);
                return(true);
            }


            for (int i = 0; i < childNodeCount; i++)
            {
                if (!PerformRecursive(childNodeArrays[i]))
                {
                    return(false);
                }
            }

            return(true);
        }