Пример #1
0
        public void AlignElements_NullAligner_ThrowsArgumentNullException()
        {
            IList <int> collection1 = new int[0];
            IList <int> collection2 = new int[0];
            IEnumerable <DiffSection> diffSections = new DiffSection[0];
            IDiffElementAligner <int> aligner      = null;

            Assert.Throws <ArgumentNullException>(() => Diff.AlignElements(collection1, collection2, diffSections, aligner));
        }
Пример #2
0
 /// <summary>
 /// Construct a new <see cref="StringSimilarity"/>.
 /// </summary>
 /// <param name="modificationThreshold">
 /// A threshold value used to determine if aligned elements are considered replacements or modifications. If
 /// two items are more similar than the threshold specifies (similarity > threshold), then it results in
 /// a <see cref="DiffOperation.Modify"/>, otherwise it results in a <see cref="DiffOperation.Replace"/>.
 /// </param>
 public StringSimilarityDiffElementAligner(double modificationThreshold = 0.3333)
 {
     _Aligner = new ElementSimilarityDiffElementAligner <string>(StringSimilarity, modificationThreshold);
 }
Пример #3
0
        /// <summary>
        /// Mutate the specified list to have the same elements as another list, by inserting or removing as needed. The end result is that
        /// <paramref name="target"/> will have equivalent elements as <paramref name="source"/>, in the same order and positions.
        /// </summary>
        /// <typeparam name="T">
        /// The type of elements in the lists.
        /// </typeparam>
        /// <param name="target">
        /// The list to mutate. Elements will possibly be inserted into or deleted from this list.
        /// </param>
        /// <param name="source">
        /// The list to use as the source of mutations for <paramref name="target"/>.
        /// </param>
        /// <param name="options">
        /// A <see cref="DiffOptions"/> object specifying options to the diff algorithm, or <c>null</c> if defaults should be used.
        /// </param>
        /// <param name="comparer">
        /// The optional <see cref="IEqualityComparer{T}"/> to use when comparing elements.
        /// If not specified/<c>null</c>, <see cref="EqualityComparer{T}.Default"/> will be used.
        /// </param>
        /// <param name="aligner">
        /// The <see cref="IDiffElementAligner{T}"/> to use when aligning elements.
        /// If not specified/<c>null</c>, <see cref="BasicReplaceInsertDeleteDiffElementAligner{T}"/> will be used.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <para><paramref name="target"/> is <c>null</c>.</para>
        /// <para>- or -</para>
        /// <para><paramref name="source"/> is <c>null</c>.</para>
        /// </exception>
        /// <remarks>
        /// The main purpose of this method is to avoid clearing and refilling the list from scratch and instead
        /// make adjustments to it to have the right elements. Useful in conjunction with UI bindings and
        /// similar that react to changes to the list.
        /// </remarks>
        public static void MutateToBeLike <T>([NotNull] this IList <T> target, [NotNull] IList <T> source, [CanBeNull] DiffOptions options, [CanBeNull] IEqualityComparer <T> comparer = null, [CanBeNull] IDiffElementAligner <T> aligner = null)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            options  = options ?? new DiffOptions();
            comparer = comparer ?? EqualityComparer <T> .Default;
            aligner  = aligner ?? new BasicReplaceInsertDeleteDiffElementAligner <T>();

            var sections = Diff.CalculateSections(target, source, options, comparer);
            var items    = Diff.AlignElements(target, source, sections, aligner).ToList();

            Assume.That(items != null);

            int targetIndex = 0;

            foreach (var item in items)
            {
                switch (item.Operation)
                {
                case DiffOperation.Match:
                    targetIndex++;
                    break;

                case DiffOperation.Insert:
                    target.Insert(targetIndex, item.ElementFromCollection2.Value);
                    targetIndex++;
                    break;

                case DiffOperation.Delete:
                    target.RemoveAt(targetIndex);
                    break;

                case DiffOperation.Replace:
                case DiffOperation.Modify:
                    target[targetIndex] = item.ElementFromCollection2.Value;
                    targetIndex++;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
        }
Пример #4
0
 /// <summary>
 /// Mutate the specified list to have the same elements as another list, by inserting or removing as needed. The end result is that
 /// <paramref name="target"/> will have equivalent elements as <paramref name="source"/>, in the same order and positions.
 /// </summary>
 /// <typeparam name="T">
 /// The type of elements in the lists.
 /// </typeparam>
 /// <param name="target">
 /// The list to mutate. Elements will possibly be inserted into or deleted from this list.
 /// </param>
 /// <param name="source">
 /// The list to use as the source of mutations for <paramref name="target"/>.
 /// </param>
 /// <param name="comparer">
 /// The optional <see cref="IEqualityComparer{T}"/> to use when comparing elements.
 /// If not specified/<c>null</c>, <see cref="EqualityComparer{T}.Default"/> will be used.
 /// </param>
 /// <param name="aligner">
 /// The <see cref="IDiffElementAligner{T}"/> to use when aligning elements.
 /// If not specified/<c>null</c>, <see cref="BasicReplaceInsertDeleteDiffElementAligner{T}"/> will be used.
 /// </param>
 /// <exception cref="ArgumentNullException">
 /// <para><paramref name="target"/> is <c>null</c>.</para>
 /// <para>- or -</para>
 /// <para><paramref name="source"/> is <c>null</c>.</para>
 /// </exception>
 /// <remarks>
 /// The main purpose of this method is to avoid clearing and refilling the list from scratch and instead
 /// make adjustments to it to have the right elements. Useful in conjunction with UI bindings and
 /// similar that react to changes to the list.
 /// </remarks>
 public static void MutateToBeLike <T>([NotNull] this IList <T> target, [NotNull] IList <T> source, [CanBeNull] IEqualityComparer <T> comparer = null, [CanBeNull] IDiffElementAligner <T> aligner = null)
 {
     MutateToBeLike(target, source, new DiffOptions(), comparer, aligner);
 }
Пример #5
0
        public static IEnumerable <DiffElement <T> > AlignElements <T>([NotNull] IList <T> collection1, [NotNull] IList <T> collection2, [NotNull] IEnumerable <DiffSection> diffSections, [NotNull] IDiffElementAligner <T> aligner)
        {
            if (collection1 == null)
            {
                throw new ArgumentNullException(nameof(collection1));
            }
            if (collection2 == null)
            {
                throw new ArgumentNullException(nameof(collection2));
            }
            if (diffSections == null)
            {
                throw new ArgumentNullException(nameof(diffSections));
            }
            if (aligner == null)
            {
                throw new ArgumentNullException(nameof(aligner));
            }

            return(AlignElementsImplementation(collection1, collection2, diffSections, aligner));
        }
Пример #6
0
        private static IEnumerable <DiffElement <T> > AlignElementsImplementation <T>([NotNull] IList <T> collection1, [NotNull] IList <T> collection2, [NotNull] IEnumerable <DiffSection> diffSections, [NotNull] IDiffElementAligner <T> aligner)
        {
            int start1 = 0;
            int start2 = 0;

            foreach (var section in diffSections)
            {
                if (section.IsMatch)
                {
                    for (int index = 0; index < section.LengthInCollection1; index++)
                    {
                        yield return(new DiffElement <T>(collection1[start1], collection2[start2], DiffOperation.Match));

                        start1++;
                        start2++;
                    }
                }
                else
                {
                    foreach (var element in aligner.Align(collection1, start1, section.LengthInCollection1, collection2, start2, section.LengthInCollection2))
                    {
                        yield return(element);
                    }

                    start1 += section.LengthInCollection1;
                    start2 += section.LengthInCollection2;
                }
            }
        }
Пример #7
0
        public Merge([NotNull] IList <T> commonBase, [NotNull] IList <T> left, [NotNull] IList <T> right, [NotNull] IDiffElementAligner <T> aligner, [NotNull] IMergeConflictResolver <T> conflictResolver, [NotNull] IEqualityComparer <T> comparer, [NotNull] DiffOptions diffOptions)
        {
            if (commonBase == null)
            {
                throw new ArgumentNullException(nameof(commonBase));
            }
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }
            if (aligner == null)
            {
                throw new ArgumentNullException(nameof(aligner));
            }
            if (comparer == null)
            {
                throw new ArgumentNullException(nameof(comparer));
            }
            if (diffOptions == null)
            {
                throw new ArgumentNullException(nameof(diffOptions));
            }

            _ConflictResolver = conflictResolver ?? throw new ArgumentNullException(nameof(conflictResolver));

            var diffCommonBaseToLeft = Diff.AlignElements(commonBase, left, Diff.CalculateSections(commonBase, left, diffOptions, comparer), aligner).ToList();

            Assume.That(diffCommonBaseToLeft != null);
            _DiffCommonBaseToLeft = diffCommonBaseToLeft;

            var diffCommonBaseToRight = Diff.AlignElements(commonBase, right, Diff.CalculateSections(commonBase, right, diffOptions, comparer), aligner).ToList();

            Assume.That(diffCommonBaseToRight != null);
            _DiffCommonBaseToRight = diffCommonBaseToRight;

            var mergeSections = Diff.CalculateSections(diffCommonBaseToLeft, diffCommonBaseToRight, diffOptions, new DiffSectionMergeComparer <T>(comparer)).ToList();

            Assume.That(mergeSections != null);
            _MergeSections = mergeSections;
        }
