| File: Language\Intermediate\IntermediateNodeWalker.Stack.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.Diagnostics; using System.Diagnostics.CodeAnalysis; namespace Microsoft.AspNetCore.Razor.Language.Intermediate; public abstract partial class IntermediateNodeWalker { /// <summary> /// Simple stack implementation that fills an array from end-to-start /// to keep the items in the reverse order they were pushed. This ensures /// that they are in the correct order to implement the <see cref="Ancestors"/> /// property. /// </summary> private struct Stack { private const int InitialStackSize = 4; private IntermediateNode[]? _stack; private int _stackPointer; [MemberNotNullWhen(false, nameof(_stack))] public readonly bool IsEmpty => _stack is null || _stackPointer == _stack.Length; public readonly ReadOnlySpan<IntermediateNode> Span => IsEmpty ? ReadOnlySpan<IntermediateNode>.Empty : _stack.AsSpan()[_stackPointer..]; public void Push(IntermediateNode node) { if (_stack is null || _stackPointer == 0) { Grow(); } _stack[--_stackPointer] = node; } public void Pop() { Debug.Assert(!IsEmpty); _stack[_stackPointer++] = null!; } [MemberNotNull(nameof(_stack))] private void Grow() { // If we haven't initialized the stack, do so and set the stack pointer. if (_stack == null) { _stack = new IntermediateNode[InitialStackSize]; _stackPointer = _stack.Length; return; } // Otherwise, double the size of the stack and copy the contents over. Debug.Assert(_stackPointer == 0, "We should only grow the ancestor stack when the stack pointer reaches 0."); var length = _stack.Length; var newStack = new IntermediateNode[length * 2]; _stack.CopyTo(newStack, length); _stackPointer = length; _stack = newStack; } } }