File: Binder\ExtensionMethodScope.cs
Web Access
Project: src\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp)
// 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
 
namespace Microsoft.CodeAnalysis.CSharp
{
    /// <summary>
    /// A distinct scope that may expose extension methods. For a particular Binder,  there
    /// are two possible scopes: one for the namespace, and another for any using statements
    /// in the namespace. The namespace scope is searched before the using scope.
    /// </summary>
    internal readonly struct ExtensionMethodScope
    {
        public readonly Binder Binder;
 
        public ExtensionMethodScope(Binder binder)
        {
            this.Binder = binder;
        }
    }
 
    /// <summary>
    /// An enumerable collection of extension method scopes in search
    /// order, from the given Binder, out through containing Binders.
    /// </summary>
    internal readonly struct ExtensionMethodScopes
    {
        private readonly Binder _binder;
 
        public ExtensionMethodScopes(Binder binder)
        {
            _binder = binder;
        }
 
        public ExtensionMethodScopeEnumerator GetEnumerator()
        {
            return new ExtensionMethodScopeEnumerator(_binder);
        }
    }
 
    /// <summary>
    /// An enumerator over ExtensionMethodScopes.
    /// </summary>
    internal struct ExtensionMethodScopeEnumerator
    {
        private readonly Binder _binder;
        private ExtensionMethodScope _current;
 
        public ExtensionMethodScopeEnumerator(Binder binder)
        {
            _binder = binder;
            _current = new ExtensionMethodScope();
        }
 
        public ExtensionMethodScope Current
        {
            get { return _current; }
        }
 
        public bool MoveNext()
        {
            if (_current.Binder == null)
            {
                _current = GetNextScope(_binder);
            }
            else
            {
                var binder = _current.Binder;
                // Return a scope for the next Binder that supports extension methods.
                _current = GetNextScope(binder.Next);
            }
 
            return (_current.Binder != null);
        }
 
        private static ExtensionMethodScope GetNextScope(Binder binder)
        {
            for (var scope = binder; scope != null; scope = scope.Next)
            {
                if (scope.SupportsExtensionMethods)
                {
                    return new ExtensionMethodScope(scope);
                }
            }
 
            return new ExtensionMethodScope();
        }
    }
}