| File: Operations\IOperation.OperationList.Reversed.cs | Web Access |
| Project: src\roslyn\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis) |
// 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 System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis { public partial interface IOperation { public readonly partial struct OperationList { /// <summary> /// Implements a reverse-order struct-based collection of <see cref="Operation"/> nodes. /// This collection is ordered, but random access into the collection is not provided. /// </summary> [NonDefaultable] public readonly struct Reversed : IReadOnlyCollection<IOperation> { private readonly Operation _operation; internal Reversed(Operation operation) { _operation = operation; } public int Count => _operation.ChildOperationsCount; public Enumerator GetEnumerator() => new Enumerator(_operation); public ImmutableArray<IOperation> ToImmutableArray() { Enumerator enumerator = GetEnumerator(); switch (_operation) { case { ChildOperationsCount: 0 }: return ImmutableArray<IOperation>.Empty; case NoneOperation { Children: var children }: return reverseArray(children); case InvalidOperation { Children: var children }: return reverseArray(children); default: var builder = ArrayBuilder<IOperation>.GetInstance(Count); foreach (var child in this) { builder.Add(child); } return builder.ToImmutableAndFree(); } static ImmutableArray<IOperation> reverseArray(ImmutableArray<IOperation> input) { var builder = ArrayBuilder<IOperation>.GetInstance(input.Length); for (int i = input.Length - 1; i >= 0; i--) { builder.Add(input[i]); } return builder.ToImmutableAndFree(); } } IEnumerator<IOperation> IEnumerable<IOperation>.GetEnumerator() { if (this.Count == 0) { return SpecializedCollections.EmptyEnumerator<IOperation>(); } return new EnumeratorImpl(new Enumerator(_operation)); } IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<IOperation>)this).GetEnumerator(); /// <summary> /// Implements a reverse-order struct-based enumerator for <see cref="Operation"/> nodes. This type is not hardened /// to <code>default(Enumerator)</code>, and will null reference in these cases. Calling <see cref="Current"/> after /// <see cref="Enumerator.MoveNext"/> has returned false will throw an <see cref="InvalidOperationException"/>. /// </summary> [NonDefaultable] public struct Enumerator { private readonly Operation _operation; private int _currentSlot; private int _currentIndex; internal Enumerator(Operation operation) { _operation = operation; _currentSlot = int.MaxValue; _currentIndex = int.MaxValue; } public IOperation Current { get { Debug.Assert(_operation != null && _currentSlot is >= 0 and not int.MaxValue && _currentIndex is >= 0 and not int.MaxValue); return _operation.GetCurrent(_currentSlot, _currentIndex); } } public bool MoveNext() { Debug.Assert((_currentSlot == int.MaxValue) == (_currentIndex == int.MaxValue)); (var result, _currentSlot, _currentIndex) = _operation.MoveNextReversed(_currentSlot, _currentIndex); return result; } public void Reset() { _currentIndex = int.MaxValue; _currentSlot = int.MaxValue; } } private sealed class EnumeratorImpl : IEnumerator<IOperation> { private Enumerator _enumerator; public EnumeratorImpl(Enumerator enumerator) { _enumerator = enumerator; } public IOperation Current => _enumerator.Current; object? IEnumerator.Current => _enumerator.Current; public void Dispose() { } public bool MoveNext() => _enumerator.MoveNext(); public void Reset() => _enumerator.Reset(); } } } } }