Beispiel #1
0
        private static void CategorizeNodesByLabels(
            TreeComparer <TNode> comparer,
            TNode root,
            int labelCount,
            out List <TNode>[] nodes,
            out int totalCount)
        {
            nodes = new List <TNode> [labelCount];
            var count = 0;

            // It is important that we add the nodes in depth-first prefix order.
            // This order ensures that a node of a certain kind can have a parent of the same kind
            // and we can still use tied-to-parent for that kind. That's because the parent will always
            // be processed earlier than the child due to depth-first prefix ordering.
            foreach (var node in comparer.GetDescendants(root))
            {
                var label = comparer.GetLabel(node);
                if (label < 0 || label >= labelCount)
                {
                    throw new InvalidOperationException(string.Format(WorkspacesResources.Label_for_node_0_is_invalid_it_must_be_within_bracket_0_1, node, labelCount));
                }

                var list = nodes[label];
                if (list == null)
                {
                    nodes[label] = list = new List <TNode>();
                }

                list.Add(node);

                count++;
            }

            totalCount = count;
        }
Beispiel #2
0
        internal Edit(EditKind kind, TreeComparer <TNode> comparer, TNode oldNode, TNode newNode)
        {
            Debug.Assert((oldNode == null || oldNode.Equals(null)) == (kind == EditKind.Insert));
            Debug.Assert((newNode == null || newNode.Equals(null)) == (kind == EditKind.Delete));

            Debug.Assert((oldNode == null || oldNode.Equals(null)) ||
                         (newNode == null || newNode.Equals(null)) ||
                         !comparer.TreesEqual(oldNode, newNode));

            _comparer = comparer;
            _kind     = kind;
            _oldNode  = oldNode;
            _newNode  = newNode;
        }
Beispiel #3
0
        internal Edit(EditKind kind, TreeComparer <TNode> comparer, TNode node1, TNode node2)
        {
            Debug.Assert((node1 == null || node1.Equals(default(TNode))) == (kind == EditKind.Insert));
            Debug.Assert((node2 == null || node2.Equals(default(TNode))) == (kind == EditKind.Delete));

            Debug.Assert((node1 == null || node1.Equals(default(TNode))) ||
                         (node2 == null || node2.Equals(default(TNode))) ||
                         !comparer.TreesEqual(node1, node2));

            this.comparer = comparer;
            this.kind     = kind;
            this.node1    = node1;
            this.node2    = node2;
        }
Beispiel #4
0
        internal Edit(EditKind kind, TreeComparer <TNode> comparer, TNode oldNode, TNode newNode)
        {
            Debug.Assert((oldNode == null || oldNode.Equals(default(TNode))) == (kind == EditKind.Insert));
            Debug.Assert((newNode == null || newNode.Equals(default(TNode))) == (kind == EditKind.Delete));

            Debug.Assert((oldNode == null || oldNode.Equals(default(TNode))) ||
                         (newNode == null || newNode.Equals(default(TNode))) ||
                         !comparer.TreesEqual(oldNode, newNode));

            this.comparer = comparer;
            this.kind     = kind;
            this.oldNode  = oldNode;
            this.newNode  = newNode;
        }
Beispiel #5
0
        internal Match(TNode root1, TNode root2, TreeComparer <TNode> nodeComparer, IEnumerable <KeyValuePair <TNode, TNode> > knownMatches)
        {
            this.root1    = root1;
            this.root2    = root2;
            this.comparer = nodeComparer;

            int labelCount = nodeComparer.LabelCount;

            // Calculate chains (not including root node):
            int count1, count2;

            List <TNode>[] nodes1, nodes2;
            CategorizeNodesByLabels(root1, labelCount, out nodes1, out count1);
            CategorizeNodesByLabels(root2, labelCount, out nodes2, out count2);

            // Calculate match:
            this.oneToTwo = new Dictionary <TNode, TNode>(count1);
            this.twoToOne = new Dictionary <TNode, TNode>(count2);

            if (knownMatches != null)
            {
                foreach (var knownMatch in knownMatches)
                {
                    if (comparer.GetLabel(knownMatch.Key) != comparer.GetLabel(knownMatch.Value))
                    {
                        throw new ArgumentException(string.Format("Matching nodes '{0}' and '{1}' must have the same label.".NeedsLocalization(), knownMatch.Key, knownMatch.Value), "knownMatches");
                    }

                    if (!comparer.TreesEqual(knownMatch.Key, root1))
                    {
                        throw new ArgumentException(string.Format("Node '{0}' must be contained in the old tree.".NeedsLocalization(), knownMatch.Key), "knownMatches");
                    }

                    if (!comparer.TreesEqual(knownMatch.Value, root2))
                    {
                        throw new ArgumentException(string.Format("Node '{0}' must be contained in the new tree.".NeedsLocalization(), knownMatch.Value), "knownMatches");
                    }

                    if (!oneToTwo.ContainsKey(knownMatch.Key))
                    {
                        Add(knownMatch.Key, knownMatch.Value);
                    }
                }
            }

            ComputeMatch(nodes1, nodes2);
        }
