diff --git a/Ix.NET/Documentation/adr/0002-System-Linq-Async-In-Net10.md b/Ix.NET/Documentation/adr/0002-System-Linq-Async-In-Net10.md index 4c3c78991..cb5a1ab06 100644 --- a/Ix.NET/Documentation/adr/0002-System-Linq-Async-In-Net10.md +++ b/Ix.NET/Documentation/adr/0002-System-Linq-Async-In-Net10.md @@ -36,6 +36,8 @@ A further complication is that some methods in `System.Interactive.Async` clash One more important point to consider is that although LINQ to `IAsyncEnumerable` _mostly_ consists of extension methods, there are a few static methods. (E.g., `AsyncEnumerable.Range`, which the .NET library implements, and `AsyncEnumerable.Create`, which it does not.) With extension methods, the compiler does not have a problem with multiple identically-named types in different assemblies all defining extension methods as long as the individual methods do not conflict. However, non-extension methods are a problem. If `System.Linq.Async` were to continue to define a public `AsyncEnumerable` type, then calls to `AsyncEnumerable.Range` would fail to compile: even though there would only be a single `Range` method (supplied by the new `System.Linq.AsyncEnumerable`) this would fail to compile because `AsyncEnumerable` itself is an ambiguous class name. So it will be necessary for the public API of `System.Linq.Async` v7 not to define an `AsyncEnumerable` type. This places some limits on how far we can go with source-level compatibility. (Binary compatibility is not a problem because the runtime assemblies can continue to define this type.) +Since that constraint requires us to define a new type to hold all the obsolete extension methods (which we'll be calling `AsyncEnumerableDeprecated`) this creates a new problem: the runtime API needs to continue to provide all these methods as members of `AsyncEnumerable` (to provide binary compatibility) but any code newly compiled against Ix.NET v7 that is continuing to use these deprecated method (and which is therefore tolerating or suppressing the deprecation warning) will now end up building code that expects these methods to be in the `AsyncEnumerableDeprecated` class. We therefore need to provide all these methods in the runtime assemblies _twice_: once for binary compatibility as members of `AsyncEnumerable` (a class we completely hide at build time) and again as members of `AsyncEnumerableDeprecated` (the class we add to provide source-level backwards compatibility for code using the deprecated methods, in a way that doesn't cause ambiguous type name errors). + ## Decision @@ -43,13 +45,14 @@ The next Ix.NET release will: 1. add a reference to `System.Linq.AsyncEnumerable` and `System.Interactive.Async` in `System.Linq.Async` 2. remove from `System.Linq.Async`'s and `System.Interactive.Async`'s publicly visible API (ref assemblies) all `IAsyncEnumerable` extension methods for which direct replacements exist (adding `MinByWithTiesAsync` and `MaxByWithTiesAsync` for the case where the new .NET runtime library methods actually have slightly different functionality) -4. Rename `AsyncEnumerable` to `AsyncEnumerableDeprecated` in the public API (reference assemblies; the old name will be retained in runtime assemblies for binary compatibility) to avoid errors arising from there being two definitions of `AsyncEnumerable` in the same namespace -5. add [Obsolete] attribute for members of `AsyncEnumerableDeprecated` for which `System.Linq.AsyncEnumerable` offers replacements that require code changes to use (e.g., `WhereAwait`, which is replaced by an overload of `Where`) -6. the `AsyncEnumerable.ToEnumerable` method that was a bad idea and that should probably have never existed has been marked as `Obsolete` and will not be replaced; note that although `ToObservable` has issues that meant the .NET team decided not to replicate it, the main issue is that it embeds opinions, and not that there's anything fundamentally broken about it, so we do not include `ToObservable` in this category -7. remaining methods of `AsyncEnumerable` (where `System.Linq.AsyncEnumerable` offers no equivalent) are removed from the publicly visible API of `System.Linq.Async`, with identical replacements being defined by `AsyncEnumerableEx` in `System.Interactive.Async` -8. mark `IAsyncGrouping` as obsolete -9. mark the public `IAsyncIListProvider` as obsolete, and define a non-public version for continued internal use in `System.Interactive.Linq` -10. continue to provide the full `System.Linq.Async` API in the `lib` assemblies to provide binary compatibility +3. Rename `AsyncEnumerable` to `AsyncEnumerableDeprecated` in the public API (reference assemblies; the old name will be retained in runtime assemblies for binary compatibility) to avoid errors arising from there being two definitions of `AsyncEnumerable` in the same namespace +4. add [Obsolete] attribute for members of `AsyncEnumerableDeprecated` for which `System.Linq.AsyncEnumerable` offers replacements that require code changes to use (e.g., `WhereAwait`, which is replaced by an overload of `Where`) +5. the `AsyncEnumerable.ToEnumerable` method that was a bad idea and that should probably have never existed has been marked as `Obsolete` and will not be replaced; note that although `ToObservable` has issues that meant the .NET team decided not to replicate it, the main issue is that it embeds opinions, and not that there's anything fundamentally broken about it, so we do not include `ToObservable` in this category +6. remaining methods of `AsyncEnumerable` (where `System.Linq.AsyncEnumerable` offers no equivalent) are removed from the publicly visible API of `System.Linq.Async`, with identical replacements being defined by `AsyncEnumerableEx` in `System.Interactive.Async` +7. mark `IAsyncGrouping` as obsolete +8. mark the public `IAsyncIListProvider` as obsolete, and define a non-public version for continued internal use in `System.Interactive.Linq` +9. continue to provide the full `System.Linq.Async` API in the `lib` assemblies to provide binary compatibility +10. in the runtime `System.Linq.Async` assembly provide a facade that duplicates the legacy `AsyncEnumerable` methods on an `AsyncEnumerableDeprecated` type so that code that builds against `System.Linq.Async` v7, and which chooses to continue to use methods marked as `[Obsolete]`, will find those methods at runtime 11. mark the `System.Linq.Async` NuGet package as obsolete, and recommend the use of `System.Linq.AsyncEnumerable` and/or `System.Interactive.Async` instead The main effect of this is that code that had been using the `System.Linq.Async` implementation of LINQ for `IAsyncEnumerable` will, in most cases, now be using the .NET runtime library implementation if it is rebuilt against this new version of `System.Linq.Async`. diff --git a/Ix.NET/Source/Playground/Program.cs b/Ix.NET/Source/Playground/Program.cs index eb0dc304e..c3742b43e 100644 --- a/Ix.NET/Source/Playground/Program.cs +++ b/Ix.NET/Source/Playground/Program.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. #pragma warning disable IDE0051 // Remove unused private members - all used via reflection +#pragma warning disable CS0618 // Type or member is obsolete - this has not been updated since the deprecation of System.Linq.Async due to .NET 10's System.Linq.AsyncEnumerable using System; using System.Collections.Generic; diff --git a/Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs b/Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs index 1ab1229cc..e1db141d5 100644 --- a/Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs +++ b/Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs @@ -1,4 +1,8 @@ -using System.Collections.Generic; +// 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.IO; using System.Text; using Microsoft.CodeAnalysis; @@ -12,7 +16,7 @@ namespace System.Linq.Async.SourceGenerator [Generator] public sealed class AsyncOverloadsGenerator : ISourceGenerator { - private const string AttributeSource = + private const string GenerateAsyncOverloadAttributeSource = "using System;\n" + "using System.Diagnostics;\n" + "namespace System.Linq\n" + @@ -21,11 +25,24 @@ public sealed class AsyncOverloadsGenerator : ISourceGenerator " [Conditional(\"COMPILE_TIME_ONLY\")]\n" + " internal sealed class GenerateAsyncOverloadAttribute : Attribute { }\n" + "}\n"; + private const string DuplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttributeSource = + "using System;\n" + + "using System.Diagnostics;\n" + + "namespace System.Linq\n" + + "{\n" + + " [AttributeUsage(AttributeTargets.Assembly)]\n" + + " [Conditional(\"COMPILE_TIME_ONLY\")]\n" + + " internal sealed class DuplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttribute : Attribute { }\n" + + "}\n"; public void Initialize(GeneratorInitializationContext context) { context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); - context.RegisterForPostInitialization(c => c.AddSource("GenerateAsyncOverloadAttribute", AttributeSource)); + context.RegisterForPostInitialization(c => + { + c.AddSource("GenerateAsyncOverloadAttribute", GenerateAsyncOverloadAttributeSource); + c.AddSource("DuplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttribute", DuplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttributeSource); + }); } public void Execute(GeneratorExecutionContext context) @@ -33,13 +50,22 @@ public void Execute(GeneratorExecutionContext context) if (context.SyntaxReceiver is not SyntaxReceiver syntaxReceiver) return; var options = GetGenerationOptions(context); - var attributeSymbol = GetAsyncOverloadAttributeSymbol(context); + var asyncOverloadAttributeSymbol = GetAsyncOverloadAttributeSymbol(context); var methodsBySyntaxTree = GetMethodsGroupedBySyntaxTree(context, syntaxReceiver); foreach (var grouping in methodsBySyntaxTree.Where(g => g.Methods.Any())) context.AddSource( $"{Path.GetFileNameWithoutExtension(grouping.SyntaxTree.FilePath)}.AsyncOverloads", - GenerateOverloads(grouping, options, context, attributeSymbol)); + GenerateOverloads(grouping, options, context, asyncOverloadAttributeSymbol)); + + var duplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttributeSymbol = GetDuplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttributeSymbol(context); + var dupBuilder = new DeprecatedDuplicateBuilder( + context, + options, + asyncOverloadAttributeSymbol, + duplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttributeSymbol, + syntaxReceiver); + dupBuilder.BuildDuplicatesIfRequired(); } private static GenerationOptions GetGenerationOptions(GeneratorExecutionContext context) @@ -95,7 +121,7 @@ private static string GenerateOverload(AsyncMethod method, GenerationOptions opt select a)))) .Where(list => list.Attributes.Count > 0)); - return MethodDeclaration(method.Syntax.ReturnType, GetMethodName(method.Symbol, options)) + return MethodDeclaration(method.Syntax.ReturnType, GetMethodNameForGeneratedAsyncMethod(method.Symbol, options)) .WithAttributeLists(attributeListsWithGenerateAsyncOverloadRemoved) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) .WithTypeParameterList(method.Syntax.TypeParameterList) @@ -117,8 +143,11 @@ private static string GenerateOverload(AsyncMethod method, GenerationOptions opt private static INamedTypeSymbol GetAsyncOverloadAttributeSymbol(GeneratorExecutionContext context) => context.Compilation.GetTypeByMetadataName("System.Linq.GenerateAsyncOverloadAttribute") ?? throw new InvalidOperationException(); + private static INamedTypeSymbol GetDuplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttributeSymbol(GeneratorExecutionContext context) + => context.Compilation.GetTypeByMetadataName("System.Linq.DuplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttribute") ?? throw new InvalidOperationException(); + private static IEnumerable GetMethodsGroupedBySyntaxTree(GeneratorExecutionContext context, SyntaxReceiver syntaxReceiver, INamedTypeSymbol attributeSymbol) - => from candidate in syntaxReceiver.Candidates + => from candidate in syntaxReceiver.CandidateMethods group candidate by candidate.SyntaxTree into grouping let model = context.Compilation.GetSemanticModel(grouping.Key) select new AsyncMethodGrouping( @@ -128,7 +157,7 @@ from methodSyntax in grouping where methodSymbol.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass!, attributeSymbol)) select new AsyncMethod(methodSymbol, methodSyntax)); - private static string GetMethodName(IMethodSymbol methodSymbol, GenerationOptions options) + internal static string GetMethodNameForGeneratedAsyncMethod(IMethodSymbol methodSymbol, GenerationOptions options) { var methodName = methodSymbol.Name.Replace("Core", ""); return options.SupportFlatAsyncApi diff --git a/Ix.NET/Source/System.Linq.Async.SourceGenerator/DeprecatedDuplicateBuilder.cs b/Ix.NET/Source/System.Linq.Async.SourceGenerator/DeprecatedDuplicateBuilder.cs new file mode 100644 index 000000000..dc264aa25 --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async.SourceGenerator/DeprecatedDuplicateBuilder.cs @@ -0,0 +1,233 @@ +// 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 Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace System.Linq.Async.SourceGenerator +{ + /// + /// Builds a facade class containing duplicate definitions of the various deprecated AsyncEnumerable methods + /// as members of AsyncEnumerableDeprecated. + /// + /// + /// + /// This is necessary because of complicated backwards compatibility issues. + /// + /// + /// The scenario this addresses is when an application has been using System.Linq.Async v6, and was using + /// methods that have been marked as obsolete in System.Linq.Async v7. For example, code might be using + /// the WhereAwaitWithCancellation extension method. + /// + /// + /// When the developer upgrades such a project to System.Linq.Async v7, we want to ensure that they get + /// deprecation warnings telling them which method they should use instead (e.g., WhereAwaitWithCancellation + /// should be replaced with one of the overloads of Where that .NET 10's System.Linq.AsyncEnumerable + /// defines. However, we don't want to break their build immediately; if they are OK with the deprecation warnings, + /// we want their existing code to continue to work without changes. + /// + /// + /// This is complicated by the fact that in .NET 10, System.Linq.AsyncEnumerable now defines its own + /// AsyncEnumerable type, meaning that System.Linq.Async's public API must no longer contain a type + /// of that name. (Otherwise, code such as AsyncEnumerable.Range(1, 10) would fail to compile due to the + /// type name being ambiguous.) Thus, the public-facing API of System.Linq.Async in v7 has moved all of the + /// extension methods that it continues to define into a type named AsyncEnumerableDeprecated. (We've + /// called it this because the only methods we need to retain from the public API are the ones that are deprecated. + /// In cases where there are direct replacements in .NET 10's System.Linq.AsyncEnumerable, we've removed + /// the corresponding methods from System.Linq.Async entirely. And in other cases we've moved functionality + /// into System.Interactive.Async. The goal is for everyone to stop using System.Linq.Async, so by + /// definition, if you are still using a method it defines, that method is obsolete.) + /// + /// + /// But now the problem is that code that continues to use these deprecated methods will expect them to live in + /// AsyncEnumerableDeprecated, because that's where the compiler will find the relevant methods. So + /// the runtime assembly will need to make these methods available in a type of that name. But for binary backwards + /// compatibility, we need every method that our AsyncEnumerable defined in V6 still to be available on + /// a type still called AsyncEnumerable. + /// + /// + /// In other words, we need to make our API available twice, on two different types. One for code that hasn't been + /// recompiled against v7, and therefore expects all the methods to be in AsyncEnumerable, and one for code + /// that has been recompiled against v7 but which has chosen to continue using deprecated method, and which will + /// expect those to be in AsyncEnumerableDeprecated. + /// + /// + /// So this generator duplicates public static methods defined by AsyncEnumerable into AsyncEnumerableDeprecated. + /// It also strips off their extension method 'this' modifier from the first parameter, so that they are normal static methods, + /// because otherwise, we get ambiguity errors in our unit tests. + /// + /// + internal class DeprecatedDuplicateBuilder + { + private readonly GeneratorExecutionContext _context; + private readonly GenerationOptions _options; + private readonly INamedTypeSymbol _generateAsyncOverloadAttributeAttributeSymbol; + private readonly INamedTypeSymbol _attributeSymbol; + private readonly SyntaxReceiver _syntaxReceiver; + + public DeprecatedDuplicateBuilder( + GeneratorExecutionContext context, + GenerationOptions options, + INamedTypeSymbol generateAsyncOverloadAttributeAttributeSymbol, + INamedTypeSymbol duplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttributeSymbol, + SyntaxReceiver syntaxReceiver) + { + _context = context; + _options = options; + _generateAsyncOverloadAttributeAttributeSymbol = generateAsyncOverloadAttributeAttributeSymbol; + _attributeSymbol = duplicateAsyncEnumerableAsAsyncEnumerableDeprecatedAttributeSymbol; + _syntaxReceiver = syntaxReceiver; + } + + internal void BuildDuplicatesIfRequired() + { + if (!_syntaxReceiver.CandidateGenerateDeprecatedDuplicatesAttributes.Any(a => + { + var sm = _context.Compilation.GetSemanticModel(a.SyntaxTree); + var am = sm.GetSymbolInfo(a.Name).Symbol?.ContainingType; + + return SymbolEqualityComparer.Default.Equals(am, _attributeSymbol); + })) + { + // The assembly does not have the attribute, so we mustn't run. + return; + } + + foreach (var classDeclaration in _syntaxReceiver.CandidateAsyncEnumerableClasses) + { + var sm = _context.Compilation.GetSemanticModel(classDeclaration.SyntaxTree); + var classSymbol = sm.GetDeclaredSymbol(classDeclaration); + if (classSymbol == null || classSymbol.DeclaredAccessibility != Accessibility.Public) + { + continue; + } + + // We aren't a general purpose generator, so we only handle the case where the class is nested in a namespace. + if (classDeclaration.Parent is not NamespaceDeclarationSyntax nsDecl) + { + _context.ReportDiagnostic(Diagnostic.Create(new DiagnosticDescriptor( + "IXNETG001", + "AsyncEnumerable class must be in a namespace declaration", + "AsyncEnumerable class must be declared within a namespace to generate deprecated duplicates", + "Usage", + DiagnosticSeverity.Warning, + isEnabledByDefault: true), + classDeclaration.Identifier.GetLocation())); + + continue; + } + + if (nsDecl.Parent is not CompilationUnitSyntax file) + { _context.ReportDiagnostic(Diagnostic.Create(new DiagnosticDescriptor( + "IXNETG002", + "Namespace must be in compilation unit", + "Namespace containing AsyncEnumerable class must be declared within a compilation unit to generate deprecated duplicates", + "Usage", + DiagnosticSeverity.Warning, + isEnabledByDefault: true), + nsDecl.Name.GetLocation())); + continue; + } + + var facadeClass = SyntaxFactory.ClassDeclaration("AsyncEnumerableDeprecated") + .WithModifiers(SyntaxFactory.TokenList( + SyntaxFactory.Token(SyntaxKind.PublicKeyword), + SyntaxFactory.Token(SyntaxKind.StaticKeyword), + SyntaxFactory.Token(SyntaxKind.PartialKeyword))); + bool atLeastOneMethod = false; + foreach (var method in classDeclaration.Members.OfType()) + { + var facadeMethod = method; + string? methodName = null; + if (facadeMethod.Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword))) + { + // We're only generating duplicates for obsolete methods. (The non-obsolete + // methods have been removed from AsyncEnumerable's public API entirely, + // because either they are now available in .NET 10's System.Linq.AsyncEnumerable + // or we've moved them to System.Interactive.Async.) + if (!facadeMethod.AttributeLists.SelectMany(a => a.Attributes) + .Any(a => + { + var asym = sm.GetSymbolInfo(a); + return asym.Symbol?.ContainingType.Name == "ObsoleteAttribute" && asym.Symbol.ContainingNamespace?.Name == "System"; + })) + { + continue; + } + + methodName = facadeMethod.Identifier.Text; + } + else + { + // We also need to emit the facades corresponding to the public methods generated with [GenerateAsyncOverload]. + // (Since this code runs as part of the same generator that expands those, we don't get to see the expanded versions + // as input, so we end up slightly duplicating a little of the logic here.) + if (facadeMethod.AttributeLists.SelectMany(a => a.Attributes).Any(a => + SymbolEqualityComparer.Default.Equals(sm.GetSymbolInfo(a.Name).Symbol?.ContainingType, _generateAsyncOverloadAttributeAttributeSymbol))) + { + var originalMethodSymbol = sm.GetDeclaredSymbol(method)!; + methodName = AsyncOverloadsGenerator.GetMethodNameForGeneratedAsyncMethod(originalMethodSymbol, _options); + + facadeMethod = facadeMethod.WithIdentifier(SyntaxFactory.Identifier(methodName)); + } + } + + if (methodName is not null) + { + // Strip off 'this' from first parameter if it's an extension method. + if (facadeMethod.ParameterList.Parameters.Count > 0) + { + var firstParam = facadeMethod.ParameterList.Parameters[0]; + if (firstParam.Modifiers.Any(SyntaxKind.ThisKeyword)) + { + var newFirstParam = firstParam.WithModifiers(SyntaxFactory.TokenList()); + var newParamList = facadeMethod.ParameterList.WithParameters( + facadeMethod.ParameterList.Parameters.Replace(firstParam, newFirstParam)); + facadeMethod = facadeMethod.WithParameterList(newParamList); + } + } + + // We don't want to duplicate the implementation. We just generate a simple + // facade that defers to the original method. + var invokeOriginalMethod = SyntaxFactory.InvocationExpression( + SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("AsyncEnumerable"), SyntaxFactory.IdentifierName(methodName)), + SyntaxFactory.ArgumentList( + SyntaxFactory.SeparatedList( + facadeMethod.ParameterList.Parameters.Select(p => + SyntaxFactory.Argument(SyntaxFactory.IdentifierName(p.Identifier)))))); + facadeMethod = facadeMethod + .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword))) + .WithAttributeLists(SyntaxFactory.List()) + .WithBody(null) + .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(invokeOriginalMethod)) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)) + .NormalizeWhitespace(); + facadeClass = facadeClass.AddMembers(facadeMethod); + + atLeastOneMethod = true; + } + } + + if (atLeastOneMethod) + { + var namespaceWithClassDup = nsDecl.WithMembers(SyntaxFactory.SingletonList(facadeClass)); + var fileWithDup = file + .WithLeadingTrivia(file.GetLeadingTrivia().Add(SyntaxFactory.Trivia(SyntaxFactory.NullableDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.EnableKeyword), true)))) + .WithMembers(SyntaxFactory.SingletonList(namespaceWithClassDup)); + + var source = fileWithDup + .NormalizeWhitespace() + .ToFullString(); + if (!string.IsNullOrEmpty(source)) + { + string existingFileName = System.IO.Path.GetFileNameWithoutExtension(classDeclaration.SyntaxTree.FilePath); + _context.AddSource($"{existingFileName}.DeprecatedDuplicates.g.cs", source); + } + + } + } + } + } +} diff --git a/Ix.NET/Source/System.Linq.Async.SourceGenerator/SyntaxReceiver.cs b/Ix.NET/Source/System.Linq.Async.SourceGenerator/SyntaxReceiver.cs index 5bd54f9c0..3a0bd54e5 100644 --- a/Ix.NET/Source/System.Linq.Async.SourceGenerator/SyntaxReceiver.cs +++ b/Ix.NET/Source/System.Linq.Async.SourceGenerator/SyntaxReceiver.cs @@ -7,13 +7,26 @@ namespace System.Linq.Async.SourceGenerator { internal sealed class SyntaxReceiver : ISyntaxReceiver { - public IList Candidates { get; } = new List(); + public List CandidateMethods { get; } = new(); + public List CandidateAsyncEnumerableClasses { get; } = new(); + public List CandidateGenerateDeprecatedDuplicatesAttributes { get; } = new(); public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { if (syntaxNode is MethodDeclarationSyntax { AttributeLists: { Count: >0 } } methodDeclarationSyntax) { - Candidates.Add(methodDeclarationSyntax); + CandidateMethods.Add(methodDeclarationSyntax); + } + else if (syntaxNode is ClassDeclarationSyntax { Identifier.Text: "AsyncEnumerable" } classDeclarationSyntax) + { + CandidateAsyncEnumerableClasses.Add(classDeclarationSyntax); + } + else if (syntaxNode is AttributeSyntax generateDeprecatedAttribute && + (generateDeprecatedAttribute.Parent is AttributeListSyntax { Target.Identifier.Text: "assembly" }) && + (generateDeprecatedAttribute.Name is IdentifierNameSyntax { Identifier.Text: "DuplicateAsyncEnumerableAsAsyncEnumerableDeprecated" } || + generateDeprecatedAttribute.Name is QualifiedNameSyntax { Right: IdentifierNameSyntax { Identifier.Text: "DuplicateAsyncEnumerableAsAsyncEnumerableDeprecated" } })) + { + CandidateGenerateDeprecatedDuplicatesAttributes.Add(generateDeprecatedAttribute); } } } diff --git a/Ix.NET/Source/System.Linq.Async.SourceGenerator/System.Linq.Async.SourceGenerator.csproj b/Ix.NET/Source/System.Linq.Async.SourceGenerator/System.Linq.Async.SourceGenerator.csproj index 28f77affa..bb8b5034a 100644 --- a/Ix.NET/Source/System.Linq.Async.SourceGenerator/System.Linq.Async.SourceGenerator.csproj +++ b/Ix.NET/Source/System.Linq.Async.SourceGenerator/System.Linq.Async.SourceGenerator.csproj @@ -2,7 +2,7 @@ netstandard2.0 true - 9.0 + 14.0 false diff --git a/Ix.NET/Source/System.Linq.Async/EnableDeprecationFacadeInRuntimeAssembly.cs b/Ix.NET/Source/System.Linq.Async/EnableDeprecationFacadeInRuntimeAssembly.cs new file mode 100644 index 000000000..bf93d6d0a --- /dev/null +++ b/Ix.NET/Source/System.Linq.Async/EnableDeprecationFacadeInRuntimeAssembly.cs @@ -0,0 +1,5 @@ +// 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. + +[assembly: System.Linq.DuplicateAsyncEnumerableAsAsyncEnumerableDeprecated] diff --git a/Ix.NET/Source/Tests.System.Interactive.ApiApprovals/Api/ApiApprovalTests.SystemLinqAsync.verified.cs b/Ix.NET/Source/Tests.System.Interactive.ApiApprovals/Api/ApiApprovalTests.SystemLinqAsync.verified.cs index 9f3f7a3e0..904e16315 100644 --- a/Ix.NET/Source/Tests.System.Interactive.ApiApprovals/Api/ApiApprovalTests.SystemLinqAsync.verified.cs +++ b/Ix.NET/Source/Tests.System.Interactive.ApiApprovals/Api/ApiApprovalTests.SystemLinqAsync.verified.cs @@ -903,6 +903,218 @@ public static System.Collections.Generic.IAsyncEnumerable ZipAwait ZipAwaitWithCancellation(this System.Collections.Generic.IAsyncEnumerable first, System.Collections.Generic.IAsyncEnumerable second, System.Func> selector) { } } + public static class AsyncEnumerableDeprecated + { + public static System.Threading.Tasks.ValueTask AggregateAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> accumulator, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AggregateAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, TAccumulate seed, System.Func> accumulator, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AggregateAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, TAccumulate seed, System.Func> accumulator, System.Func> resultSelector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AggregateAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> accumulator, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AggregateAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, TAccumulate seed, System.Func> accumulator, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AggregateAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, TAccumulate seed, System.Func> accumulator, System.Func> resultSelector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AllAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AllAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AnyAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AnyAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask AverageAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask CountAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask CountAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask FirstAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask FirstAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask FirstOrDefaultAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask FirstOrDefaultAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.Task ForEachAsync(System.Collections.Generic.IAsyncEnumerable source, System.Action action, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.Task ForEachAsync(System.Collections.Generic.IAsyncEnumerable source, System.Action action, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.Task ForEachAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func action, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.Task ForEachAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func action, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.Task ForEachAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func action, System.Threading.CancellationToken cancellationToken) { } + public static System.Threading.Tasks.Task ForEachAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func action, System.Threading.CancellationToken cancellationToken) { } + public static System.Collections.Generic.IAsyncEnumerable> GroupByAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector) { } + public static System.Collections.Generic.IAsyncEnumerable> GroupByAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable> GroupByAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector) { } + public static System.Collections.Generic.IAsyncEnumerable GroupByAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func, System.Threading.Tasks.ValueTask> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable> GroupByAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable GroupByAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func, System.Threading.Tasks.ValueTask> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable GroupByAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Func, System.Threading.Tasks.ValueTask> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable GroupByAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Func, System.Threading.Tasks.ValueTask> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable> GroupByAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector) { } + public static System.Collections.Generic.IAsyncEnumerable> GroupByAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable> GroupByAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector) { } + public static System.Collections.Generic.IAsyncEnumerable GroupByAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable> GroupByAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable GroupByAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable GroupByAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Func, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable GroupByAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Func, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable GroupJoinAwait(System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func, System.Threading.Tasks.ValueTask> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable GroupJoinAwait(System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func, System.Threading.Tasks.ValueTask> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable GroupJoinAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable GroupJoinAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable JoinAwait(System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable JoinAwait(System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Collections.Generic.IAsyncEnumerable JoinAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable JoinAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { } + public static System.Threading.Tasks.ValueTask LastAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask LastAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask LastOrDefaultAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask LastOrDefaultAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask LongCountAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask LongCountAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MaxAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask MinAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Linq.IOrderedAsyncEnumerable OrderByAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector) { } + public static System.Linq.IOrderedAsyncEnumerable OrderByAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IComparer comparer) { } + public static System.Linq.IOrderedAsyncEnumerable OrderByAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector) { } + public static System.Linq.IOrderedAsyncEnumerable OrderByAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IComparer comparer) { } + public static System.Linq.IOrderedAsyncEnumerable OrderByDescendingAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector) { } + public static System.Linq.IOrderedAsyncEnumerable OrderByDescendingAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IComparer comparer) { } + public static System.Linq.IOrderedAsyncEnumerable OrderByDescendingAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector) { } + public static System.Linq.IOrderedAsyncEnumerable OrderByDescendingAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IComparer comparer) { } + public static System.Collections.Generic.IAsyncEnumerable SelectAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectManyAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func>> selector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectManyAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func>> selector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectManyAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func>> collectionSelector, System.Func> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectManyAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func>> collectionSelector, System.Func> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectManyAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func>> selector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectManyAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func>> selector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectManyAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func>> collectionSelector, System.Func> resultSelector) { } + public static System.Collections.Generic.IAsyncEnumerable SelectManyAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func>> collectionSelector, System.Func> resultSelector) { } + public static System.Threading.Tasks.ValueTask SingleAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SingleAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SingleOrDefaultAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SingleOrDefaultAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Collections.Generic.IAsyncEnumerable SkipWhileAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Collections.Generic.IAsyncEnumerable SkipWhileAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Collections.Generic.IAsyncEnumerable SkipWhileAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Collections.Generic.IAsyncEnumerable SkipWhileAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Threading.Tasks.ValueTask SumAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask SumAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> selector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Collections.Generic.IAsyncEnumerable TakeWhileAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Collections.Generic.IAsyncEnumerable TakeWhileAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Collections.Generic.IAsyncEnumerable TakeWhileAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Collections.Generic.IAsyncEnumerable TakeWhileAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Linq.IOrderedAsyncEnumerable ThenByAwait(System.Linq.IOrderedAsyncEnumerable source, System.Func> keySelector) { } + public static System.Linq.IOrderedAsyncEnumerable ThenByAwait(System.Linq.IOrderedAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IComparer comparer) { } + public static System.Linq.IOrderedAsyncEnumerable ThenByAwaitWithCancellation(System.Linq.IOrderedAsyncEnumerable source, System.Func> keySelector) { } + public static System.Linq.IOrderedAsyncEnumerable ThenByAwaitWithCancellation(System.Linq.IOrderedAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IComparer comparer) { } + public static System.Linq.IOrderedAsyncEnumerable ThenByDescendingAwait(System.Linq.IOrderedAsyncEnumerable source, System.Func> keySelector) { } + public static System.Linq.IOrderedAsyncEnumerable ThenByDescendingAwait(System.Linq.IOrderedAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IComparer comparer) { } + public static System.Linq.IOrderedAsyncEnumerable ThenByDescendingAwaitWithCancellation(System.Linq.IOrderedAsyncEnumerable source, System.Func> keySelector) { } + public static System.Linq.IOrderedAsyncEnumerable ThenByDescendingAwaitWithCancellation(System.Linq.IOrderedAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IComparer comparer) { } + public static System.Threading.Tasks.ValueTask> ToDictionaryAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Threading.CancellationToken cancellationToken = default) + where TKey : notnull { } + public static System.Threading.Tasks.ValueTask> ToDictionaryAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IEqualityComparer? comparer, System.Threading.CancellationToken cancellationToken = default) + where TKey : notnull { } + public static System.Threading.Tasks.ValueTask> ToDictionaryAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Threading.CancellationToken cancellationToken = default) + where TKey : notnull { } + public static System.Threading.Tasks.ValueTask> ToDictionaryAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Collections.Generic.IEqualityComparer? comparer, System.Threading.CancellationToken cancellationToken = default) + where TKey : notnull { } + public static System.Threading.Tasks.ValueTask> ToDictionaryAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Threading.CancellationToken cancellationToken = default) + where TKey : notnull { } + public static System.Threading.Tasks.ValueTask> ToDictionaryAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IEqualityComparer? comparer, System.Threading.CancellationToken cancellationToken = default) + where TKey : notnull { } + public static System.Threading.Tasks.ValueTask> ToDictionaryAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Threading.CancellationToken cancellationToken = default) + where TKey : notnull { } + public static System.Threading.Tasks.ValueTask> ToDictionaryAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Collections.Generic.IEqualityComparer? comparer, System.Threading.CancellationToken cancellationToken = default) + where TKey : notnull { } + public static System.Collections.Generic.IEnumerable ToEnumerable(System.Collections.Generic.IAsyncEnumerable source) { } + public static System.Threading.Tasks.ValueTask> ToLookupAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask> ToLookupAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IEqualityComparer? comparer, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask> ToLookupAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask> ToLookupAwaitAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Collections.Generic.IEqualityComparer? comparer, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask> ToLookupAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask> ToLookupAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Collections.Generic.IEqualityComparer? comparer, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask> ToLookupAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.ValueTask> ToLookupAwaitWithCancellationAsync(System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Collections.Generic.IEqualityComparer? comparer, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Collections.Generic.IAsyncEnumerable WhereAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Collections.Generic.IAsyncEnumerable WhereAwait(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Collections.Generic.IAsyncEnumerable WhereAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Collections.Generic.IAsyncEnumerable WhereAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate) { } + public static System.Collections.Generic.IAsyncEnumerable ZipAwait(System.Collections.Generic.IAsyncEnumerable first, System.Collections.Generic.IAsyncEnumerable second, System.Func> selector) { } + public static System.Collections.Generic.IAsyncEnumerable ZipAwaitWithCancellation(System.Collections.Generic.IAsyncEnumerable first, System.Collections.Generic.IAsyncEnumerable second, System.Func> selector) { } + } public interface IAsyncGrouping : System.Collections.Generic.IAsyncEnumerable { TKey Key { get; }