Skip to content

Commit e87a164

Browse files
sharwellmmanela
authored andcommitted
Allow diff generation to consider whitespace
1 parent 9493cb3 commit e87a164

5 files changed

Lines changed: 302 additions & 8 deletions

File tree

DiffPlex/DiffBuilder/InlineDiffBuilder.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@ public InlineDiffBuilder(IDiffer differ)
1515
}
1616

1717
public DiffPaneModel BuildDiffModel(string oldText, string newText)
18+
=> BuildDiffModel(oldText, newText, ignoreWhitespace: true);
19+
20+
public DiffPaneModel BuildDiffModel(string oldText, string newText, bool ignoreWhitespace)
1821
{
1922
if (oldText == null) throw new ArgumentNullException(nameof(oldText));
2023
if (newText == null) throw new ArgumentNullException(nameof(newText));
2124

2225
var model = new DiffPaneModel();
23-
var diffResult = differ.CreateLineDiffs(oldText, newText, ignoreWhitespace: true);
26+
var diffResult = differ.CreateLineDiffs(oldText, newText, ignoreWhitespace);
2427
BuildDiffPieces(diffResult, model.Lines);
2528
return model;
2629
}

DiffPlex/DiffBuilder/Model/DiffPiece.cs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23

34
namespace DiffPlex.DiffBuilder.Model
45
{
@@ -11,7 +12,7 @@ public enum ChangeType
1112
Modified
1213
}
1314

14-
public class DiffPiece
15+
public class DiffPiece : IEquatable<DiffPiece>
1516
{
1617
public ChangeType Type { get; set; }
1718
public int? Position { get; set; }
@@ -29,5 +30,48 @@ public DiffPiece()
2930
: this(null, ChangeType.Imaginary)
3031
{
3132
}
33+
34+
public override bool Equals(object obj)
35+
{
36+
return Equals(obj as DiffPiece);
37+
}
38+
39+
public bool Equals(DiffPiece other)
40+
{
41+
return other != null
42+
&& Type == other.Type
43+
&& EqualityComparer<int?>.Default.Equals(Position, other.Position)
44+
&& Text == other.Text
45+
&& SubPiecesEqual(other);
46+
}
47+
48+
public override int GetHashCode()
49+
{
50+
var hashCode = 1688038063;
51+
hashCode = hashCode * -1521134295 + Type.GetHashCode();
52+
hashCode = hashCode * -1521134295 + EqualityComparer<int?>.Default.GetHashCode(Position);
53+
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Text);
54+
hashCode = hashCode * -1521134295 + EqualityComparer<int?>.Default.GetHashCode(SubPieces?.Count);
55+
return hashCode;
56+
}
57+
58+
private bool SubPiecesEqual(DiffPiece other)
59+
{
60+
if (SubPieces is null)
61+
return other.SubPieces is null;
62+
else if (other.SubPieces is null)
63+
return false;
64+
65+
if (SubPieces.Count != other.SubPieces.Count)
66+
return false;
67+
68+
for (int i = 0; i < SubPieces.Count; i++)
69+
{
70+
if (!Equals(SubPieces[i], other.SubPieces[i]))
71+
return false;
72+
}
73+
74+
return true;
75+
}
3276
}
3377
}

DiffPlex/DiffBuilder/SideBySideDiffBuilder.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,28 @@ public SideBySideDiffBuilder(IDiffer differ, char[] wordSeparators) : this(diffe
2828
}
2929

3030
public SideBySideDiffModel BuildDiffModel(string oldText, string newText)
31+
=> BuildDiffModel(oldText, newText, ignoreWhitespace: true);
32+
33+
public SideBySideDiffModel BuildDiffModel(string oldText, string newText, bool ignoreWhitespace)
3134
{
3235
return BuildLineDiff(
3336
oldText ?? throw new ArgumentNullException(nameof(oldText)),
34-
newText ?? throw new ArgumentNullException(nameof(newText)));
37+
newText ?? throw new ArgumentNullException(nameof(newText)),
38+
ignoreWhitespace);
3539
}
3640

