forked from UbiquityDotNET/Ubiquity.NET.Utils
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStructurallyEquatableTypedConstant.cs
More file actions
113 lines (98 loc) · 5.34 KB
/
StructurallyEquatableTypedConstant.cs
File metadata and controls
113 lines (98 loc) · 5.34 KB
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
// Copyright (c) Ubiquity.NET Contributors. All rights reserved.
// Licensed under the Apache-2.0 WITH LLVM-exception license. See the LICENSE.md file in the project root for full license information.
namespace Ubiquity.NET.CodeAnalysis.Utils
{
/// <summary>Wrapper for <see cref="TypedConstant"/> that implements structural (deep) equality</summary>
/// <remarks>
/// While <see cref="TypedConstant"/> implements <see cref="IEquatable{T}"/> it does so with a shallow
/// depth if <see cref="TypedConstant.Kind"/> indicates an array. Use of this, type expresses intent
/// to use structural equality (deep) semantics. It is intentionally designed where the size is the
/// same as it is just functionality that is different.
/// </remarks>
public readonly struct StructurallyEquatableTypedConstant
: IEquatable<StructurallyEquatableTypedConstant>
{
/// <summary>Initializes a new instance of the <see cref="StructurallyEquatableTypedConstant"/> struct.</summary>
/// <param name="other"><see cref="TypedConstant"/> to wrap</param>
public StructurallyEquatableTypedConstant(TypedConstant other)
{
InnerConst = other;
}
/// <inheritdoc cref="TypedConstant.Kind"/>
public TypedConstantKind Kind => InnerConst.Kind;
/// <inheritdoc cref="TypedConstant.Type"/>
public ITypeSymbol? Type => InnerConst.Type;
/// <inheritdoc cref="TypedConstant.IsNull"/>
public bool IsNull => InnerConst.IsNull;
/// <inheritdoc cref="TypedConstant.Value"/>
public object? Value => InnerConst.Value;
/// <summary>Gets the value for a <see cref="StructurallyEquatableTypedConstant"/> array.</summary>
/// <value>
/// <see langword="default" /> <c>ImmutableArray</c> if <see langword="null"/> was passed as the array value;
/// <see cref="IsNull"/> can be used to check for this.
/// </value>
public ImmutableArray<StructurallyEquatableTypedConstant> Values => [ .. InnerConst.Values.Select(e=> new StructurallyEquatableTypedConstant(e)) ];
/// <summary>Test if this instance is structurally equal to <paramref name="other"/></summary>
/// <param name="other">Comparand</param>
/// <returns>true if instance is structurally equal to <paramref name="other"/>; false if not</returns>
public bool Equals( StructurallyEquatableTypedConstant other )
{
return StructuralTypedConstantComparer.Default.Equals(InnerConst, other.InnerConst);
}
/// <summary>Test if this instance is structurally equal to <paramref name="obj"/></summary>
/// <param name="obj">Comparand</param>
/// <returns>
/// true if obj is <see cref="StructurallyEquatableTypedConstant"/> and this instance is structurally equal to <paramref name="obj"/>; false if not.
/// </returns>
public override bool Equals( object obj )
{
return obj is StructurallyEquatableTypedConstant other
&& Equals( other );
}
/// <inheritdoc/>
public override int GetHashCode( )
{
return StructuralTypedConstantComparer.Default.GetHashCode(InnerConst);
}
/// <summary>Test two instances for equality</summary>
/// <param name="left">Left side of the comparison</param>
/// <param name="right">Right side of the comparison</param>
/// <returns>True if the values are equal and false if not</returns>
public static bool operator ==( StructurallyEquatableTypedConstant left, StructurallyEquatableTypedConstant right )
{
return left.Equals(right);
}
/// <summary>Test two instances for inequality</summary>
/// <param name="left">Left side of the comparison</param>
/// <param name="right">Right side of the comparison</param>
/// <returns>False if the values are not equal and true if not</returns>
public static bool operator !=( StructurallyEquatableTypedConstant left, StructurallyEquatableTypedConstant right )
{
return !(left == right);
}
/// <summary>Gets the wrapped <see cref="TypedConstant"/></summary>
/// <returns>The inner <see cref="TypedConstant"/></returns>
/// <remarks>
/// This is useful for getting access to extension methods for <see cref="TypedConstant"/>
/// that are otherwise unrelated to equality.
/// </remarks>
public TypedConstant ToTypedConstant()
{
return InnerConst;
}
private readonly TypedConstant InnerConst;
/// <summary>Implicit cast from <see cref="TypedConstant"/></summary>
/// <param name="other">Constant to cast</param>
[SuppressMessage( "Usage", "CA2225:Operator overloads have named alternates", Justification = "Simple alternate for existing constructor" )]
public static implicit operator StructurallyEquatableTypedConstant( TypedConstant other )
{
return new( other );
}
/// <summary>Implicit cast from <see cref="StructurallyEquatableTypedConstant"/></summary>
/// <param name="other">Constant to cast</param>
public static explicit operator TypedConstant( StructurallyEquatableTypedConstant other )
{
return other.ToTypedConstant();
}
}
}