/
Edit.cs
118 lines (99 loc) · 3.8 KB
/
Edit.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
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Differencing
{
/// <summary>
/// Represents an edit operation on a tree or a sequence of nodes.
/// </summary>
/// <typeparam name="TNode">Tree node.</typeparam>
[DebuggerDisplay("{GetDebuggerDisplay(), nq}")]
public struct Edit<TNode> : IEquatable<Edit<TNode>>
{
private readonly TreeComparer<TNode> _comparer;
private readonly EditKind _kind;
private readonly TNode _oldNode;
private readonly TNode _newNode;
internal Edit(EditKind kind, TreeComparer<TNode> comparer, TNode oldNode, TNode newNode)
{
Debug.Assert((oldNode == null || oldNode.Equals(default)) == (kind == EditKind.Insert));
Debug.Assert((newNode == null || newNode.Equals(default)) == (kind == EditKind.Delete));
Debug.Assert((oldNode == null || oldNode.Equals(default)) ||
(newNode == null || newNode.Equals(default)) ||
!comparer.TreesEqual(oldNode, newNode));
_comparer = comparer;
_kind = kind;
_oldNode = oldNode;
_newNode = newNode;
}
public EditKind Kind => _kind;
/// <summary>
/// Insert:
/// default(TNode).
///
/// Delete:
/// Deleted node.
///
/// Move, Update:
/// Node in the old tree/sequence.
/// </summary>
public TNode OldNode => _oldNode;
/// <summary>
/// Insert:
/// Inserted node.
///
/// Delete:
/// default(TNode)
///
/// Move, Update:
/// Node in the new tree/sequence.
/// </summary>
public TNode NewNode => _newNode;
public override bool Equals(object obj)
{
return obj is Edit<TNode> && Equals((Edit<TNode>)obj);
}
public bool Equals(Edit<TNode> other)
{
return _kind == other._kind
&& (_oldNode == null) ? other._oldNode == null : _oldNode.Equals(other._oldNode)
&& (_newNode == null) ? other._newNode == null : _newNode.Equals(other._newNode);
}
public override int GetHashCode()
{
var hash = (int)_kind;
if (_oldNode != null)
{
hash = Hash.Combine(_oldNode.GetHashCode(), hash);
}
if (_newNode != null)
{
hash = Hash.Combine(_newNode.GetHashCode(), hash);
}
return hash;
}
// Has to be 'internal' for now as it's used by EnC test tool
internal string GetDebuggerDisplay()
{
var result = Kind.ToString();
switch (Kind)
{
case EditKind.Delete:
return result + " [" + _oldNode.ToString() + "]" + DisplayPosition(_oldNode);
case EditKind.Insert:
return result + " [" + _newNode.ToString() + "]" + DisplayPosition(_newNode);
case EditKind.Update:
return result + " [" + _oldNode.ToString() + "]" + DisplayPosition(_oldNode) + " -> [" + _newNode.ToString() + "]" + DisplayPosition(_newNode);
case EditKind.Move:
case EditKind.Reorder:
return result + " [" + _oldNode.ToString() + "]" + DisplayPosition(_oldNode) + " -> " + DisplayPosition(_newNode);
}
return result;
}
private string DisplayPosition(TNode node)
{
return "@" + _comparer.GetSpan(node).Start;
}
}
}