| File: Language\Syntax\SyntaxTokenList.Enumerator.cs | Web Access |
| Project: src\roslyn\src\Razor\src\Compiler\Microsoft.CodeAnalysis.Razor.Compiler\src\Microsoft.CodeAnalysis.Razor.Compiler.csproj (Microsoft.CodeAnalysis.Razor.Compiler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; namespace Microsoft.AspNetCore.Razor.Language.Syntax; internal readonly partial struct SyntaxTokenList { public struct Enumerator { // This enumerator allows us to enumerate through two types of lists. // either it looks like: // // Parent // | // List // | \ // c1 c2 // // or // // Parent // | // c1 // // I.e. in the single child case, we optimize and store the child // directly (without any list parent). // // Enumerating over the single child case is simple. We just // return it and we're done. // // In the multi child case, things are a bit more difficult. We need // to return the children in order, while also keeping their offset // correct. private readonly SyntaxNode? _parent; private readonly GreenNode? _singleNodeOrList; private readonly int _baseIndex; private readonly int _count; private int _index; private GreenNode? _current; private int _position; internal Enumerator(in SyntaxTokenList list) { _parent = list._parent; _singleNodeOrList = list.Node; _baseIndex = list._index; _count = list.Count; _index = -1; _current = null; _position = list.Position; } /// <summary> /// Advances the enumerator to the next token in the collection. /// </summary> /// <returns>true if the enumerator was successfully advanced to the next element; false if the enumerator /// has passed the end of the collection.</returns> public bool MoveNext() { if (_count == 0 || _count <= _index + 1) { // invalidate iterator _current = null; return false; } _index++; // Add the length of the previous node to the offset so that // the next node's offset is reported correctly. if (_current != null) { _position += _current.Width; } Debug.Assert(_singleNodeOrList != null); _current = GetGreenNodeAt(_singleNodeOrList, _index); Debug.Assert(_current != null); return true; } /// <summary> /// Gets the current element in the collection. /// </summary> public readonly SyntaxToken Current { get { if (_current == null) { throw new InvalidOperationException(); } // In both the list and the single node case we want to // return the original root parent as the parent of this // token. return new SyntaxToken(_parent, _current, _position, _baseIndex + _index); } } public override readonly bool Equals(object? obj) => throw new NotSupportedException(); public override readonly int GetHashCode() => throw new NotSupportedException(); } private sealed class EnumeratorImpl : IEnumerator<SyntaxToken> { private Enumerator _enumerator; // SyntaxTriviaList is a relatively big struct so is passed by ref internal EnumeratorImpl(in SyntaxTokenList list) { _enumerator = new Enumerator(in list); } public SyntaxToken Current => _enumerator.Current; object IEnumerator.Current => _enumerator.Current; public bool MoveNext() => _enumerator.MoveNext(); public void Reset() => throw new NotSupportedException(); public void Dispose() { } } }