File: src\ExpressionEvaluator\Core\Source\ResultProvider\Helpers\TypeWalker.cs
Web Access
Project: src\src\ExpressionEvaluator\Core\Source\ResultProvider\Portable\Microsoft.CodeAnalysis.ResultProvider.csproj (Microsoft.CodeAnalysis.ExpressionEvaluator.ResultProvider)
// 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.
 
#nullable disable
 
using System;
using System.Diagnostics;
using Type = Microsoft.VisualStudio.Debugger.Metadata.Type;
 
namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
    internal readonly struct TypeWalker
    {
        private readonly Type _type;
 
        public TypeWalker(Type type)
        {
            _type = type;
        }
 
        public TypeEnumerator GetEnumerator()
        {
            return new TypeEnumerator(_type);
        }
 
        internal struct TypeEnumerator : IDisposable
        {
            private bool _first;
            private ArrayBuilder<Type> _stack;
 
            public TypeEnumerator(Type type)
            {
                _first = true;
                _stack = ArrayBuilder<Type>.GetInstance();
                _stack.Push(type);
            }
 
            public readonly Type Current => _stack.Peek();
 
            public bool MoveNext()
            {
                if (_first)
                {
                    _first = false;
                    return true;
                }
 
                if (_stack.Count == 0)
                {
                    return false;
                }
 
                var curr = _stack.Pop();
 
                if (curr.HasElementType)
                {
                    _stack.Push(curr.GetElementType());
                    return true;
                }
 
                // Push children in reverse order so they get popped in forward order.
                var children = curr.GetGenericArguments();
                var numChildren = children.Length;
                for (int i = numChildren - 1; i >= 0; i--)
                {
                    _stack.Push(children[i]);
                }
 
                return _stack.Count > 0;
            }
 
            public void Reset()
            {
                throw new NotSupportedException();
            }
 
            public void Dispose()
            {
                Debug.Assert(_stack != null);
                _stack.Free();
                _stack = null;
            }
        }
    }
}