-
Notifications
You must be signed in to change notification settings - Fork 4k
/
SemanticEdit.cs
125 lines (110 loc) · 5.22 KB
/
SemanticEdit.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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Symbols;
using Roslyn.Utilities;
using System;
namespace Microsoft.CodeAnalysis.Emit
{
/// <summary>
/// Describes a symbol edit between two compilations.
/// For example, an addition of a method, an update of a method, removal of a type, etc.
/// </summary>
public struct SemanticEdit : IEquatable<SemanticEdit>
{
/// <summary>
/// The type of edit.
/// </summary>
public SemanticEditKind Kind { get; }
/// <summary>
/// The symbol from the earlier compilation,
/// or null if the edit represents an addition.
/// </summary>
public ISymbol? OldSymbol { get; }
/// <summary>
/// The symbol from the later compilation,
/// or null if the edit represents a deletion.
/// </summary>
public ISymbol? NewSymbol { get; }
/// <summary>
/// A map from syntax node in the later compilation to syntax node in the previous compilation,
/// or null if <see cref="PreserveLocalVariables"/> is false and the map is not needed or
/// the source of the current method is the same as the source of the previous method.
/// </summary>
/// <remarks>
/// The map does not need to map all syntax nodes in the active method, only those syntax nodes
/// that declare a local or generate a long lived local.
/// </remarks>
public Func<SyntaxNode, SyntaxNode?>? SyntaxMap { get; }
/// <summary>
/// True if the edit is an update of the active method and local values
/// should be preserved; false otherwise.
/// </summary>
public bool PreserveLocalVariables { get; }
/// <summary>
/// Initializes an instance of <see cref="SemanticEdit"/>.
/// </summary>
/// <param name="kind">The type of edit.</param>
/// <param name="oldSymbol">
/// The symbol from the earlier compilation, or null if the edit represents an addition.
/// </param>
/// <param name="newSymbol">
/// The symbol from the later compilation, or null if the edit represents a deletion.
/// </param>
/// <param name="syntaxMap">
/// A map from syntax node in the later compilation to syntax node in the previous compilation,
/// or null if <paramref name="preserveLocalVariables"/> is false and the map is not needed or
/// the source of the current method is the same as the source of the previous method.
/// </param>
/// <param name="preserveLocalVariables">
/// True if the edit is an update of an active method and local values should be preserved; false otherwise.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="oldSymbol"/> or <paramref name="newSymbol"/> is null and the edit isn't a <see cref="SemanticEditKind.Insert"/> or <see cref="SemanticEditKind.Delete"/>, respectively.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="kind"/> is not a valid kind.
/// </exception>
public SemanticEdit(SemanticEditKind kind, ISymbol? oldSymbol, ISymbol? newSymbol, Func<SyntaxNode, SyntaxNode?>? syntaxMap = null, bool preserveLocalVariables = false)
{
if (oldSymbol == null && kind != SemanticEditKind.Insert)
{
throw new ArgumentNullException(nameof(oldSymbol));
}
if (newSymbol == null && kind != SemanticEditKind.Delete)
{
throw new ArgumentNullException(nameof(newSymbol));
}
if (kind <= SemanticEditKind.None || kind > SemanticEditKind.Delete)
{
throw new ArgumentOutOfRangeException(nameof(kind));
}
this.Kind = kind;
this.OldSymbol = oldSymbol;
this.NewSymbol = newSymbol;
this.PreserveLocalVariables = preserveLocalVariables;
this.SyntaxMap = syntaxMap;
}
internal static SemanticEdit Create(SemanticEditKind kind, ISymbolInternal oldSymbol, ISymbolInternal newSymbol, Func<SyntaxNode, SyntaxNode>? syntaxMap = null, bool preserveLocalVariables = false)
{
return new SemanticEdit(kind, oldSymbol?.GetISymbol(), newSymbol?.GetISymbol(), syntaxMap, preserveLocalVariables);
}
public override int GetHashCode()
{
return Hash.Combine(OldSymbol,
Hash.Combine(NewSymbol,
(int)Kind));
}
public override bool Equals(object? obj)
{
return obj is SemanticEdit && Equals((SemanticEdit)obj);
}
public bool Equals(SemanticEdit other)
{
return this.Kind == other.Kind
&& (this.OldSymbol == null ? other.OldSymbol == null : this.OldSymbol.Equals(other.OldSymbol))
&& (this.NewSymbol == null ? other.NewSymbol == null : this.NewSymbol.Equals(other.NewSymbol));
}
}
}