// 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. // This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp), // more info in ThirdPartyNotices.txt in the root of the project. using System; using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.CodeAnalysis; namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; /// /// Extension methods for . /// internal static class IncrementalValuesProviderExtensions { /// /// Groups items in a given sequence by a specified key. /// /// The type of left items in each tuple. /// The type of right items in each tuple. /// The input instance. /// A comparer. /// An with the grouped results. public static IncrementalValuesProvider<(TLeft Left, ImmutableArray Right)> GroupBy( this IncrementalValuesProvider<(TLeft Left, TRight Right)> source, IEqualityComparer comparer) { return source.Collect().SelectMany((item, _) => { Dictionary.Builder> map = new(comparer); foreach ((TLeft hierarchy, TRight info) in item) { if (!map.TryGetValue(hierarchy, out ImmutableArray.Builder builder)) { builder = ImmutableArray.CreateBuilder(); map.Add(hierarchy, builder); } builder.Add(info); } ImmutableArray<(TLeft Hierarchy, ImmutableArray Properties)>.Builder result = ImmutableArray.CreateBuilder<(TLeft, ImmutableArray)>(); foreach (KeyValuePair.Builder> entry in map) { result.Add((entry.Key, entry.Value.ToImmutable())); } return result; }); } /// /// Creates a new instance with a given pair of comparers. /// /// The type of left items in each tuple. /// The type of right items in each tuple. /// The input instance. /// An instance for items. /// An instance for items. /// An with the specified comparers applied to each item. public static IncrementalValuesProvider<(TLeft Left, TRight Right)> WithComparers( this IncrementalValuesProvider<(TLeft Left, TRight Right)> source, IEqualityComparer comparerLeft, IEqualityComparer comparerRight) { return source.WithComparer(new Comparer(comparerLeft, comparerRight)); } /// /// Creates a new instance with a given pair of comparers. /// /// The type of first items in each tuple. /// The type of second items in each tuple. /// The type of third items in each tuple. /// The input instance. /// An instance for items. /// An instance for items. /// An instance for items. /// An with the specified comparers applied to each item. public static IncrementalValuesProvider<(T1, T2, T3)> WithComparers( this IncrementalValuesProvider<(T1, T2, T3)> source, IEqualityComparer comparer1, IEqualityComparer comparer2, IEqualityComparer comparer3) { return source.WithComparer(new Comparer(comparer1, comparer2, comparer3)); } /// /// An implementation for a value tuple. /// private sealed class Comparer : IEqualityComparer<(TLeft Left, TRight Right)> { /// /// The comparer. /// private readonly IEqualityComparer comparerLeft; /// /// The comparer. /// private readonly IEqualityComparer comparerRight; /// /// Creates a new instance with the specified parameters. /// /// The comparer. /// The comparer. public Comparer(IEqualityComparer comparerLeft, IEqualityComparer comparerRight) { this.comparerLeft = comparerLeft; this.comparerRight = comparerRight; } /// public bool Equals((TLeft Left, TRight Right) x, (TLeft Left, TRight Right) y) { return this.comparerLeft.Equals(x.Left, y.Left) && this.comparerRight.Equals(x.Right, y.Right); } /// public int GetHashCode((TLeft Left, TRight Right) obj) { return HashCode.Combine( this.comparerLeft.GetHashCode(obj.Left), this.comparerRight.GetHashCode(obj.Right)); } } /// /// An implementation for a value tuple. /// private sealed class Comparer : IEqualityComparer<(T1, T2, T3)> { /// /// The comparer. /// private readonly IEqualityComparer comparer1; /// /// The comparer. /// private readonly IEqualityComparer comparer2; /// /// The comparer. /// private readonly IEqualityComparer comparer3; /// /// Creates a new instance with the specified parameters. /// /// The comparer. /// The comparer. /// The comparer. public Comparer(IEqualityComparer comparer1, IEqualityComparer comparer2, IEqualityComparer comparer3) { this.comparer1 = comparer1; this.comparer2 = comparer2; this.comparer3 = comparer3; } /// public bool Equals((T1, T2, T3) x, (T1, T2, T3) y) { return this.comparer1.Equals(x.Item1, y.Item1) && this.comparer2.Equals(x.Item2, y.Item2) && this.comparer3.Equals(x.Item3, y.Item3); } /// public int GetHashCode((T1, T2, T3) obj) { return HashCode.Combine( this.comparer1.GetHashCode(obj.Item1), this.comparer2.GetHashCode(obj.Item2), this.comparer3.GetHashCode(obj.Item3)); } } }