Add more information about `foreach` loop to the `IOperation` tree
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
## Background and Motivation
Roslyn's `IOperation` tree provides a solid common denominator for a roslyn AST, both C# and VB, and is handy when writing a language-neutral analyzer. It includes shared primitives like `CommonConversion`, which exposes information relevant to both languages. At the same time there is a `ForEachStatementInfo` primitive available in both C# and VB language layer which isn't exposed in the `IOperation` tree, making it harder to work with for each statements staying language-neutral. I found myself in a situation when I want to get an element type in a `IForEachLoopOperation`, but in order to do that I have to dive into `LoopControlVariable`, handle both declarations and deconstructs and so on. This can be simplified if a shared functionality is exposed on that operation itself.
## Proposed API
```diff
namespace Microsoft.CodeAnalysis.Operations
{
public interface IForEachLoopOperation
{
+ public CommonForEachInfo Info { get; }
}
+ public readonly struct CommonForEachInfo
+ {
+ public IMethodSymbol? GetEnumeratorMethod { get; }
+ public IMethodSymbol? MoveNextMethod { get; }
+ public IPropertySymbol? CurrentProperty { get; }
+ public IMethodSymbol? DisposeMethod { get; }
+ public ITypeSymbol? ElementType { get; }
+ public CommonConversion ElementConversion { get; }
+ public CommonConversion CurrentConversion { get; }
+ }
}
```
## Usage Examples
It sould be too much boilerplate to write a sample analyzer demonstrating usage of the new info struct. I don't think this is strictly necessary.
## Alternative Designs
- I am not sure if `Statement` should be included into the name of a new struct (resulting in `CommonForEachStatementInfo`). In both C# and VB related language-level struct is called `ForEachStatementInfo`, but on the other hand the shared layer should probably stay abstract of specific language syntax constructs. Hence the name in the proposal is just `CommonForEachInfo`
- I am not sure whether `CommonForEachInfo` should implement `IEquatable` or not. On one hand, both language-specific `ForEachStatementInfo`s implement `IEquatable` interface. But on the other hand the same is true for `Conversion` structs yet on a shared layer `CommonConversion` doesn't implement `IEquatable`. Therefore for sake of the API consistency I didn't include `IEquatable` into the proposal
- The `CommonForEachInfo` can be dropped entirely and properties may be added directly to the `IForEachLoopOperation` instead. Existing `IsAsynchronous` property already follows that pattern (is is exposed as a member of `ForEachStatementInfo` on the C# layer)
## Risks
I don't see any. This just exposes aready available language-level info on a shared layer
Contributor guide
Assessment
This issue has not been assessed yet.