File: src\RoslynAnalyzers\Utilities\FlowAnalysis\Extensions\ListExtensions.cs
Web Access
Project: src\src\RoslynAnalyzers\Microsoft.CodeAnalysis.AnalyzerUtilities\Microsoft.CodeAnalysis.AnalyzerUtilities.csproj (Microsoft.CodeAnalysis.AnalyzerUtilities)
// 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;
 
namespace Analyzer.Utilities.Extensions
{
    internal static class ListExtensions
    {
        /// <summary>
        /// Extract and remove all elements from <paramref name="list"/> which are matched by
        /// <paramref name="predicate"/>.
        /// </summary>
        /// <typeparam name="T">The type of element in the list.</typeparam>
        /// <typeparam name="TArg">A state argument to pass to <paramref name="predicate"/>.</typeparam>
        /// <param name="list">The list.</param>
        /// <param name="predicate">A predicate matching elements to remove from <paramref name="list"/>.</param>
        /// <param name="argument">An additional state argument to pass to <paramref name="predicate"/>.</param>
        /// <returns>A collection of elements removed from <paramref name="list"/>, in the order they were removed. If
        /// no elements were removed, this method returns <see cref="ImmutableArray{T}.Empty"/>.</returns>
        public static ImmutableArray<T> ExtractAll<T, TArg>(this List<T> list, Func<T, TArg, bool> predicate, TArg argument)
        {
            ImmutableArray<T>.Builder? builder = null;
            for (int i = 0; i < list.Count; i++)
            {
                var value = list[i];
                if (predicate(value, argument))
                {
                    builder ??= ImmutableArray.CreateBuilder<T>();
                    builder.Add(value);
                }
                else if (builder is not null)
                {
                    list[i - builder.Count] = value;
                }
            }
 
            if (builder is null)
            {
                return ImmutableArray<T>.Empty;
            }
 
            list.RemoveRange(list.Count - builder.Count, builder.Count);
            return builder.Capacity == builder.Count ? builder.MoveToImmutable() : builder.ToImmutable();
        }
    }
}