File: Symbols\ITypeSymbolExtensions.CollectTypeParameterSymbolsVisitor.cs
Web Access
Project: src\src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Extensions\Microsoft.CodeAnalysis.Extensions.Package.csproj (Microsoft.CodeAnalysis.Extensions.Package)
// 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 enable
 
using System;
using Microsoft.CodeAnalysis.PooledObjects;
 
namespace Microsoft.CodeAnalysis.Shared.Extensions;
 
internal static partial class ITypeSymbolExtensions
{
    private sealed class CollectTypeParameterSymbolsVisitor(
        ArrayBuilder<ITypeParameterSymbol> typeParameters,
        bool onlyMethodTypeParameters) : SymbolVisitor, IDisposable
    {
        private readonly PooledHashSet<ISymbol> _visited = PooledHashSet<ISymbol>.GetInstance();
 
        public void Dispose()
        {
            _visited.Free();
        }
 
        public override void DefaultVisit(ISymbol node)
            => throw new NotImplementedException();
 
        public override void VisitDynamicType(IDynamicTypeSymbol symbol)
        {
        }
 
        public override void VisitArrayType(IArrayTypeSymbol symbol)
        {
            if (!_visited.Add(symbol))
            {
                return;
            }
 
            symbol.ElementType.Accept(this);
        }
 
        public override void VisitFunctionPointerType(IFunctionPointerTypeSymbol symbol)
        {
            if (!_visited.Add(symbol))
            {
                return;
            }
 
            foreach (var parameter in symbol.Signature.Parameters)
            {
                parameter.Type.Accept(this);
            }
 
            symbol.Signature.ReturnType.Accept(this);
        }
 
        public override void VisitNamedType(INamedTypeSymbol symbol)
        {
            if (_visited.Add(symbol))
            {
                foreach (var child in symbol.GetAllTypeArguments())
                {
                    child.Accept(this);
                }
            }
        }
 
        public override void VisitPointerType(IPointerTypeSymbol symbol)
        {
            if (!_visited.Add(symbol))
            {
                return;
            }
 
            symbol.PointedAtType.Accept(this);
        }
 
        public override void VisitTypeParameter(ITypeParameterSymbol symbol)
        {
            if (_visited.Add(symbol))
            {
                if (symbol.TypeParameterKind == TypeParameterKind.Method || !onlyMethodTypeParameters)
                {
                    if (!typeParameters.Contains(symbol))
                    {
                        typeParameters.Add(symbol);
                    }
                }
 
                foreach (var constraint in symbol.ConstraintTypes)
                {
                    constraint.Accept(this);
                }
            }
        }
    }
}