37-
private SideBySideDiffModel BuildLineDiff(string oldText, string newText)
41+
private SideBySideDiffModel BuildLineDiff(string oldText, string newText, bool ignoreWhitespace)
3842
{
3943
var model = new SideBySideDiffModel();
40-
var diffResult = differ.CreateLineDiffs(oldText, newText, ignoreWhitespace: true);
44+
var diffResult = differ.CreateLineDiffs(oldText, newText, ignoreWhitespace);
4145
BuildDiffPieces(diffResult, model.OldText.Lines, model.NewText.Lines, BuildWordDiffPieces);
4246
return model;
4347
}
4448

4549
private void BuildWordDiffPieces(string oldText, string newText, List<DiffPiece> oldPieces, List<DiffPiece> newPieces)
4650
{
47-
var diffResult = differ.CreateWordDiffs(oldText, newText, false, WordSeparaters);
48-
BuildDiffPieces(diffResult, oldPieces, newPieces, null);
51+
var diffResult = differ.CreateWordDiffs(oldText, newText, ignoreWhitespace: false, WordSeparaters);
52+
BuildDiffPieces(diffResult, oldPieces, newPieces, subPieceBuilder: null);
4953
}
5054

5155
private static void BuildDiffPieces(DiffResult diffResult, List<DiffPiece> oldPieces, List<DiffPiece> newPieces, PieceBuilder subPieceBuilder)

Facts.DiffPlex/InlineDiffBuilderFacts.cs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,85 @@ public void Will_build_diffModel_for_multiple_diff_blocks()
259259
Assert.Equal(ChangeType.Unchanged, bidiff.Lines[10].Type);
260260
Assert.Equal(8, bidiff.Lines[10].Position);
261261
}
262+
263+
[Fact]
264+
public void Will_ignore_whitespace_by_default_1()
265+
{
266+
string textOld = "1\n 2\n3 \n 4 \n5";
267+
string textNew = "1\n2\n3\n4\n5";
268+
var builder = new InlineDiffBuilder(new Differ());
269+
var model = builder.BuildDiffModel(textOld, textNew);
270+
Assert.Equal(
271+
model.Lines,
272+
new DiffPiece[]
273+
{
274+
new DiffPiece("1", ChangeType.Unchanged, 1),
275+
new DiffPiece("2", ChangeType.Unchanged, 2),
276+
new DiffPiece("3", ChangeType.Unchanged, 3),
277+
new DiffPiece("4", ChangeType.Unchanged, 4),
278+
new DiffPiece("5", ChangeType.Unchanged, 5),
279+
});
280+
}
281+
282+
[Fact]
283+
public void Will_ignore_whitespace_by_default_2()
284+
{
285+
string textOld = "1\n2\n3\n4\n5";
286+
string textNew = "1\n 2\n3 \n 4 \n5";
287+
var builder = new InlineDiffBuilder(new Differ());
288+
var model = builder.BuildDiffModel(textOld, textNew);
289+
Assert.Equal(
290+
model.Lines,
291+
new DiffPiece[]
292+
{
293+
new DiffPiece("1", ChangeType.Unchanged, 1),
294+
new DiffPiece(" 2", ChangeType.Unchanged, 2),
295+
new DiffPiece("3 ", ChangeType.Unchanged, 3),
296+
new DiffPiece(" 4 ", ChangeType.Unchanged, 4),
297+
new DiffPiece("5", ChangeType.Unchanged, 5),
298+
});
299+
}
300+
301+
[Fact]
302+
public void Will_ignore_whitespace_by_default_3()
303+
{
304+
string textOld = "1\n 2\n3 \n 4 \n5";
305+
string textNew = "1\n2\n3\n4\n5";
306+
var builder = new InlineDiffBuilder(new Differ());
307+
var model = builder.BuildDiffModel(textOld, textNew, ignoreWhitespace: true);
308+
Assert.Equal(
309+
model.Lines,
310+
new DiffPiece[]
311+
{
312+
new DiffPiece("1", ChangeType.Unchanged, 1),
313+
new DiffPiece("2", ChangeType.Unchanged, 2),
314+
new DiffPiece("3", ChangeType.Unchanged, 3),
315+
new DiffPiece("4", ChangeType.Unchanged, 4),
316+
new DiffPiece("5", ChangeType.Unchanged, 5),
317+
});
318+
}
319+
320+
[Fact]
321+
public void Can_compare_whitespace()
322+
{
323+
string textOld = "1\n 2\n3 \n 4 \n5";
324+
string textNew = "1\n2\n3\n4\n5";
325+
var builder = new InlineDiffBuilder(new Differ());
326+
var model = builder.BuildDiffModel(textOld, textNew, ignoreWhitespace: false);
327+
Assert.Equal(
328+
model.Lines,
329+
new DiffPiece[]
330+
{
331+
new DiffPiece("1", ChangeType.Unchanged, 1),
332+
new DiffPiece(" 2", ChangeType.Deleted),
333+
new DiffPiece("3 ", ChangeType.Deleted),
334+
new DiffPiece(" 4 ", ChangeType.Deleted),
335+
new DiffPiece("2", ChangeType.Inserted, 2),
336+
new DiffPiece("3", ChangeType.Inserted, 3),
337+
new DiffPiece("4", ChangeType.Inserted, 4),
338+
new DiffPiece("5", ChangeType.Unchanged, 5),
339+
});
340+
}
262341
}
263342
}
264343
}

