-
Notifications
You must be signed in to change notification settings - Fork 178
/
InlineDiffBuilder.cs
128 lines (107 loc) · 5.51 KB
/
InlineDiffBuilder.cs
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
using System;
using System.Collections.Generic;
using System.Linq;
using DiffPlex.Chunkers;
using DiffPlex.DiffBuilder.Model;
using DiffPlex.Model;
namespace DiffPlex.DiffBuilder
{
public class InlineDiffBuilder : IInlineDiffBuilder
{
private readonly IDiffer differ;
/// <summary>
/// Gets the default singleton instance of the inline diff builder.
/// </summary>
public static InlineDiffBuilder Instance { get; } = new InlineDiffBuilder();
public InlineDiffBuilder(IDiffer differ = null)
{
this.differ = differ ?? Differ.Instance;
}
public DiffPaneModel BuildDiffModel(string oldText, string newText)
=> BuildDiffModel(oldText, newText, ignoreWhitespace: true);
public DiffPaneModel BuildDiffModel(string oldText, string newText, bool ignoreWhitespace)
{
var chunker = new LineChunker();
return BuildDiffModel(oldText, newText, ignoreWhitespace, false, chunker);
}
public DiffPaneModel BuildDiffModel(string oldText, string newText, bool ignoreWhitespace, bool ignoreCase, IChunker chunker)
{
if (oldText == null) throw new ArgumentNullException(nameof(oldText));
if (newText == null) throw new ArgumentNullException(nameof(newText));
var model = new DiffPaneModel();
bool hasDifferences;
var diffResult = differ.CreateDiffs(oldText, newText, ignoreWhitespace, ignoreCase: ignoreCase, chunker);
BuildDiffPieces(diffResult, model.Lines, out hasDifferences);
model.HasDifferences = hasDifferences;
return model;
}
/// <summary>
/// Gets the inline textual diffs.
/// </summary>
/// <param name="oldText">The old text to diff.</param>
/// <param name="newText">The new text.</param>
/// <param name="ignoreWhiteSpace">true if ignore the white space; othewise, false.</param>
/// <param name="ignoreCase">true if case-insensitive; otherwise, false.</param>
/// <param name="chunker">The chunker.</param>
/// <returns>The diffs result.</returns>
public static DiffPaneModel Diff(string oldText, string newText, bool ignoreWhiteSpace = true, bool ignoreCase = false, IChunker chunker = null)
{
return Diff(Differ.Instance, oldText, newText, ignoreWhiteSpace, ignoreCase, chunker);
}
/// <summary>
/// Gets the inline textual diffs.
/// </summary>
/// <param name="differ">The differ instance.</param>
/// <param name="oldText">The old text to diff.</param>
/// <param name="newText">The new text.</param>
/// <param name="ignoreWhiteSpace">true if ignore the white space; othewise, false.</param>
/// <param name="ignoreCase">true if case-insensitive; otherwise, false.</param>
/// <param name="chunker">The chunker.</param>
/// <returns>The diffs result.</returns>
public static DiffPaneModel Diff(IDiffer differ, string oldText, string newText, bool ignoreWhiteSpace = true, bool ignoreCase = false, IChunker chunker = null)
{
if (oldText == null) throw new ArgumentNullException(nameof(oldText));
if (newText == null) throw new ArgumentNullException(nameof(newText));
var model = new DiffPaneModel();
bool hasDifferences;
var diffResult = (differ ?? Differ.Instance).CreateDiffs(oldText, newText, ignoreWhiteSpace, ignoreCase, chunker ?? LineChunker.Instance);
BuildDiffPieces(diffResult, model.Lines, out hasDifferences);
model.HasDifferences = hasDifferences;
return model;
}
private static void BuildDiffPieces(DiffResult diffResult, List<DiffPiece> pieces, out bool hasDifferences)
{
int bPos = 0;
foreach (var diffBlock in diffResult.DiffBlocks)
{
for (; bPos < diffBlock.InsertStartB; bPos++)
pieces.Add(new DiffPiece(diffResult.PiecesNew[bPos], ChangeType.Unchanged, bPos + 1));
int i = 0;
for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++)
pieces.Add(new DiffPiece(diffResult.PiecesOld[i + diffBlock.DeleteStartA], ChangeType.Deleted));
i = 0;
for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++)
{
pieces.Add(new DiffPiece(diffResult.PiecesNew[i + diffBlock.InsertStartB], ChangeType.Inserted, bPos + 1));
bPos++;
}
if (diffBlock.DeleteCountA > diffBlock.InsertCountB)
{
for (; i < diffBlock.DeleteCountA; i++)
pieces.Add(new DiffPiece(diffResult.PiecesOld[i + diffBlock.DeleteStartA], ChangeType.Deleted));
}
else
{
for (; i < diffBlock.InsertCountB; i++)
{
pieces.Add(new DiffPiece(diffResult.PiecesNew[i + diffBlock.InsertStartB], ChangeType.Inserted, bPos + 1));
bPos++;
}
}
}
for (; bPos < diffResult.PiecesNew.Length; bPos++)
pieces.Add(new DiffPiece(diffResult.PiecesNew[bPos], ChangeType.Unchanged, bPos + 1));
hasDifferences = pieces.Any(x => x.Type != ChangeType.Unchanged);
}
}
}