From 4cd90ceb9116adea17c5f0db48d423a3f0aa4d1c Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Sat, 22 May 2021 10:49:47 +0200 Subject: [PATCH 01/11] Add reference to System.Collections.Immutable NuGet package for down-level support --- Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj | 1 + .../refs/System.Linq.Async.Ref/System.Linq.Async.Ref.csproj | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj b/Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj index 1bfe13cbef..09d7dd28b6 100644 --- a/Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj +++ b/Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj @@ -27,6 +27,7 @@ + diff --git a/Ix.NET/Source/refs/System.Linq.Async.Ref/System.Linq.Async.Ref.csproj b/Ix.NET/Source/refs/System.Linq.Async.Ref/System.Linq.Async.Ref.csproj index ead9cd3018..0d355fff3c 100644 --- a/Ix.NET/Source/refs/System.Linq.Async.Ref/System.Linq.Async.Ref.csproj +++ b/Ix.NET/Source/refs/System.Linq.Async.Ref/System.Linq.Async.Ref.csproj @@ -16,6 +16,8 @@ ExtrasIsReferenceAssembly;AssemblyName;Version;AssemblyTitle + From efccb6335352c42a7c5c878c0e0e28c270092bc9 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Sat, 22 May 2021 11:16:24 +0200 Subject: [PATCH 02/11] Implement ToImmutableDictionaryAsync --- .../Linq/Operators/ToImmutableDictionary.cs | 112 ++++++++ .../System/Linq/FunctionalHelpers.cs | 23 ++ .../Linq/Operators/ToImmutableDictionary.cs | 267 ++++++++++++++++++ 3 files changed, 402 insertions(+) create mode 100644 Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableDictionary.cs create mode 100644 Ix.NET/Source/System.Linq.Async/System/Linq/FunctionalHelpers.cs create mode 100644 Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableDictionary.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableDictionary.cs new file mode 100644 index 0000000000..e4ad40b40d --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableDictionary.cs @@ -0,0 +1,112 @@ +// 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.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Tests +{ + public class ToImmutableDictionary : AsyncEnumerableTests + { + [Fact] + public async Task ToImmutableDictionary_Null() + { + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default(Func)).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, EqualityComparer.Default).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, EqualityComparer.Default).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, x => 0).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, x => 0).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, x => 0, default).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, x => 0, EqualityComparer.Default).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, x => 0, EqualityComparer.Default).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, x => 0, default, EqualityComparer.Default).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default(Func), CancellationToken.None).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, EqualityComparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, EqualityComparer.Default, CancellationToken.None).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, x => 0, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, x => 0, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, x => 0, default, CancellationToken.None).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, x => 0, EqualityComparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, x => 0, EqualityComparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, x => 0, default, EqualityComparer.Default, CancellationToken.None).AsTask()); + } + + [Fact] + public async Task ToImmutableDictionary1Async() + { + var xs = new[] { 1, 4 }.ToAsyncEnumerable(); + var res = await xs.ToImmutableDictionaryAsync(x => x % 2); + Assert.True(res[0] == 4); + Assert.True(res[1] == 1); + } + + [Fact] + public async Task ToImmutableDictionary2Async() + { + var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable(); + await AssertThrowsAsync(xs.ToImmutableDictionaryAsync(x => x % 2).AsTask()); + } + + [Fact] + public async Task ToImmutableDictionary3Async() + { + var xs = new[] { 1, 4 }.ToAsyncEnumerable(); + var res = await xs.ToImmutableDictionaryAsync(x => x % 2, x => x + 1); + Assert.True(res[0] == 5); + Assert.True(res[1] == 2); + } + + [Fact] + public async Task ToImmutableDictionary4Async() + { + var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable(); + await AssertThrowsAsync(xs.ToImmutableDictionaryAsync(x => x % 2, x => x + 1).AsTask()); + } + + [Fact] + public async Task ToImmutableDictionary5Async() + { + var xs = new[] { 1, 4 }.ToAsyncEnumerable(); + var res = await xs.ToImmutableDictionaryAsync(x => x % 2, new Eq()); + Assert.True(res[0] == 4); + Assert.True(res[1] == 1); + } + + [Fact] + public async Task ToImmutableDictionary6Async() + { + var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable(); + await AssertThrowsAsync(xs.ToImmutableDictionaryAsync(x => x % 2, new Eq()).AsTask()); + } + + [Fact] + public async Task ToImmutableDictionary7Async() + { + var xs = new[] { 1, 4 }.ToAsyncEnumerable(); + var res = await xs.ToImmutableDictionaryAsync(x => x % 2, x => x, new Eq()); + Assert.True(res[0] == 4); + Assert.True(res[1] == 1); + } + + private sealed class Eq : IEqualityComparer + { + public bool Equals(int x, int y) => EqualityComparer.Default.Equals(Math.Abs(x), Math.Abs(y)); + + public int GetHashCode(int obj) => EqualityComparer.Default.GetHashCode(Math.Abs(obj)); + } + } +} diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/FunctionalHelpers.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/FunctionalHelpers.cs new file mode 100644 index 0000000000..f88e9ca9b2 --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/FunctionalHelpers.cs @@ -0,0 +1,23 @@ +// 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.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Linq.Async.System.Linq +{ + internal static class FunctionalHelpers + { + public static T Identity(T value) => value; + + public static ValueTask IdentityAsync(T value) => new(value); + + public static ValueTask IdentityAsync(T value, CancellationToken token) => new(value); + + public static TKey Key(KeyValuePair kvp) => kvp.Key; + + public static TValue Value(KeyValuePair kvp) => kvp.Value; + } +} diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs new file mode 100644 index 0000000000..e2fed0282c --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs @@ -0,0 +1,267 @@ +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; +using static System.Linq.Async.System.Linq.FunctionalHelpers; + +namespace System.Linq +{ + public static partial class AsyncEnumerable + { + /// + /// Creates an immutable dictionary from an async-enumerable sequence according to a specified key selector function. + /// + /// The type of the elements in the source sequence. + /// The type of the dictionary key computed for each element in the source sequence. + /// An async-enumerable sequence to create a dictionary for. + /// A function to extract a key from each element. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// or is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableDictionaryAsync(this IAsyncEnumerable source, Func keySelector, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAsync(keySelector, elementSelector: Identity, keyComparer: null, valueComparer: null, cancellationToken); + + /// + /// Creates an immutable dictionary from an async-enumerable sequence according to a specified key selector function, and an element selector function. + /// + /// The type of the elements in the source sequence. + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// An async-enumerable sequence to create a dictionary for. + /// A function to extract a key from each element. + /// A transform function to produce a result element value from each element. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// , , or is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableDictionaryAsync(this IAsyncEnumerable source, Func keySelector, Func elementSelector, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAsync(keySelector, elementSelector, keyComparer: null, valueComparer: null, cancellationToken); + + /// + /// Creates an immutable dictionary from an async-enumerable sequence according to a specified key selector function, and a key equality comparer. + /// + /// The type of the elements in the source sequence. + /// The type of the dictionary key computed for each element in the source sequence. + /// An async-enumerable sequence to create a dictionary for. + /// A function to extract a key from each element. + /// An equality comparer to compare keys. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// or is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableDictionaryAsync(this IAsyncEnumerable source, Func keySelector, IEqualityComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAsync(keySelector, elementSelector: Identity, keyComparer, valueComparer: null, cancellationToken); + + /// + /// Creates an immutable dictionary from an async-enumerable sequence according to a specified key selector function, an element selector function, and a key equality comparer. + /// + /// The type of the elements in the source sequence. + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// An async-enumerable sequence to create a dictionary for. + /// A function to extract a key from each element. + /// A transform function to produce a result element value from each element. + /// An equality comparer to compare keys. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// , , or is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableDictionaryAsync(this IAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAsync(keySelector, elementSelector, keyComparer, valueComparer: null, cancellationToken); + + /// + /// Creates an immutable dictionary from an async-enumerable sequence of key/value pairs. + /// + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// An async-enumerable sequence to create a dictionary for. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableDictionaryAsync(this IAsyncEnumerable> source, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAsync(keySelector: Key, elementSelector: Value, keyComparer: null, valueComparer: null, cancellationToken); + + /// + /// Creates an immutable dictionary from an async-enumerable sequence of key/value pairs according to a specified key equality comparer. + /// + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// An equality comparer to compare keys. + /// An async-enumerable sequence to create a dictionary for. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableDictionaryAsync(this IAsyncEnumerable> source, IEqualityComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAsync(keySelector: Key, elementSelector: Value, keyComparer, valueComparer: null, cancellationToken); + + /// + /// Creates an immutable dictionary from an async-enumerable sequence of key/value pairs according to a specified key equality comparer and a value equality comparer. + /// + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// An equality comparer to compare keys. + /// An equality comparer to compare values. + /// An async-enumerable sequence to create a dictionary for. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableDictionaryAsync(this IAsyncEnumerable> source, IEqualityComparer? keyComparer, IEqualityComparer? valueComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAsync(keySelector: Key, elementSelector: Value, keyComparer, valueComparer, cancellationToken); + + /// + /// Creates an immutable dictionary from an async-enumerable sequence according to a specified key selector function, an element selector function, a key equality comparer and a value equality comparer. + /// + /// The type of the elements in the source sequence. + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// An async-enumerable sequence to create a dictionary for. + /// A function to extract a key from each element. + /// A transform function to produce a result element value from each element. + /// An equality comparer to compare keys. + /// An equality comparer to compare values. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// , , or is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableDictionaryAsync( + this IAsyncEnumerable source, + Func keySelector, Func elementSelector, + IEqualityComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + where TKey : notnull + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (keySelector == null) + throw Error.ArgumentNull(nameof(keySelector)); + if (elementSelector == null) + throw Error.ArgumentNull(nameof(elementSelector)); + + return Core(source, keySelector, elementSelector, keyComparer, valueComparer, cancellationToken); + + static async ValueTask> Core( + IAsyncEnumerable source, + Func keySelector, Func elementSelector, + IEqualityComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + { + var builder = ImmutableDictionary.CreateBuilder(keyComparer, valueComparer); + + await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) + { + builder.Add(keySelector(item), elementSelector(item)); + } + + return builder.ToImmutable(); + } + } + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableDictionaryAwaitAsyncCore(this IAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAwaitAsyncCore(keySelector, elementSelector: IdentityAsync, keyComparer: null, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableDictionaryAwaitAsyncCore(this IAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAwaitAsyncCore(keySelector, elementSelector, keyComparer: null, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableDictionaryAwaitAsyncCore(this IAsyncEnumerable source, Func> keySelector, IEqualityComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAwaitAsyncCore(keySelector, elementSelector: IdentityAsync, keyComparer, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableDictionaryAwaitAsyncCore(this IAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAwaitAsyncCore(keySelector, elementSelector, keyComparer, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableDictionaryAwaitAsyncCore( + this IAsyncEnumerable source, + Func> keySelector, Func> elementSelector, + IEqualityComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + where TKey : notnull + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (keySelector == null) + throw Error.ArgumentNull(nameof(keySelector)); + if (elementSelector == null) + throw Error.ArgumentNull(nameof(elementSelector)); + + return Core(source, keySelector, elementSelector, keyComparer, valueComparer, cancellationToken); + + static async ValueTask> Core( + IAsyncEnumerable source, + Func> keySelector, Func> elementSelector, + IEqualityComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + { + var builder = ImmutableDictionary.CreateBuilder(keyComparer, valueComparer); + + await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) + { + builder.Add(await keySelector(item).ConfigureAwait(false), await elementSelector(item).ConfigureAwait(false)); + } + + return builder.ToImmutable(); + } + } + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableDictionaryAwaitWithCancellationAsyncCore(this IAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAwaitWithCancellationAsyncCore(keySelector, elementSelector: IdentityAsync, keyComparer: null, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableDictionaryAwaitWithCancellationAsyncCore(this IAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAwaitWithCancellationAsyncCore(keySelector, elementSelector, keyComparer: null, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableDictionaryAwaitWithCancellationAsyncCore(this IAsyncEnumerable source, Func> keySelector, IEqualityComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAwaitWithCancellationAsyncCore(keySelector, elementSelector: IdentityAsync, keyComparer, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableDictionaryAwaitWithCancellationAsyncCore(this IAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableDictionaryAwaitWithCancellationAsyncCore(keySelector, elementSelector, keyComparer, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableDictionaryAwaitWithCancellationAsyncCore( + this IAsyncEnumerable source, + Func> keySelector, Func> elementSelector, + IEqualityComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + where TKey : notnull + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (keySelector == null) + throw Error.ArgumentNull(nameof(keySelector)); + if (elementSelector == null) + throw Error.ArgumentNull(nameof(elementSelector)); + + return Core(source, keySelector, elementSelector, keyComparer, valueComparer, cancellationToken); + + static async ValueTask> Core( + IAsyncEnumerable source, + Func> keySelector, Func> elementSelector, + IEqualityComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + { + var builder = ImmutableDictionary.CreateBuilder(keyComparer, valueComparer); + + await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) + { + builder.Add(await keySelector(item, cancellationToken).ConfigureAwait(false), await elementSelector(item, cancellationToken).ConfigureAwait(false)); + } + + return builder.ToImmutable(); + } + } + } +} From 840dcd8df2e63c6fada611c0d06557e61354d266 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Sun, 23 May 2021 22:39:00 +0200 Subject: [PATCH 03/11] Implement ToImmutableHashSetAsync --- .../Linq/Operators/ToImmutableHashSet.cs | 48 ++++++++++++++++ .../Linq/Operators/ToImmutableHashSet.cs | 56 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableHashSet.cs create mode 100644 Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableHashSet.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableHashSet.cs new file mode 100644 index 0000000000..6875df62cf --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableHashSet.cs @@ -0,0 +1,48 @@ +// 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.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Tests +{ + public class ToImmutableHashSet : AsyncEnumerableTests + { + [Fact] + public async Task ToImmutableHashSet_Null() + { + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableHashSetAsync(default).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableHashSetAsync(default, CancellationToken.None).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableHashSetAsync(default, EqualityComparer.Default, CancellationToken.None).AsTask()); + } + + [Fact] + public async Task ToImmutableHashSet_Simple() + { + var xs = new[] { 1, 2, 1, 2, 3, 4, 1, 2, 3, 4 }; + var res = xs.ToAsyncEnumerable().ToImmutableHashSetAsync(); + Assert.True((await res).OrderBy(x => x).SequenceEqual(new[] { 1, 2, 3, 4 })); + } + + [Fact] + public async Task ToImmutableHashSet_Comparer() + { + var xs = new[] { 1, 12, 11, 2, 3, 14, 1, 12, 13, 4 }; + var res = xs.ToAsyncEnumerable().ToImmutableHashSetAsync(new Eq()); + Assert.True((await res).OrderBy(x => x).SequenceEqual(new[] { 1, 3, 12, 14 })); + } + + private class Eq : IEqualityComparer + { + public bool Equals(int x, int y) => x % 10 == y % 10; + + public int GetHashCode(int obj) => obj % 10; + } + } +} diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs new file mode 100644 index 0000000000..18751a69c8 --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs @@ -0,0 +1,56 @@ +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Linq +{ + public static partial class AsyncEnumerable + { + /// + /// Creates an immutable hash set from an async-enumerable sequence. + /// + /// The type of the elements in the source sequence. + /// The source async-enumerable sequence to get a hash set of elements for. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a hash set containing all the elements of the source sequence. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableHashSetAsync(this IAsyncEnumerable source, CancellationToken cancellationToken = default) + => ToImmutableHashSetAsync(source, equalityComparer: null, cancellationToken); + + /// + /// Creates an immutable hash set from an async-enumerable sequence according to a specified equality comparer. + /// + /// The type of the elements in the source sequence. + /// The source async-enumerable sequence to get a hash set of elements for. + /// An equality comparer to compare elements of the sequence. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a hash set containing all the elements of the source sequence. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableHashSetAsync(this IAsyncEnumerable source, IEqualityComparer? equalityComparer, CancellationToken cancellationToken = default) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + + return Core(source, equalityComparer, cancellationToken); + + static async ValueTask> Core(IAsyncEnumerable source, IEqualityComparer? equalityComparer, CancellationToken cancellationToken) + { + var builder = ImmutableHashSet.CreateBuilder(equalityComparer); + + await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) + { + builder.Add(item); + } + + return builder.ToImmutable(); + } + } + } +} From 7b5585905a962b1fa3be49a6d2a229fe15751fad Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Mon, 24 May 2021 12:17:36 +0200 Subject: [PATCH 04/11] Implement ToImmutableSortedDictionaryAsync --- .../Operators/ToImmutableSortedDictionary.cs | 106 +++++++++ .../Operators/ToImmutableSortedDictionary.cs | 222 ++++++++++++++++++ 2 files changed, 328 insertions(+) create mode 100644 Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedDictionary.cs create mode 100644 Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedDictionary.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedDictionary.cs new file mode 100644 index 0000000000..d3c3f683d4 --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedDictionary.cs @@ -0,0 +1,106 @@ +// 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.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Tests +{ + public class ToImmutableSortedDictionary : AsyncEnumerableTests + { + [Fact] + public async Task ToImmutableSortedDictionary_Null() + { + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, default, x => 0).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, x => 0, default).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0, Comparer.Default).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, default, x => 0, Comparer.Default).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, x => 0, default, Comparer.Default).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, default, x => 0, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, x => 0, default, CancellationToken.None).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0, Comparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, default, x => 0, Comparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, x => 0, default, Comparer.Default, CancellationToken.None).AsTask()); + } + + [Fact] + public async Task ToImmutableSortedDictionary1Async() + { + var xs = new[] { 1, 4 }.ToAsyncEnumerable(); + var res = await xs.ToImmutableSortedDictionaryAsync(x => x % 2, x => x); + Assert.True(res[0] == 4); + Assert.True(res[1] == 1); + } + + [Fact] + public async Task ToImmutableSortedDictionary2Async() + { + var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable(); + await AssertThrowsAsync(xs.ToImmutableSortedDictionaryAsync(x => x % 2, x => x).AsTask()); + } + + [Fact] + public async Task ToImmutableSortedDictionary3Async() + { + var xs = new[] { 1, 4 }.ToAsyncEnumerable(); + var res = await xs.ToImmutableSortedDictionaryAsync(x => x % 2, x => x + 1); + Assert.True(res[0] == 5); + Assert.True(res[1] == 2); + } + + [Fact] + public async Task ToImmutableSortedDictionary4Async() + { + var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable(); + await AssertThrowsAsync(xs.ToImmutableSortedDictionaryAsync(x => x % 2, x => x + 1).AsTask()); + } + + [Fact] + public async Task ToImmutableSortedDictionary5Async() + { + var xs = new[] { 1, 4 }.ToAsyncEnumerable(); + var res = await xs.ToImmutableSortedDictionaryAsync(x => x % 2, x => x, new Eq()); + Assert.True(res[0] == 4); + Assert.True(res[1] == 1); + } + + [Fact] + public async Task ToImmutableSortedDictionary6Async() + { + var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable(); + await AssertThrowsAsync(xs.ToImmutableSortedDictionaryAsync(x => x % 2, x => x, new Eq()).AsTask()); + } + + [Fact] + public async Task ToImmutableSortedDictionary7Async() + { + var xs = new[] { 1, 4 }.ToAsyncEnumerable(); + var res = await xs.ToImmutableSortedDictionaryAsync(x => x % 2, x => x, new Eq()); + Assert.True(res[0] == 4); + Assert.True(res[1] == 1); + } + + [Fact] + public async Task ToImmutableSortedDictionary8Async() + { + var xs = new[] { 5, 8, 7, 1, 9 }.ToAsyncEnumerable(); + var res = await xs.ToImmutableSortedDictionaryAsync(x => x, x => x); + Assert.Equal(new[] { 1, 5, 7, 8, 9 }, res.Keys); + } + + private sealed class Eq : IComparer + { + public int Compare(int x, int y) => Comparer.Default.Compare(Math.Abs(x), Math.Abs(y)); + } + } +} diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs new file mode 100644 index 0000000000..61a0bc4346 --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs @@ -0,0 +1,222 @@ +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; +using static System.Linq.Async.System.Linq.FunctionalHelpers; + +namespace System.Linq +{ + public static partial class AsyncEnumerable + { + /// + /// Creates an immutable sorted dictionary from an async-enumerable sequence according to a specified key selector function, and an element selector function. + /// + /// The type of the elements in the source sequence. + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// An async-enumerable sequence to create a dictionary for. + /// A function to extract a key from each element. + /// A transform function to produce a result element value from each element. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// , , or is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableSortedDictionaryAsync(this IAsyncEnumerable source, Func keySelector, Func elementSelector, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableSortedDictionaryAsync(keySelector, elementSelector, keyComparer: null, valueComparer: null, cancellationToken); + + /// + /// Creates an immutable sorted dictionary from an async-enumerable sequence according to a specified key selector function, an element selector function, and a key comparer. + /// + /// The type of the elements in the source sequence. + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// An async-enumerable sequence to create a dictionary for. + /// A function to extract a key from each element. + /// A transform function to produce a result element value from each element. + /// A comparer to compare keys. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// , , or is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableSortedDictionaryAsync(this IAsyncEnumerable source, Func keySelector, Func elementSelector, IComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableSortedDictionaryAsync(keySelector, elementSelector, keyComparer, valueComparer: null, cancellationToken); + + /// + /// Creates an immutable sorted dictionary from an async-enumerable sequence of key/value pairs. + /// + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// An async-enumerable sequence to create a dictionary for. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableSortedDictionaryAsync(this IAsyncEnumerable> source, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableSortedDictionaryAsync(keySelector: Key, elementSelector: Value, keyComparer: null, valueComparer: null, cancellationToken); + + /// + /// Creates an immutable sorted dictionary from an async-enumerable sequence of key/value pairs according to a specified key comparer. + /// + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// A comparer to compare keys. + /// An async-enumerable sequence to create a dictionary for. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableSortedDictionaryAsync(this IAsyncEnumerable> source, IComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableSortedDictionaryAsync(keySelector: Key, elementSelector: Value, keyComparer, valueComparer: null, cancellationToken); + + /// + /// Creates an immutable sorted dictionary from an async-enumerable sequence of key/value pairs according to a specified key comparer and a value equality comparer. + /// + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// A comparer to compare keys. + /// An equality comparer to compare values. + /// An async-enumerable sequence to create a dictionary for. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableSortedDictionaryAsync(this IAsyncEnumerable> source, IComparer? keyComparer, IEqualityComparer? valueComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableSortedDictionaryAsync(keySelector: Key, elementSelector: Value, keyComparer, valueComparer, cancellationToken); + + /// + /// Creates an sorted immutable dictionary from an async-enumerable sequence according to a specified key selector function, an element selector function, a key comparer and a value equality comparer. + /// + /// The type of the elements in the source sequence. + /// The type of the dictionary key computed for each element in the source sequence. + /// The type of the dictionary value computed for each element in the source sequence. + /// An async-enumerable sequence to create a dictionary for. + /// A function to extract a key from each element. + /// A transform function to produce a result element value from each element. + /// A comparer to compare keys. + /// An equality comparer to compare values. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a dictionary mapping unique key values onto the corresponding source sequence's element. + /// , , or is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableSortedDictionaryAsync( + this IAsyncEnumerable source, + Func keySelector, Func elementSelector, + IComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + where TKey : notnull + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (keySelector == null) + throw Error.ArgumentNull(nameof(keySelector)); + if (elementSelector == null) + throw Error.ArgumentNull(nameof(elementSelector)); + + return Core(source, keySelector, elementSelector, keyComparer, valueComparer, cancellationToken); + + static async ValueTask> Core( + IAsyncEnumerable source, + Func keySelector, Func elementSelector, + IComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + { + var builder = ImmutableSortedDictionary.CreateBuilder(keyComparer, valueComparer); + + await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) + { + builder.Add(keySelector(item), elementSelector(item)); + } + + return builder.ToImmutable(); + } + } + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableSortedDictionaryAwaitAsyncCore(this IAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableSortedDictionaryAwaitAsyncCore(keySelector, elementSelector, keyComparer: null, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableSortedDictionaryAwaitAsyncCore(this IAsyncEnumerable source, Func> keySelector, Func> elementSelector, IComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableSortedDictionaryAwaitAsyncCore(keySelector, elementSelector, keyComparer, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableSortedDictionaryAwaitAsyncCore( + this IAsyncEnumerable source, + Func> keySelector, Func> elementSelector, + IComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + where TKey : notnull + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (keySelector == null) + throw Error.ArgumentNull(nameof(keySelector)); + if (elementSelector == null) + throw Error.ArgumentNull(nameof(elementSelector)); + + return Core(source, keySelector, elementSelector, keyComparer, valueComparer, cancellationToken); + + static async ValueTask> Core( + IAsyncEnumerable source, + Func> keySelector, Func> elementSelector, + IComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + { + var builder = ImmutableSortedDictionary.CreateBuilder(keyComparer, valueComparer); + + await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) + { + builder.Add(await keySelector(item).ConfigureAwait(false), await elementSelector(item).ConfigureAwait(false)); + } + + return builder.ToImmutable(); + } + } + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableSortedDictionaryAwaitWithCancellationAsyncCore(this IAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableSortedDictionaryAwaitWithCancellationAsyncCore(keySelector, elementSelector, keyComparer: null, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableSortedDictionaryAwaitWithCancellationAsyncCore(this IAsyncEnumerable source, Func> keySelector, Func> elementSelector, IComparer? keyComparer, CancellationToken cancellationToken = default) where TKey : notnull + => source.ToImmutableSortedDictionaryAwaitWithCancellationAsyncCore(keySelector, elementSelector, keyComparer, valueComparer: null, cancellationToken); + + [GenerateAsyncOverload] + private static ValueTask> ToImmutableSortedDictionaryAwaitWithCancellationAsyncCore( + this IAsyncEnumerable source, + Func> keySelector, Func> elementSelector, + IComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + where TKey : notnull + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (keySelector == null) + throw Error.ArgumentNull(nameof(keySelector)); + if (elementSelector == null) + throw Error.ArgumentNull(nameof(elementSelector)); + + return Core(source, keySelector, elementSelector, keyComparer, valueComparer, cancellationToken); + + static async ValueTask> Core( + IAsyncEnumerable source, + Func> keySelector, Func> elementSelector, + IComparer? keyComparer, IEqualityComparer? valueComparer, + CancellationToken cancellationToken = default) + { + var builder = ImmutableSortedDictionary.CreateBuilder(keyComparer, valueComparer); + + await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) + { + builder.Add(await keySelector(item, cancellationToken).ConfigureAwait(false), await elementSelector(item, cancellationToken).ConfigureAwait(false)); + } + + return builder.ToImmutable(); + } + } + } +} From 7729f5660f38e7b40f8704b0b69f7d9b5a67b225 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Mon, 24 May 2021 13:34:32 +0200 Subject: [PATCH 05/11] Implement ToImmutableArrayAsync --- .../System/Linq/Operators/ToImmutableArray.cs | 83 +++++++++++++++++++ .../System/Linq/Operators/ToImmutableArray.cs | 35 ++++++++ 2 files changed, 118 insertions(+) create mode 100644 Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableArray.cs create mode 100644 Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableArray.cs diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableArray.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableArray.cs new file mode 100644 index 0000000000..3f967b6752 --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableArray.cs @@ -0,0 +1,83 @@ +// 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.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Tests +{ + public class ToImmutableArray : AsyncEnumerableTests + { + [Fact] + public async Task ToImmutableArray_Null() + { + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableArrayAsync(default).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableArrayAsync(default, CancellationToken.None).AsTask()); + } + + [Fact] + public async Task ToImmutableArray_IAsyncIListProvider_Simple() + { + var xs = new[] { 42, 25, 39 }; + var res = xs.ToAsyncEnumerable().ToImmutableArrayAsync(); + Assert.True((await res).SequenceEqual(xs)); + } + + [Fact] + public async Task ToImmutableArray_IAsyncIListProvider_Empty1() + { + var xs = new int[0]; + var res = xs.ToAsyncEnumerable().ToImmutableArrayAsync(); + Assert.True((await res).SequenceEqual(xs)); + } + + [Fact] + public async Task ToImmutableArray_IAsyncIListProvider_Empty2() + { + var xs = new HashSet(); + var res = xs.ToAsyncEnumerable().ToImmutableArrayAsync(); + Assert.True((await res).SequenceEqual(xs)); + } + + [Fact] + public async Task ToImmutableArray_Empty() + { + var xs = AsyncEnumerable.Empty(); + var res = xs.ToImmutableArrayAsync(); + Assert.True((await res).Length == 0); + } + + [Fact] + public async Task ToImmutableArray_Throw() + { + var ex = new Exception("Bang!"); + var res = Throw(ex).ToImmutableArrayAsync(); + await AssertThrowsAsync(res, ex); + } + + [Fact] + public async Task ToImmutableArray_Query() + { + var xs = await AsyncEnumerable.Range(5, 50).Take(10).ToImmutableArrayAsync(); + var ex = new[] { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; + + Assert.True(ex.SequenceEqual(xs)); + } + + [Fact] + public async Task ToImmutableArray_Set() + { + var res = new[] { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; + var xs = new HashSet(res); + + var arr = await xs.ToAsyncEnumerable().ToImmutableArrayAsync(); + + Assert.True(res.SequenceEqual(arr)); + } + } +} diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableArray.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableArray.cs new file mode 100644 index 0000000000..fee7901073 --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableArray.cs @@ -0,0 +1,35 @@ +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Linq +{ + public static partial class AsyncEnumerable + { + /// + /// Creates an immutable array from an async-enumerable sequence. + /// + /// The type of the elements in the source sequence. + /// The source async-enumerable sequence to get an array of elements for. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with an array containing all the elements of the source sequence. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableArrayAsync( + this IAsyncEnumerable source, CancellationToken cancellationToken = default) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + + return Core(source, cancellationToken); + + static async ValueTask> Core(IAsyncEnumerable source, CancellationToken cancellationToken) + => ImmutableArray.Create(await source.ToArrayAsync(cancellationToken).ConfigureAwait(false)); + } + } +} From a41be9b02433aa749b94b5bc21cfd5baf09686e1 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Mon, 24 May 2021 13:38:39 +0200 Subject: [PATCH 06/11] Implement ToImmutableListAsync --- .../System/Linq/Operators/ToImmutableList.cs | 46 +++++++++++++++++++ .../System/Linq/Operators/ToImmutableList.cs | 43 +++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableList.cs create mode 100644 Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableList.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableList.cs new file mode 100644 index 0000000000..0ae688521c --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableList.cs @@ -0,0 +1,46 @@ +// 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.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Tests +{ + public class ToImmutableList : AsyncEnumerableTests + { + [Fact] + public async Task ToImmutableList_Null() + { + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableListAsync(default).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableListAsync(default, CancellationToken.None).AsTask()); + } + + [Fact] + public async Task ToImmutableList_Simple() + { + var xs = new[] { 42, 25, 39 }; + var res = xs.ToAsyncEnumerable().ToImmutableListAsync(); + Assert.True((await res).SequenceEqual(xs)); + } + + [Fact] + public async Task ToImmutableList_Empty() + { + var xs = AsyncEnumerable.Empty(); + var res = xs.ToImmutableListAsync(); + Assert.True((await res).Count == 0); + } + + [Fact] + public async Task ToImmutableList_Throw() + { + var ex = new Exception("Bang!"); + var res = Throw(ex).ToImmutableListAsync(); + await AssertThrowsAsync(res, ex); + } + } +} diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs new file mode 100644 index 0000000000..24a63a4bb6 --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs @@ -0,0 +1,43 @@ +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Linq +{ + public static partial class AsyncEnumerable + { + /// + /// Creates an immutable list from an async-enumerable sequence. + /// + /// The type of the elements in the source sequence. + /// The source async-enumerable sequence to get a list of elements for. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a list containing all the elements of the source sequence. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableListAsync(this IAsyncEnumerable source, CancellationToken cancellationToken = default) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + + return Core(source, cancellationToken); + + static async ValueTask> Core(IAsyncEnumerable source, CancellationToken cancellationToken = default) + { + var builder = ImmutableList.CreateBuilder(); + + await foreach (var item in source.WithCancellation(cancellationToken)) + { + builder.Add(item); + } + + return builder.ToImmutable(); + } + } + } +} From 2ba267f2753e761b25ba2dafb9cb4bf35749f736 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Mon, 24 May 2021 13:45:35 +0200 Subject: [PATCH 07/11] Implement ToImmutableSortedSet --- .../Linq/Operators/ToImmutableSortedSet.cs | 54 ++++++++++++++++++ .../Linq/Operators/ToImmutableSortedSet.cs | 56 +++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedSet.cs create mode 100644 Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedSet.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedSet.cs new file mode 100644 index 0000000000..8eba536292 --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedSet.cs @@ -0,0 +1,54 @@ +// 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.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Tests +{ + public class ToImmutableSortedSet : AsyncEnumerableTests + { + [Fact] + public async Task ToImmutableSortedSet_Null() + { + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedSetAsync(default).AsTask()); + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedSetAsync(default, CancellationToken.None).AsTask()); + + await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedSetAsync(default, Comparer.Default, CancellationToken.None).AsTask()); + } + + [Fact] + public async Task ToImmutableSortedSet_Simple() + { + var xs = new[] { 1, 2, 1, 2, 3, 4, 1, 2, 3, 4 }; + var res = xs.ToAsyncEnumerable().ToImmutableSortedSetAsync(); + Assert.Equal(new[] { 1, 2, 3, 4 }, await res); + } + + [Fact] + public async Task ToImmutableSortedSet_Comparer() + { + var xs = new[] { 1, 12, 11, 2, 3, 14, 1, 12, 13, 4 }; + var res = xs.ToAsyncEnumerable().ToImmutableSortedSetAsync(new Eq()); + Assert.Equal(new[] { 1, 12, 3, 14 }, await res); + } + + [Fact] + public async Task ToImmutableSortedSet_Sorted() + { + var xs = new[] { 5, 8, 7, 1, 9 }.ToAsyncEnumerable(); + var res = await xs.ToImmutableSortedSetAsync(); + Assert.Equal(new[] { 1, 5, 7, 8, 9 }, res); + } + + private sealed class Eq : IComparer + { + public int Compare(int x, int y) => Comparer.Default.Compare(x % 10, y % 10); + } + } +} diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs new file mode 100644 index 0000000000..70c38ccd7d --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs @@ -0,0 +1,56 @@ +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Linq +{ + public static partial class AsyncEnumerable + { + /// + /// Creates an immutable sorted set from an async-enumerable sequence. + /// + /// The type of the elements in the source sequence. + /// The source async-enumerable sequence to get a hash set of elements for. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a sorted set containing all the elements of the source sequence. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableSortedSetAsync(this IAsyncEnumerable source, CancellationToken cancellationToken = default) + => ToImmutableSortedSetAsync(source, comparer: null, cancellationToken); + + /// + /// Creates an immutable sorted set from an async-enumerable sequence according to a specified comparer. + /// + /// The type of the elements in the source sequence. + /// The source async-enumerable sequence to get a hash set of elements for. + /// A comparer to compare elements of the sequence. + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// An async-enumerable sequence containing a single element with a hash set containing all the elements of the source sequence. + /// is null. + /// The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior. + public static ValueTask> ToImmutableSortedSetAsync(this IAsyncEnumerable source, IComparer? comparer, CancellationToken cancellationToken = default) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + + return Core(source, comparer, cancellationToken); + + static async ValueTask> Core(IAsyncEnumerable source, IComparer? comparer, CancellationToken cancellationToken) + { + var builder = ImmutableSortedSet.CreateBuilder(comparer); + + await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) + { + builder.Add(item); + } + + return builder.ToImmutable(); + } + } + } +} From 0f70dc609595667cd4cf7179bd46ab914f4a1935 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Mon, 24 May 2021 14:22:42 +0200 Subject: [PATCH 08/11] Create helper method for building collections --- .../System/Linq/Operators/ToHashSet.cs | 18 +++++------------- .../Linq/Operators/ToImmutableHashSet.cs | 17 ++++------------- .../System/Linq/Operators/ToImmutableList.cs | 17 ++++------------- .../Linq/Operators/ToImmutableSortedSet.cs | 17 ++++------------- .../System/Linq/Operators/ToList.cs | 15 ++------------- .../System/Linq/Operators/Utilities.cs | 15 +++++++++++++++ 6 files changed, 34 insertions(+), 65 deletions(-) diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToHashSet.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToHashSet.cs index 2bf7c487f8..22214f2db8 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToHashSet.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToHashSet.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using static System.Linq.Async.System.Linq.FunctionalHelpers; namespace System.Linq { @@ -37,19 +38,10 @@ public static ValueTask> ToHashSetAsync(this IAsyncEnu if (source == null) throw Error.ArgumentNull(nameof(source)); - return Core(source, comparer, cancellationToken); - - static async ValueTask> Core(IAsyncEnumerable source, IEqualityComparer? comparer, CancellationToken cancellationToken) - { - var set = new HashSet(comparer); - - await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) - { - set.Add(item); - } - - return set; - } + return source.ToCollection( + new HashSet(comparer), + Identity, + cancellationToken); } } } diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs index 18751a69c8..186eaf6682 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs @@ -38,19 +38,10 @@ public static ValueTask> ToImmutableHashSetAsync> Core(IAsyncEnumerable source, IEqualityComparer? equalityComparer, CancellationToken cancellationToken) - { - var builder = ImmutableHashSet.CreateBuilder(equalityComparer); - - await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) - { - builder.Add(item); - } - - return builder.ToImmutable(); - } + return source.ToCollection( + ImmutableHashSet.CreateBuilder(equalityComparer), + static builder => builder.ToImmutable(), + cancellationToken); } } } diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs index 24a63a4bb6..4c390e16fc 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs @@ -25,19 +25,10 @@ public static ValueTask> ToImmutableListAsync(th if (source == null) throw Error.ArgumentNull(nameof(source)); - return Core(source, cancellationToken); - - static async ValueTask> Core(IAsyncEnumerable source, CancellationToken cancellationToken = default) - { - var builder = ImmutableList.CreateBuilder(); - - await foreach (var item in source.WithCancellation(cancellationToken)) - { - builder.Add(item); - } - - return builder.ToImmutable(); - } + return source.ToCollection( + ImmutableList.CreateBuilder(), + static builder => builder.ToImmutable(), + cancellationToken); } } } diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs index 70c38ccd7d..bdbd501af1 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs @@ -38,19 +38,10 @@ public static ValueTask> ToImmutableSortedSetAsync> Core(IAsyncEnumerable source, IComparer? comparer, CancellationToken cancellationToken) - { - var builder = ImmutableSortedSet.CreateBuilder(comparer); - - await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) - { - builder.Add(item); - } - - return builder.ToImmutable(); - } + return source.ToCollection( + ImmutableSortedSet.CreateBuilder(comparer), + static builder => builder.ToImmutable(), + cancellationToken); } } } diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs index 6c50505d40..b4bd6d84ac 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using static System.Linq.Async.System.Linq.FunctionalHelpers; namespace System.Linq { @@ -27,19 +28,7 @@ public static ValueTask> ToListAsync(this IAsyncEnumerabl if (source is IAsyncIListProvider listProvider) return listProvider.ToListAsync(cancellationToken); - return Core(source, cancellationToken); - - static async ValueTask> Core(IAsyncEnumerable source, CancellationToken cancellationToken) - { - var list = new List(); - - await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) - { - list.Add(item); - } - - return list; - } + return source.ToCollection(new List(), Identity, cancellationToken); } } } diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Utilities.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Utilities.cs index a0073f1cbf..d2b1bda514 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Utilities.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Utilities.cs @@ -43,5 +43,20 @@ public static async ValueTask AddRangeAsync(this List list, IAsyncEnumerab list.Add(item); } } + + public static async ValueTask ToCollection( + this IAsyncEnumerable source, + TCollection collection, + Func resultSelector, + CancellationToken cancellationToken) + where TCollection : ICollection + { + await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) + { + collection.Add(item); + } + + return resultSelector(collection); + } } } From e70ecb9455f7522189500c8f8623aede6d972e31 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Wed, 26 May 2021 19:41:27 +0200 Subject: [PATCH 09/11] Clean up namespace for functional helpers --- .../Source/System.Linq.Async/System/Linq/FunctionalHelpers.cs | 2 +- .../Source/System.Linq.Async/System/Linq/Operators/ToHashSet.cs | 2 +- .../System/Linq/Operators/ToImmutableDictionary.cs | 2 +- .../System/Linq/Operators/ToImmutableSortedDictionary.cs | 2 +- Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/FunctionalHelpers.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/FunctionalHelpers.cs index f88e9ca9b2..b080ab532e 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/FunctionalHelpers.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/FunctionalHelpers.cs @@ -6,7 +6,7 @@ using System.Threading; using System.Threading.Tasks; -namespace System.Linq.Async.System.Linq +namespace System.Linq { internal static class FunctionalHelpers { diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToHashSet.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToHashSet.cs index 22214f2db8..7590daf8f7 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToHashSet.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToHashSet.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using static System.Linq.Async.System.Linq.FunctionalHelpers; +using static System.Linq.FunctionalHelpers; namespace System.Linq { diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs index e2fed0282c..2ff744f2f5 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs @@ -6,7 +6,7 @@ using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; -using static System.Linq.Async.System.Linq.FunctionalHelpers; +using static System.Linq.FunctionalHelpers; namespace System.Linq { diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs index 61a0bc4346..3501e828f0 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs @@ -6,7 +6,7 @@ using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; -using static System.Linq.Async.System.Linq.FunctionalHelpers; +using static System.Linq.FunctionalHelpers; namespace System.Linq { diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs index b4bd6d84ac..51ef03a36c 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using static System.Linq.Async.System.Linq.FunctionalHelpers; +using static System.Linq.FunctionalHelpers; namespace System.Linq { From 9f3466d4eb44f3220590a31633377509e2deb6df Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Wed, 1 Sep 2021 20:09:43 +0200 Subject: [PATCH 10/11] Move operators for immutable collections to System.Collections.Immutable namespace --- .../Immutable}/ToImmutableArray.cs | 5 ++- .../Immutable}/ToImmutableDictionary.cs | 41 ++++++++++--------- .../Immutable}/ToImmutableHashSet.cs | 7 ++-- .../Immutable}/ToImmutableList.cs | 5 ++- .../Immutable}/ToImmutableSortedDictionary.cs | 25 +++++------ .../Immutable}/ToImmutableSortedSet.cs | 7 ++-- .../Immutable}/Operators/ToImmutableArray.cs | 6 +-- .../Operators/ToImmutableDictionary.cs | 6 +-- .../Operators/ToImmutableHashSet.cs | 6 +-- .../Immutable}/Operators/ToImmutableList.cs | 6 +-- .../Operators/ToImmutableSortedDictionary.cs | 6 +-- .../Operators/ToImmutableSortedSet.cs | 6 +-- 12 files changed, 66 insertions(+), 60 deletions(-) rename Ix.NET/Source/System.Linq.Async.Tests/System/{Linq/Operators => Collections/Immutable}/ToImmutableArray.cs (91%) rename Ix.NET/Source/System.Linq.Async.Tests/System/{Linq/Operators => Collections/Immutable}/ToImmutableDictionary.cs (58%) rename Ix.NET/Source/System.Linq.Async.Tests/System/{Linq/Operators => Collections/Immutable}/ToImmutableHashSet.cs (79%) rename Ix.NET/Source/System.Linq.Async.Tests/System/{Linq/Operators => Collections/Immutable}/ToImmutableList.cs (85%) rename Ix.NET/Source/System.Linq.Async.Tests/System/{Linq/Operators => Collections/Immutable}/ToImmutableSortedDictionary.cs (66%) rename Ix.NET/Source/System.Linq.Async.Tests/System/{Linq/Operators => Collections/Immutable}/ToImmutableSortedSet.cs (81%) rename Ix.NET/Source/System.Linq.Async/System/{Linq => Collections/Immutable}/Operators/ToImmutableArray.cs (93%) rename Ix.NET/Source/System.Linq.Async/System/{Linq => Collections/Immutable}/Operators/ToImmutableDictionary.cs (99%) rename Ix.NET/Source/System.Linq.Async/System/{Linq => Collections/Immutable}/Operators/ToImmutableHashSet.cs (96%) rename Ix.NET/Source/System.Linq.Async/System/{Linq => Collections/Immutable}/Operators/ToImmutableList.cs (93%) rename Ix.NET/Source/System.Linq.Async/System/{Linq => Collections/Immutable}/Operators/ToImmutableSortedDictionary.cs (99%) rename Ix.NET/Source/System.Linq.Async/System/{Linq => Collections/Immutable}/Operators/ToImmutableSortedSet.cs (95%) diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableArray.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableArray.cs similarity index 91% rename from Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableArray.cs rename to Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableArray.cs index 3f967b6752..8c0c9606a5 100644 --- a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableArray.cs +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableArray.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -16,8 +17,8 @@ public class ToImmutableArray : AsyncEnumerableTests [Fact] public async Task ToImmutableArray_Null() { - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableArrayAsync(default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableArrayAsync(default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableArrayAsyncEnumerableExtensions.ToImmutableArrayAsync(default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableArrayAsyncEnumerableExtensions.ToImmutableArrayAsync(default, CancellationToken.None).AsTask()); } [Fact] diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableDictionary.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableDictionary.cs similarity index 58% rename from Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableDictionary.cs rename to Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableDictionary.cs index e4ad40b40d..2ca697a579 100644 --- a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableDictionary.cs +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableDictionary.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -16,33 +17,33 @@ public class ToImmutableDictionary : AsyncEnumerableTests [Fact] public async Task ToImmutableDictionary_Null() { - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default(Func)).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(default, x => 0).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, default(Func)).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, EqualityComparer.Default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, EqualityComparer.Default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(default, x => 0, EqualityComparer.Default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, default, EqualityComparer.Default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, x => 0).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, x => 0).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, x => 0, default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(default, x => 0, x => 0).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, default, x => 0).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, x => 0, default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, x => 0, EqualityComparer.Default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, x => 0, EqualityComparer.Default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, x => 0, default, EqualityComparer.Default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(default, x => 0, x => 0, EqualityComparer.Default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, default, x => 0, EqualityComparer.Default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, x => 0, default, EqualityComparer.Default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default(Func), CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(default, x => 0, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, default(Func), CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, EqualityComparer.Default, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, EqualityComparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(default, x => 0, EqualityComparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, default, EqualityComparer.Default, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, x => 0, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, x => 0, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, x => 0, default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(default, x => 0, x => 0, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, default, x => 0, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, x => 0, default, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(default, x => 0, x => 0, EqualityComparer.Default, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, default, x => 0, EqualityComparer.Default, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableDictionaryAsync(Return42, x => 0, default, EqualityComparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(default, x => 0, x => 0, EqualityComparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, default, x => 0, EqualityComparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableDictionaryAsyncEnumerableExtensions.ToImmutableDictionaryAsync(Return42, x => 0, default, EqualityComparer.Default, CancellationToken.None).AsTask()); } [Fact] diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableHashSet.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableHashSet.cs similarity index 79% rename from Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableHashSet.cs rename to Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableHashSet.cs index 6875df62cf..c56e256076 100644 --- a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableHashSet.cs +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableHashSet.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -16,10 +17,10 @@ public class ToImmutableHashSet : AsyncEnumerableTests [Fact] public async Task ToImmutableHashSet_Null() { - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableHashSetAsync(default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableHashSetAsync(default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableHashSetAsyncEnumerableExtensions.ToImmutableHashSetAsync(default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableHashSetAsyncEnumerableExtensions.ToImmutableHashSetAsync(default, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableHashSetAsync(default, EqualityComparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableHashSetAsyncEnumerableExtensions.ToImmutableHashSetAsync(default, EqualityComparer.Default, CancellationToken.None).AsTask()); } [Fact] diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableList.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableList.cs similarity index 85% rename from Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableList.cs rename to Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableList.cs index 0ae688521c..d3e5e7bfdf 100644 --- a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableList.cs +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableList.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -15,8 +16,8 @@ public class ToImmutableList : AsyncEnumerableTests [Fact] public async Task ToImmutableList_Null() { - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableListAsync(default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableListAsync(default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableListAsyncEnumerableExtensions.ToImmutableListAsync(default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableListAsyncEnumerableExtensions.ToImmutableListAsync(default, CancellationToken.None).AsTask()); } [Fact] diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedDictionary.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableSortedDictionary.cs similarity index 66% rename from Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedDictionary.cs rename to Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableSortedDictionary.cs index d3c3f683d4..d9ae5938f4 100644 --- a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedDictionary.cs +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableSortedDictionary.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -16,21 +17,21 @@ public class ToImmutableSortedDictionary : AsyncEnumerableTests [Fact] public async Task ToImmutableSortedDictionary_Null() { - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, default, x => 0).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, x => 0, default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(Return42, default, x => 0).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(Return42, x => 0, default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0, Comparer.Default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, default, x => 0, Comparer.Default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, x => 0, default, Comparer.Default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0, Comparer.Default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(Return42, default, x => 0, Comparer.Default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(Return42, x => 0, default, Comparer.Default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, default, x => 0, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, x => 0, default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(Return42, default, x => 0, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(Return42, x => 0, default, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0, Comparer.Default, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, default, x => 0, Comparer.Default, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedDictionaryAsync(Return42, x => 0, default, Comparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(default, x => 0, x => 0, Comparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(Return42, default, x => 0, Comparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedDictionaryAsyncEnumerableExtensions.ToImmutableSortedDictionaryAsync(Return42, x => 0, default, Comparer.Default, CancellationToken.None).AsTask()); } [Fact] diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedSet.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableSortedSet.cs similarity index 81% rename from Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedSet.cs rename to Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableSortedSet.cs index 8eba536292..7915484590 100644 --- a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToImmutableSortedSet.cs +++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Collections/Immutable/ToImmutableSortedSet.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -16,10 +17,10 @@ public class ToImmutableSortedSet : AsyncEnumerableTests [Fact] public async Task ToImmutableSortedSet_Null() { - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedSetAsync(default).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedSetAsync(default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedSetAsyncEnumerableExtensions.ToImmutableSortedSetAsync(default).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedSetAsyncEnumerableExtensions.ToImmutableSortedSetAsync(default, CancellationToken.None).AsTask()); - await Assert.ThrowsAsync(() => AsyncEnumerable.ToImmutableSortedSetAsync(default, Comparer.Default, CancellationToken.None).AsTask()); + await Assert.ThrowsAsync(() => ImmutableSortedSetAsyncEnumerableExtensions.ToImmutableSortedSetAsync(default, Comparer.Default, CancellationToken.None).AsTask()); } [Fact] diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableArray.cs b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableArray.cs similarity index 93% rename from Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableArray.cs rename to Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableArray.cs index fee7901073..7869a67739 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableArray.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableArray.cs @@ -3,13 +3,13 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace System.Linq +namespace System.Collections.Immutable { - public static partial class AsyncEnumerable + public static class ImmutableArrayAsyncEnumerableExtensions { /// /// Creates an immutable array from an async-enumerable sequence. diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableDictionary.cs similarity index 99% rename from Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs rename to Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableDictionary.cs index 2ff744f2f5..b7ef01964c 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableDictionary.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableDictionary.cs @@ -3,14 +3,14 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using System.Threading; using System.Threading.Tasks; using static System.Linq.FunctionalHelpers; -namespace System.Linq +namespace System.Collections.Immutable { - public static partial class AsyncEnumerable + public static class ImmutableDictionaryAsyncEnumerableExtensions { /// /// Creates an immutable dictionary from an async-enumerable sequence according to a specified key selector function. diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableHashSet.cs similarity index 96% rename from Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs rename to Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableHashSet.cs index 186eaf6682..6858d65ac4 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableHashSet.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableHashSet.cs @@ -3,13 +3,13 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace System.Linq +namespace System.Collections.Immutable { - public static partial class AsyncEnumerable + public static class ImmutableHashSetAsyncEnumerableExtensions { /// /// Creates an immutable hash set from an async-enumerable sequence. diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableList.cs similarity index 93% rename from Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs rename to Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableList.cs index 4c390e16fc..919090e1e1 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableList.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableList.cs @@ -3,13 +3,13 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace System.Linq +namespace System.Collections.Immutable { - public static partial class AsyncEnumerable + public static class ImmutableListAsyncEnumerableExtensions { /// /// Creates an immutable list from an async-enumerable sequence. diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableSortedDictionary.cs similarity index 99% rename from Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs rename to Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableSortedDictionary.cs index 3501e828f0..627737d72c 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedDictionary.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableSortedDictionary.cs @@ -3,14 +3,14 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using System.Threading; using System.Threading.Tasks; using static System.Linq.FunctionalHelpers; -namespace System.Linq +namespace System.Collections.Immutable { - public static partial class AsyncEnumerable + public static class ImmutableSortedDictionaryAsyncEnumerableExtensions { /// /// Creates an immutable sorted dictionary from an async-enumerable sequence according to a specified key selector function, and an element selector function. diff --git a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableSortedSet.cs similarity index 95% rename from Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs rename to Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableSortedSet.cs index bdbd501af1..61f2536cde 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToImmutableSortedSet.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableSortedSet.cs @@ -3,13 +3,13 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace System.Linq +namespace System.Collections.Immutable { - public static partial class AsyncEnumerable + public static class ImmutableSortedSetAsyncEnumerableExtensions { /// /// Creates an immutable sorted set from an async-enumerable sequence. From c4a853b978ca81ccab9c80b37e338295d35cf998 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Wed, 15 Sep 2021 22:11:43 +0200 Subject: [PATCH 11/11] Update source generator to support different class and namespace names --- .../AsyncOverloadsGenerator.cs | 37 +++++++------------ .../Operators/ToImmutableDictionary.cs | 2 +- .../Operators/ToImmutableSortedDictionary.cs | 2 +- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs b/Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs index b0c27ecfee..e497565114 100644 --- a/Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs +++ b/Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs @@ -52,28 +52,21 @@ private static IEnumerable GetMethodsGroupedBySyntaxTree(Ge private static string GenerateOverloads(AsyncMethodGrouping grouping, GenerationOptions options) { - var usings = grouping.SyntaxTree.GetRoot() is CompilationUnitSyntax compilationUnit - ? compilationUnit.Usings.ToString() - : string.Empty; - - var overloads = new StringBuilder(); - overloads.AppendLine("#nullable enable"); - overloads.AppendLine(usings); - overloads.AppendLine("namespace System.Linq"); - overloads.AppendLine("{"); - overloads.AppendLine(" partial class AsyncEnumerable"); - overloads.AppendLine(" {"); - - foreach (var method in grouping.Methods) - overloads.AppendLine(GenerateOverload(method, options)); - - overloads.AppendLine(" }"); - overloads.AppendLine("}"); - - return overloads.ToString(); + var compilationRoot = grouping.SyntaxTree.GetCompilationUnitRoot(); + var namespaceDeclaration = compilationRoot.ChildNodes().OfType().Single(); + var classDeclaration = namespaceDeclaration.ChildNodes().OfType().Single(); + + return CompilationUnit() + .WithUsings(List(compilationRoot.Usings.Select(@using => @using.WithoutTrivia()))) + .AddMembers(NamespaceDeclaration(namespaceDeclaration.Name) + .AddMembers(ClassDeclaration(classDeclaration.Identifier) + .AddModifiers(Token(SyntaxKind.PartialKeyword)) + .WithMembers(List(grouping.Methods.Select(method => GenerateOverload(method, options)))))) + .NormalizeWhitespace() + .ToFullString(); } - private static string GenerateOverload(AsyncMethod method, GenerationOptions options) + private static MemberDeclarationSyntax GenerateOverload(AsyncMethod method, GenerationOptions options) => MethodDeclaration(method.Syntax.ReturnType, GetMethodName(method.Symbol, options)) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) .WithTypeParameterList(method.Syntax.TypeParameterList) @@ -87,9 +80,7 @@ private static string GenerateOverload(AsyncMethod method, GenerationOptions opt method.Syntax.ParameterList.Parameters .Select(p => Argument(IdentifierName(p.Identifier)))))))) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) - .WithLeadingTrivia(method.Syntax.GetLeadingTrivia().Where(t => t.GetStructure() is not DirectiveTriviaSyntax)) - .NormalizeWhitespace() - .ToFullString(); + .WithLeadingTrivia(method.Syntax.GetLeadingTrivia().Where(t => t.GetStructure() is not DirectiveTriviaSyntax)); private static INamedTypeSymbol GetAsyncOverloadAttributeSymbol(GeneratorExecutionContext context) => context.Compilation.GetTypeByMetadataName("System.Linq.GenerateAsyncOverloadAttribute") ?? throw new InvalidOperationException(); diff --git a/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableDictionary.cs b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableDictionary.cs index b7ef01964c..923c04f52d 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableDictionary.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableDictionary.cs @@ -10,7 +10,7 @@ namespace System.Collections.Immutable { - public static class ImmutableDictionaryAsyncEnumerableExtensions + public static partial class ImmutableDictionaryAsyncEnumerableExtensions { /// /// Creates an immutable dictionary from an async-enumerable sequence according to a specified key selector function. diff --git a/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableSortedDictionary.cs b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableSortedDictionary.cs index 627737d72c..51c6e36407 100644 --- a/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableSortedDictionary.cs +++ b/Ix.NET/Source/System.Linq.Async/System/Collections/Immutable/Operators/ToImmutableSortedDictionary.cs @@ -10,7 +10,7 @@ namespace System.Collections.Immutable { - public static class ImmutableSortedDictionaryAsyncEnumerableExtensions + public static partial class ImmutableSortedDictionaryAsyncEnumerableExtensions { /// /// Creates an immutable sorted dictionary from an async-enumerable sequence according to a specified key selector function, and an element selector function.