Welcome to mirror list, hosted at ThFree Co, Russian Federation.

HierarchicalDifferenceCollection.cs « DifferenceAlgorithm « Impl « Text « src - github.com/microsoft/vs-editor-api.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 33d06cbf1e2eed05686b23f540d5dbb2fd08d559 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//
//  Copyright (c) Microsoft Corporation. All rights reserved.
//  Licensed under the MIT License. See License.txt in the project root for license information.
//
// This file contain implementations details that are subject to change without notice.
// Use at your own risk.
//
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Microsoft.VisualStudio.Utilities;

namespace Microsoft.VisualStudio.Text.Differencing.Implementation
{
    /// <summary>
    /// The default implementation of IDecomposedDifferenceCollection.  This maintains
    /// a given IDifferenceCollection&lt;string&gt; and a mapping of Difference indices to
    /// contained differences (if there are any).
    /// </summary>
    internal class HierarchicalDifferenceCollection : IHierarchicalDifferenceCollection
    {
        private readonly ITokenizedStringListInternal left;
        private readonly ITokenizedStringListInternal right;
        private readonly IDifferenceCollection<string> differenceCollection;
        private readonly ITextDifferencingService differenceService;
        private readonly StringDifferenceOptions options;

        private readonly ConcurrentDictionary<int, IHierarchicalDifferenceCollection> containedDifferences;

        /// <summary>
        /// Create a new hierarchical difference collection.
        /// </summary>
        /// <param name="differenceCollection">The underlying difference collection for this level
        /// of the hierarchy.</param>
        /// <param name="differenceService">The difference service to use for doing the next level of
        /// differencing</param>
        /// <param name="options">The options to use for the next level of differencing.
        /// If <see cref="StringDifferenceOptions.DifferenceType" /> is <c>0</c>, then
        /// no further differencing will take place.</param>
        public HierarchicalDifferenceCollection(IDifferenceCollection<string> differenceCollection,
                                                ITokenizedStringListInternal left,
                                                ITokenizedStringListInternal right,
                                                ITextDifferencingService differenceService,
                                                StringDifferenceOptions options)
        {
            if (differenceCollection == null)
                throw new ArgumentNullException("differenceCollection");
            if (left == null)
                throw new ArgumentNullException("left");
            if (right == null)
                throw new ArgumentNullException("right");
            if (!object.ReferenceEquals(left, differenceCollection.LeftSequence))
                throw new ArgumentException("left must equal differenceCollection.LeftSequence");
            if (!object.ReferenceEquals(right, differenceCollection.RightSequence))
                throw new ArgumentException("right must equal differenceCollection.RightSequence");

            this.left = left;
            this.right = right;

            this.differenceCollection = differenceCollection;
            this.differenceService = differenceService;
            this.options = options;

            containedDifferences = new ConcurrentDictionary<int, IHierarchicalDifferenceCollection>();
        }

        #region IHierarchicalDifferenceCollection Members

        public ITokenizedStringList LeftDecomposition
        {
            get { return left; }
        }

        public ITokenizedStringList RightDecomposition
        {
            get { return right; }
        }

        public IHierarchicalDifferenceCollection GetContainedDifferences(int index)
        {
            if (options.DifferenceType == 0)
                return null;

            return containedDifferences.GetOrAdd(index, CalculateContainedDiff);
        }

        /// <summary>
        /// Calculate the contained difference at the given index.  Used by the concurrent dictionary's
        /// GetOrAdd that takes a value factory.
        /// </summary>
        private IHierarchicalDifferenceCollection CalculateContainedDiff(int index)
        {
            // We need to compute the next level of differences.
            var diff = this.Differences[index];

            if (diff.DifferenceType == DifferenceType.Change)
            {
                Span leftSpan = this.left.GetSpanInOriginal(diff.Left);
                Span rightSpan = this.right.GetSpanInOriginal(diff.Right);

                string leftString = this.left.OriginalSubstring(leftSpan.Start, leftSpan.Length);
                string rightString = this.right.OriginalSubstring(rightSpan.Start, rightSpan.Length);

                return differenceService.DiffStrings(leftString, rightString, options);
            }

            return null;
        }

        public bool HasContainedDifferences(int index)
        {
            return GetContainedDifferences(index) != null;
        }

        #endregion

        #region IDifferenceCollection<string> Members

        public IList<Difference> Differences
        {
            get { return differenceCollection.Differences;  }
        }

        public IList<string> LeftSequence
        {
            get { return left; }
        }

        public IEnumerable<Tuple<int, int>> MatchSequence
        {
            get { return differenceCollection.MatchSequence; }
        }

        public IList<string> RightSequence
        {
            get { return right; }
        }

        #endregion

        #region IEnumerable<Difference> Members

        public IEnumerator<Difference> GetEnumerator()
        {
            return differenceCollection.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }
}