File: Language\Syntax\InternalSyntax\SyntaxListOfT.cs
Web Access
Project: src\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.
 
#nullable disable
 
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
 
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax;
 
[CollectionBuilder(typeof(SyntaxList), methodName: "Create")]
internal struct SyntaxList<TNode> : IEquatable<SyntaxList<TNode>>
    where TNode : GreenNode
{
    private readonly GreenNode _node;
 
    public SyntaxList(GreenNode node)
    {
        _node = node;
    }
 
    internal GreenNode Node => _node;
 
    public int Count
    {
        get
        {
            return (_node == null) ? 0 : _node.IsList ? _node.SlotCount : 1;
        }
    }
 
    public TNode this[int index]
    {
        get
        {
            if (_node == null)
            {
                return null;
            }
            else if (_node.IsList)
            {
                Debug.Assert(index >= 0);
                Debug.Assert(index <= _node.SlotCount);
 
                return ((TNode)_node.GetSlot(index));
            }
            else if (index == 0)
            {
                return ((TNode)_node);
            }
            else
            {
                throw new InvalidOperationException("This program location is thought to be unreachable.");
            }
        }
    }
 
    public GreenNode ItemUntyped(int index)
    {
        var node = _node;
        if (node.IsList)
        {
            return node.GetSlot(index);
        }
 
        Debug.Assert(index == 0);
        return node;
    }
 
    public bool Any()
    {
        return _node != null;
    }
 
    public bool Any(SyntaxKind kind)
    {
        for (var i = 0; i < Count; i++)
        {
            var element = ItemUntyped(i);
            if ((element.Kind == kind))
            {
                return true;
            }
        }
 
        return false;
    }
 
    public TNode[] Nodes
    {
        get
        {
            var arr = new TNode[Count];
            for (var i = 0; i < Count; i++)
            {
                arr[i] = this[i];
            }
 
            return arr;
        }
    }
 
    public TNode Last
    {
        get
        {
            var node = _node;
            if (node.IsList)
            {
                return ((TNode)node.GetSlot(node.SlotCount - 1));
            }
 
            return ((TNode)node);
        }
    }
 
    public Enumerator GetEnumerator()
    {
        return new Enumerator(this);
    }
 
    public static bool operator ==(SyntaxList<TNode> left, SyntaxList<TNode> right)
    {
        return (left._node == right._node);
    }
 
    public static bool operator !=(SyntaxList<TNode> left, SyntaxList<TNode> right)
    {
        return !(left._node == right._node);
    }
 
    public bool Equals(SyntaxList<TNode> other)
    {
        return _node == other._node;
    }
 
    public override bool Equals(object obj)
    {
        return (obj is SyntaxList<TNode> && (_node == ((SyntaxList<TNode>)obj)._node));
    }
 
    public override int GetHashCode()
    {
        return _node != null ? _node.GetHashCode() : 0;
    }
 
    public static implicit operator SyntaxList<TNode>(TNode node)
    {
        return new SyntaxList<TNode>(node);
    }
 
    public static implicit operator SyntaxList<GreenNode>(SyntaxList<TNode> nodes)
    {
        return new SyntaxList<GreenNode>(nodes._node);
    }
 
    internal struct Enumerator
    {
        private readonly SyntaxList<TNode> _list;
        private int _index;
 
        internal Enumerator(SyntaxList<TNode> list)
        {
            _list = list;
            _index = -1;
        }
 
        public bool MoveNext()
        {
            var newIndex = _index + 1;
            if (newIndex < _list.Count)
            {
                _index = newIndex;
                return true;
            }
 
            return false;
        }
 
        public TNode Current
        {
            get
            {
                return _list[_index];
            }
        }
    }
}