File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Core\Utilities\PooledBuilderExtensions.cs
Web Access
Project: src\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// 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.
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.PooledObjects;
 
namespace Roslyn.Utilities;
 
internal static class PooledBuilderExtensions
{
    public static Dictionary<K, V> ToDictionaryAndFree<K, V>(this PooledDictionary<K, V> builders)
        where K : notnull
    {
        var dictionary = new Dictionary<K, V>(builders.Count);
 
        foreach (var (key, items) in builders)
        {
            dictionary.Add(key, items);
        }
 
        builders.Free();
        return dictionary;
    }
 
    public static Dictionary<K, ImmutableArray<V>> ToMultiDictionaryAndFree<K, V>(this PooledDictionary<K, ArrayBuilder<V>> builders)
        where K : notnull
    {
        var dictionary = new Dictionary<K, ImmutableArray<V>>(builders.Count);
 
        foreach (var (key, items) in builders)
        {
            dictionary.Add(key, items.ToImmutableAndFree());
        }
 
        builders.Free();
        return dictionary;
    }
 
    public static ImmutableDictionary<K, ImmutableArray<V>> ToImmutableMultiDictionaryAndFree<K, V>(this PooledDictionary<K, ArrayBuilder<V>> builders)
        where K : notnull
    {
        var result = ImmutableDictionary.CreateBuilder<K, ImmutableArray<V>>();
 
        foreach (var (key, items) in builders)
        {
            result.Add(key, items.ToImmutableAndFree());
        }
 
        builders.Free();
        return result.ToImmutable();
    }
 
    public static void FreeValues<K, V>(this IReadOnlyDictionary<K, ArrayBuilder<V>> builders)
        where K : notnull
    {
        foreach (var (_, items) in builders)
        {
            items.Free();
        }
    }
 
    public static ImmutableArray<T> ToFlattenedImmutableArrayAndFree<T>(this ArrayBuilder<ArrayBuilder<T>> builders)
    {
        try
        {
            if (builders.Count == 0)
            {
                return [];
            }
 
            if (builders.Count == 1)
            {
                return builders[0].ToImmutableAndFree();
            }
 
            var result = ArrayBuilder<T>.GetInstance(builders.Sum(b => b.Count));
 
            foreach (var builder in builders)
            {
                result.AddRange(builder);
                builder.Free();
            }
 
            return result.ToImmutableAndFree();
        }
        finally
        {
            builders.Free();
        }
    }
 
    public static bool HasDuplicates<T>(this ArrayBuilder<T> builder)
        => builder.HasDuplicates(static x => x);
 
    public static bool HasDuplicates<T, U>(this ArrayBuilder<T> builder, Func<T, U> selector)
    {
        switch (builder.Count)
        {
            case 0:
            case 1:
                return false;
 
            case 2:
                return EqualityComparer<U>.Default.Equals(selector(builder[0]), selector(builder[1]));
 
            default:
                {
                    using var _ = PooledHashSet<U>.GetInstance(out var set);
 
                    foreach (var element in builder)
                    {
                        if (!set.Add(selector(element)))
                            return true;
                    }
 
                    return false;
                }
        }
    }
}