Beispiel #6
0
        internal Match(TNode root1, TNode root2, TreeComparer <TNode> nodeComparer, IEnumerable <KeyValuePair <TNode, TNode> > knownMatches)
        {
            this.root1    = root1;
            this.root2    = root2;
            this.comparer = nodeComparer;

            int labelCount = nodeComparer.LabelCount;

            // Calculate chains (not including root node):
            int count1, count2;

            List <TNode>[] nodes1, nodes2;
            CategorizeNodesByLabels(root1, labelCount, out nodes1, out count1);
            CategorizeNodesByLabels(root2, labelCount, out nodes2, out count2);

            // Calculate match:
            this.oneToTwo = new Dictionary <TNode, TNode>(count1);
            this.twoToOne = new Dictionary <TNode, TNode>(count2);

            if (knownMatches != null)
            {
                foreach (var knownMatch in knownMatches)
                {
                    if (comparer.GetLabel(knownMatch.Key) != comparer.GetLabel(knownMatch.Value))
                    {
                        throw new ArgumentException(string.Format(WorkspacesResources.MatchingNodesMustHaveTheSameLabel, knownMatch.Key, knownMatch.Value), "knownMatches");
                    }

                    if (!comparer.TreesEqual(knownMatch.Key, root1))
                    {
                        throw new ArgumentException(string.Format(WorkspacesResources.NodeMustBeContainedInTheOldTree, knownMatch.Key), "knownMatches");
                    }

                    if (!comparer.TreesEqual(knownMatch.Value, root2))
                    {
                        throw new ArgumentException(string.Format(WorkspacesResources.NodeMustBeContainedInTheNewTree, knownMatch.Value), "knownMatches");
                    }

                    if (!oneToTwo.ContainsKey(knownMatch.Key))
                    {
                        Add(knownMatch.Key, knownMatch.Value);
                    }
                }
            }

            ComputeMatch(nodes1, nodes2);
        }
Beispiel #7
0
        internal Match(TNode root1, TNode root2, TreeComparer <TNode> comparer, IEnumerable <KeyValuePair <TNode, TNode> > knownMatches)
        {
            _root1    = root1;
            _root2    = root2;
            _comparer = comparer;

            int labelCount = comparer.LabelCount;

            // Calculate chains (not including root node):
            int count1, count2;

            List <TNode>[] nodes1, nodes2;
            CategorizeNodesByLabels(comparer, root1, labelCount, out nodes1, out count1);
            CategorizeNodesByLabels(comparer, root2, labelCount, out nodes2, out count2);

            _oneToTwo = new Dictionary <TNode, TNode>();
            _twoToOne = new Dictionary <TNode, TNode>();

            // Root nodes always match. Add them before adding known matches to make sure we always have root mapping.
            TryAdd(root1, root2);

            if (knownMatches != null)
            {
                foreach (var knownMatch in knownMatches)
                {
                    if (comparer.GetLabel(knownMatch.Key) != comparer.GetLabel(knownMatch.Value))
                    {
                        throw new ArgumentException(string.Format(WorkspacesResources.MatchingNodesMustHaveTheSameLabel, knownMatch.Key, knownMatch.Value), nameof(knownMatches));
                    }

                    if (!comparer.TreesEqual(knownMatch.Key, root1))
                    {
                        throw new ArgumentException(string.Format(WorkspacesResources.NodeMustBeContainedInTheOldTree, knownMatch.Key), nameof(knownMatches));
                    }

                    if (!comparer.TreesEqual(knownMatch.Value, root2))
                    {
                        throw new ArgumentException(string.Format(WorkspacesResources.NodeMustBeContainedInTheNewTree, knownMatch.Value), nameof(knownMatches));
                    }

                    // skip pairs whose key or value is already mapped:
                    TryAdd(knownMatch.Key, knownMatch.Value);
                }
            }

            ComputeMatch(nodes1, nodes2);
        }
Beispiel #8
0
        internal Match(TNode root1, TNode root2, TreeComparer <TNode> comparer, IEnumerable <KeyValuePair <TNode, TNode> > knownMatches)
        {
            _root1    = root1;
            _root2    = root2;
            _comparer = comparer;

            var labelCount = comparer.LabelCount;

            CategorizeNodesByLabels(comparer, root1, labelCount, out var nodes1, out _);
            CategorizeNodesByLabels(comparer, root2, labelCount, out var nodes2, out _);

            _oneToTwo = new Dictionary <TNode, TNode>();
            _twoToOne = new Dictionary <TNode, TNode>();

            // Root nodes always match. Add them before adding known matches to make sure we always have root mapping.
            TryAdd(root1, root2);

            if (knownMatches != null)
            {
                foreach (var knownMatch in knownMatches)
                {
                    if (comparer.GetLabel(knownMatch.Key) != comparer.GetLabel(knownMatch.Value))
                    {
                        throw new ArgumentException(string.Format(WorkspacesResources.Matching_nodes_0_and_1_must_have_the_same_label, knownMatch.Key, knownMatch.Value), nameof(knownMatches));
                    }

                    if (!comparer.TreesEqual(knownMatch.Key, root1))
                    {
                        throw new ArgumentException(string.Format(WorkspacesResources.Node_0_must_be_contained_in_the_old_tree, knownMatch.Key), nameof(knownMatches));
                    }

                    if (!comparer.TreesEqual(knownMatch.Value, root2))
                    {
                        throw new ArgumentException(string.Format(WorkspacesResources.Node_0_must_be_contained_in_the_new_tree, knownMatch.Value), nameof(knownMatches));
                    }

                    // skip pairs whose key or value is already mapped:
                    TryAdd(knownMatch.Key, knownMatch.Value);
                }
            }

            ComputeMatch(nodes1, nodes2);
        }
Beispiel #9
0
 internal Edit(EditKind kind, TreeComparer <TNode> comparer, TNode oldNode, TNode newNode)
 {
     Debug.Assert((oldNode == null || oldNode.Equals(default)) == (kind == EditKind.Insert));