File: Language\TagHelperObjectBuilderCollection`2.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.
 
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.Extensions.ObjectPool;
 
namespace Microsoft.AspNetCore.Razor.Language;
 
public sealed partial class TagHelperObjectBuilderCollection<TObject, TBuilder> : IEnumerable<TBuilder>
    where TObject : TagHelperObject<TObject>
    where TBuilder : TagHelperObjectBuilder<TObject>
{
    private readonly ObjectPool<TBuilder> _builderPool;
    private List<TBuilder>? _builders;
 
    internal TagHelperObjectBuilderCollection(ObjectPool<TBuilder> builderPool)
    {
        _builderPool = builderPool;
    }
 
    public int Count
        => _builders?.Count ?? 0;
 
    public TBuilder this[int index]
        => _builders.AssumeNotNull()[index];
 
    public Enumerator GetEnumerator()
        => new(this);
 
    IEnumerator<TBuilder> IEnumerable<TBuilder>.GetEnumerator()
        => GetEnumerator();
 
    IEnumerator IEnumerable.GetEnumerator()
        => GetEnumerator();
 
    internal void Add(TBuilder builder)
    {
        _builders ??= new();
        _builders.Add(builder);
    }
 
    internal void Clear()
    {
        // Ensure that we return all builders to their pool
        if (_builders is { } builders)
        {
            foreach (var builder in builders)
            {
                _builderPool.Return(builder);
            }
 
            builders.Clear();
        }
    }
 
    internal ImmutableArray<TObject> ToImmutable()
    {
        if (_builders is not { Count: > 0 } builders)
        {
            return ImmutableArray<TObject>.Empty;
        }
        else if (builders.Count == 1)
        {
            return [builders[0].Build()];
        }
 
        using var result = new PooledArrayBuilder<TObject>(capacity: builders.Count);
        using var set = new PooledHashSet<TObject>(capacity: builders.Count);
 
        foreach (var builder in builders)
        {
            var item = builder.Build();
 
            if (set.Add(item))
            {
                result.Add(item);
            }
        }
 
        return result.ToImmutableAndClear();
    }
}