Facts.DiffPlex/SideBySideDiffBuilderFacts.cs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,170 @@ public void Will_build_diffModel_for_partially_different_lines()
367367
Assert.Equal(ChangeType.Imaginary, bidiff.OldText.Lines[0].SubPieces[3].Type);
368368
Assert.Equal(ChangeType.Unchanged, bidiff.OldText.Lines[0].SubPieces[4].Type);
369369
}
370+
371+
[Fact]
372+
public void Will_ignore_whitespace_by_default_1()
373+
{
374+
string textOld = "1\n 2\n3 \n 4 \n5";
375+
string textNew = "1\n2\n3\n4\n5";
376+
var builder = new SideBySideDiffBuilder(new Differ());
377+
var model = builder.BuildDiffModel(textOld, textNew);
378+
Assert.Equal(
379+
model.OldText.Lines,
380+
new DiffPiece[]
381+
{
382+
new DiffPiece("1", ChangeType.Unchanged, 1),
383+
new DiffPiece(" 2", ChangeType.Unchanged, 2),
384+
new DiffPiece("3 ", ChangeType.Unchanged, 3),
385+
new DiffPiece(" 4 ", ChangeType.Unchanged, 4),
386+
new DiffPiece("5", ChangeType.Unchanged, 5),
387+
});
388+
Assert.Equal(
389+
model.NewText.Lines,
390+
new DiffPiece[]
391+
{
392+
new DiffPiece("1", ChangeType.Unchanged, 1),
393+
new DiffPiece("2", ChangeType.Unchanged, 2),
394+
new DiffPiece("3", ChangeType.Unchanged, 3),
395+
new DiffPiece("4", ChangeType.Unchanged, 4),
396+
new DiffPiece("5", ChangeType.Unchanged, 5),
397+
});
398+
}
399+
400+
[Fact]
401+
public void Will_ignore_whitespace_by_default_2()
402+
{
403+
string textOld = "1\n2\n3\n4\n5";
404+
string textNew = "1\n 2\n3 \n 4 \n5";
405+
var builder = new SideBySideDiffBuilder(new Differ());
406+
var model = builder.BuildDiffModel(textOld, textNew);
407+
Assert.Equal(
408+
model.OldText.Lines,
409+
new DiffPiece[]
410+
{
411+
new DiffPiece("1", ChangeType.Unchanged, 1),
412+
new DiffPiece("2", ChangeType.Unchanged, 2),
413+
new DiffPiece("3", ChangeType.Unchanged, 3),
414+
new DiffPiece("4", ChangeType.Unchanged, 4),
415+
new DiffPiece("5", ChangeType.Unchanged, 5),
416+
});
417+
Assert.Equal(
418+
model.NewText.Lines,
419+
new DiffPiece[]
420+
{
421+
new DiffPiece("1", ChangeType.Unchanged, 1),
422+
new DiffPiece(" 2", ChangeType.Unchanged, 2),
423+
new DiffPiece("3 ", ChangeType.Unchanged, 3),
424+
new DiffPiece(" 4 ", ChangeType.Unchanged, 4),
425+
new DiffPiece("5", ChangeType.Unchanged, 5),
426+
});
427+
}
428+
429+
[Fact]
430+
public void Will_ignore_whitespace_by_default_3()
431+
{
432+
string textOld = "1\n 2\n3 \n 4 \n5";
433+
string textNew = "1\n2\n3\n4\n5";
434+
var builder = new SideBySideDiffBuilder(new Differ());
435+
var model = builder.BuildDiffModel(textOld, textNew, ignoreWhitespace: true);
436+
Assert.Equal(
437+
model.OldText.Lines,
438+
new DiffPiece[]
439+
{
440+
new DiffPiece("1", ChangeType.Unchanged, 1),
441+
new DiffPiece(" 2", ChangeType.Unchanged, 2),
442+
new DiffPiece("3 ", ChangeType.Unchanged, 3),
443+
new DiffPiece(" 4 ", ChangeType.Unchanged, 4),
444+
new DiffPiece("5", ChangeType.Unchanged, 5),
445+
});
446+
Assert.Equal(
447+
model.NewText.Lines,
448+
new DiffPiece[]
449+
{
450+
new DiffPiece("1", ChangeType.Unchanged, 1),
451+
new DiffPiece("2", ChangeType.Unchanged, 2),
452+
new DiffPiece("3", ChangeType.Unchanged, 3),
453+
new DiffPiece("4", ChangeType.Unchanged, 4),
454+
new DiffPiece("5", ChangeType.Unchanged, 5),
455+
});
456+
}
457+
458+
[Fact]
459+
public void Can_compare_whitespace()
460+
{
461+
string textOld = "1\n 2\n3 \n 4 \n5";
462+
string textNew = "1\n2\n3\n4\n5";
463+
var builder = new SideBySideDiffBuilder(new Differ());
464+
var model = builder.BuildDiffModel(textOld, textNew, ignoreWhitespace: false);
465+
Assert.Equal(
466+
model.OldText.Lines,
467+
new DiffPiece[]
468+
{
469+
new DiffPiece("1", ChangeType.Unchanged, 1),
470+
new DiffPiece(" 2", ChangeType.Modified, 2)
471+
{
472+
SubPieces =
473+
{
474+
new DiffPiece("", ChangeType.Deleted, 1),
475+
new DiffPiece(" ", ChangeType.Deleted, 2),
476+
new DiffPiece("2", ChangeType.Unchanged, 3),
477+
},
478+
},
479+
new DiffPiece("3 ", ChangeType.Modified, 3)
480+
{
481+
SubPieces =
482+
{
483+
new DiffPiece("3", ChangeType.Unchanged, 1),
484+
new DiffPiece(" ", ChangeType.Deleted, 2),
485+
},
486+
},
487+
new DiffPiece(" 4 ", ChangeType.Modified, 4)
488+
{
489+
SubPieces =
490+
{
491+
new DiffPiece("", ChangeType.Deleted, 1),
492+
new DiffPiece(" ", ChangeType.Deleted, 2),
493+
new DiffPiece("4", ChangeType.Unchanged, 3),
494+
new DiffPiece(" ", ChangeType.Deleted, 4),
495+
},
496+
},
497+
new DiffPiece("5", ChangeType.Unchanged, 5),
498+
});
499+
Assert.Equal(
500+
model.NewText.Lines,
501+
new DiffPiece[]
502+
{
503+
new DiffPiece("1", ChangeType.Unchanged, 1),
504+
new DiffPiece("2", ChangeType.Modified, 2)
505+
{
506+
SubPieces =
507+
{
508+
new DiffPiece(null, ChangeType.Imaginary),
509+
new DiffPiece(null, ChangeType.Imaginary),
510+
new DiffPiece("2", ChangeType.Unchanged, 1),
511+
},
512+
},
513+
new DiffPiece("3", ChangeType.Modified, 3)
514+
{
515+
SubPieces =
516+
{
517+
new DiffPiece("3", ChangeType.Unchanged, 1),
518+
new DiffPiece(null, ChangeType.Imaginary),
519+
},
520+
},
521+
new DiffPiece("4", ChangeType.Modified, 4)
522+
{
523+
SubPieces =
524+
{
525+
new DiffPiece(null, ChangeType.Imaginary),
526+
new DiffPiece(null, ChangeType.Imaginary),
527+
new DiffPiece("4", ChangeType.Unchanged, 1),
528+
new DiffPiece(null, ChangeType.Imaginary),
529+
},
530+
},
531+
new DiffPiece("5", ChangeType.Unchanged, 5),
532+
});
533+
}
370534
}
371535
}
372536
}

0 commit comments

Comments
 (0)