-
Notifications
You must be signed in to change notification settings - Fork 4k
/
ForEachStatementInfo.cs
113 lines (100 loc) · 4.54 KB
/
ForEachStatementInfo.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
// 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.
using System;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
{
/// <summary>
/// Structure containing all semantic information about a for each statement.
/// </summary>
public readonly struct ForEachStatementInfo : IEquatable<ForEachStatementInfo>
{
/// <summary>
/// Whether this is an asynchronous foreach.
/// </summary>
public bool IsAsynchronous { get; }
/// <summary>
/// Gets the "GetEnumerator" method.
/// </summary>
public IMethodSymbol? GetEnumeratorMethod { get; }
/// <summary>
/// Gets the "MoveNext" method (or "MoveNextAsync" in an asynchronous foreach).
/// </summary>
public IMethodSymbol? MoveNextMethod { get; }
/// <summary>
/// Gets the "Current" property.
/// </summary>
public IPropertySymbol? CurrentProperty { get; }
/// <summary>
/// Gets the "Dispose" method (or "DisposeAsync" in an asynchronous foreach).
/// </summary>
public IMethodSymbol? DisposeMethod { get; }
/// <summary>
/// The intermediate type to which the output of the <see cref="CurrentProperty"/> is converted
/// before being converted to the iteration variable type.
/// </summary>
/// <remarks>
/// As you might hope, for an array, it is the element type of the array.
/// </remarks>
public ITypeSymbol? ElementType { get; }
/// <summary>
/// The conversion from the <see cref="ElementType"/> to the iteration variable type.
/// </summary>
/// <remarks>
/// May be user-defined.
/// </remarks>
public Conversion ElementConversion { get; }
/// <summary>
/// The conversion from the type of the <see cref="CurrentProperty"/> to the <see cref="ElementType"/>.
/// </summary>
public Conversion CurrentConversion { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ForEachStatementInfo" /> structure.
/// </summary>
internal ForEachStatementInfo(bool isAsync,
IMethodSymbol getEnumeratorMethod,
IMethodSymbol moveNextMethod,
IPropertySymbol currentProperty,
IMethodSymbol disposeMethod,
ITypeSymbol elementType,
Conversion elementConversion,
Conversion currentConversion)
{
this.IsAsynchronous = isAsync;
this.GetEnumeratorMethod = getEnumeratorMethod;
this.MoveNextMethod = moveNextMethod;
this.CurrentProperty = currentProperty;
this.DisposeMethod = disposeMethod;
this.ElementType = elementType;
this.ElementConversion = elementConversion;
this.CurrentConversion = currentConversion;
}
public override bool Equals(object? obj)
{
return obj is ForEachStatementInfo && Equals((ForEachStatementInfo)obj);
}
public bool Equals(ForEachStatementInfo other)
{
return this.IsAsynchronous == other.IsAsynchronous
&& object.Equals(this.GetEnumeratorMethod, other.GetEnumeratorMethod)
&& object.Equals(this.MoveNextMethod, other.MoveNextMethod)
&& object.Equals(this.CurrentProperty, other.CurrentProperty)
&& object.Equals(this.DisposeMethod, other.DisposeMethod)
&& object.Equals(this.ElementType, other.ElementType)
&& this.ElementConversion == other.ElementConversion
&& this.CurrentConversion == other.CurrentConversion;
}
public override int GetHashCode()
{
return Hash.Combine(IsAsynchronous,
Hash.Combine(GetEnumeratorMethod,
Hash.Combine(MoveNextMethod,
Hash.Combine(CurrentProperty,
Hash.Combine(DisposeMethod,
Hash.Combine(ElementType,
Hash.Combine(ElementConversion.GetHashCode(),
CurrentConversion.GetHashCode())))))));
}
}
}