Пример #8
0
        public static IEnumerable <T> Perform <T>([NotNull] IList <T> commonBase, [NotNull] IList <T> left, [NotNull] IList <T> right, [CanBeNull] DiffOptions diffOptions, [NotNull] IDiffElementAligner <T> aligner, [NotNull] IMergeConflictResolver <T> conflictResolver, [CanBeNull] IEqualityComparer <T> comparer = null)
        {
            if (commonBase == null)
            {
                throw new ArgumentNullException(nameof(commonBase));
            }
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }
            if (aligner == null)
            {
                throw new ArgumentNullException(nameof(aligner));
            }
            if (conflictResolver == null)
            {
                throw new ArgumentNullException(nameof(conflictResolver));
            }

            diffOptions = diffOptions ?? new DiffOptions();
            comparer    = comparer ?? EqualityComparer <T> .Default;
            Assume.That(comparer != null);

            return(new Merge <T>(commonBase, left, right, aligner, conflictResolver, comparer, diffOptions));
        }
Пример #9
0
 public static IEnumerable <T> Perform <T>([NotNull] IList <T> commonBase, [NotNull] IList <T> left, [NotNull] IList <T> right, [NotNull] IDiffElementAligner <T> aligner, [NotNull] IMergeConflictResolver <T> conflictResolver, [CanBeNull] IEqualityComparer <T> comparer = null)
 {
     return(Perform(commonBase, left, right, new DiffOptions(), aligner, conflictResolver, comparer));
 }