/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Symbol/Compilation/ForEachStatementInfoTests.cs
201 строка
10 KB
Fred Silberberg
Add followup async public apis (#80455)
07 окт 2025, 03:26
Не верифицирован
07 окт 2025, 03:26
1017e4a
Код
Авторство
О чём код?
// 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. #nullable disable using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp { public class ForEachStatementInfoTests : CSharpTestBase { [Fact] public void Equality() { var c = (Compilation)CreateCompilation(@" class E1 { public E GetEnumerator() { return null; } public bool MoveNext() { return false; } public object Current { get; } public void Dispose() { } } class E2 { public E GetEnumerator() { return null; } public bool MoveNext() { return false; } public object Current { get; } public void Dispose() { } } "); var e1 = (ITypeSymbol)c.GlobalNamespace.GetMembers("E1").Single(); var ge1 = (IMethodSymbol)e1.GetMembers("GetEnumerator").Single(); var mn1 = (IMethodSymbol)e1.GetMembers("MoveNext").Single(); var cur1 = (IPropertySymbol)e1.GetMembers("Current").Single(); var disp1 = (IMethodSymbol)e1.GetMembers("Dispose").Single(); var conv1 = Conversion.Identity; var mnea1 = default(AwaitExpressionInfo); var dispa1 = default(AwaitExpressionInfo); var e2 = (ITypeSymbol)c.GlobalNamespace.GetMembers("E2").Single(); var ge2 = (IMethodSymbol)e2.GetMembers("GetEnumerator").Single(); var mn2 = (IMethodSymbol)e2.GetMembers("MoveNext").Single(); var cur2 = (IPropertySymbol)e2.GetMembers("Current").Single(); var disp2 = (IMethodSymbol)e2.GetMembers("Dispose").Single(); var conv2 = Conversion.NoConversion; var mnea2 = new AwaitExpressionInfo(mn2, null, null, null, false); var dispa2 = new AwaitExpressionInfo(disp2, null, null, null, false); EqualityTesting.AssertEqual(default(ForEachStatementInfo), default(ForEachStatementInfo)); EqualityTesting.AssertEqual(new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1), new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); EqualityTesting.AssertNotEqual(new ForEachStatementInfo(isAsync: true, ge2, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1), new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); EqualityTesting.AssertNotEqual(new ForEachStatementInfo(isAsync: true, ge1, mn2, mnea1, cur1, disp1, dispa1, e1, conv1, conv1), new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); EqualityTesting.AssertNotEqual(new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea2, cur1, disp1, dispa1, e1, conv1, conv1), new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); EqualityTesting.AssertNotEqual(new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur2, disp1, dispa1, e1, conv1, conv1), new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); EqualityTesting.AssertNotEqual(new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp2, dispa1, e1, conv1, conv1), new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); EqualityTesting.AssertNotEqual(new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa2, e1, conv1, conv1), new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); EqualityTesting.AssertNotEqual(new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e2, conv1, conv1), new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); EqualityTesting.AssertNotEqual(new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv2, conv1), new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); EqualityTesting.AssertNotEqual(new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv2), new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); EqualityTesting.AssertNotEqual(new ForEachStatementInfo(isAsync: true, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1), new ForEachStatementInfo(isAsync: false, ge1, mn1, mnea1, cur1, disp1, dispa1, e1, conv1, conv1)); } [Fact] public void TestAwaitForeachAwaitableInfo() { var text = @" using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; class C { async Task M() { await foreach (var x in new AsyncEnumerable()) { } } } class AsyncEnumerable : IAsyncEnumerable<int> { public IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default) => new AsyncEnumerator(); } class AsyncEnumerator : IAsyncEnumerator<int> { public int Current => 42; public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(false); public ValueTask DisposeAsync() => default; }"; var comp = CreateCompilationWithTasksExtensions(new[] { text, s_IAsyncEnumerable }); validate(comp, isRuntimeAsync: false); comp = CreateRuntimeAsyncCompilation(text); validate(comp, isRuntimeAsync: true); static void validate(CSharpCompilation comp, bool isRuntimeAsync) { comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); var awaitForeachStatement = tree.GetRoot().DescendantNodes().OfType<ForEachStatementSyntax>().Single(); var info = model.GetForEachStatementInfo(awaitForeachStatement); Assert.True(info.IsAsynchronous); // Verify MoveNextAwaitableInfo var moveNextAwaitInfo = info.MoveNextAwaitableInfo; if (isRuntimeAsync) { Assert.Null(moveNextAwaitInfo.GetAwaiterMethod); Assert.Null(moveNextAwaitInfo.IsCompletedProperty); Assert.Null(moveNextAwaitInfo.GetResultMethod); AssertEx.Equal("System.Boolean System.Runtime.CompilerServices.AsyncHelpers.Await<System.Boolean>(System.Threading.Tasks.ValueTask<System.Boolean> task)", moveNextAwaitInfo.RuntimeAwaitMethod.ToTestDisplayString()); } else { AssertEx.Equal("System.Runtime.CompilerServices.ValueTaskAwaiter<System.Boolean> System.Threading.Tasks.ValueTask<System.Boolean>.GetAwaiter()", moveNextAwaitInfo.GetAwaiterMethod.ToTestDisplayString()); Assert.NotNull(moveNextAwaitInfo.IsCompletedProperty); Assert.NotNull(moveNextAwaitInfo.GetResultMethod); Assert.Null(moveNextAwaitInfo.RuntimeAwaitMethod); } Assert.False(moveNextAwaitInfo.IsDynamic); // Verify DisposeAwaitableInfo var disposeAwaitInfo = info.DisposeAwaitableInfo; if (isRuntimeAsync) { Assert.Null(disposeAwaitInfo.GetAwaiterMethod); Assert.Null(disposeAwaitInfo.IsCompletedProperty); Assert.Null(disposeAwaitInfo.GetResultMethod); AssertEx.Equal("void System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.ValueTask task)", disposeAwaitInfo.RuntimeAwaitMethod.ToTestDisplayString()); } else { AssertEx.Equal("System.Runtime.CompilerServices.ValueTaskAwaiter System.Threading.Tasks.ValueTask.GetAwaiter()", disposeAwaitInfo.GetAwaiterMethod.ToTestDisplayString()); Assert.NotNull(disposeAwaitInfo.IsCompletedProperty); Assert.NotNull(disposeAwaitInfo.GetResultMethod); Assert.Null(disposeAwaitInfo.RuntimeAwaitMethod); } Assert.False(disposeAwaitInfo.IsDynamic); } } [Fact] public void TestSynchronousForeachAwaitableInfo() { var text = @" using System.Collections.Generic; class C { void M() { foreach (var x in new List<int>()) { } } }"; var comp = CreateCompilation(text); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var foreachStatement = tree.GetRoot().DescendantNodes().OfType<ForEachStatementSyntax>().Single(); var info = model.GetForEachStatementInfo(foreachStatement); Assert.False(info.IsAsynchronous); var moveNextAwaitInfo = info.MoveNextAwaitableInfo; Assert.Null(moveNextAwaitInfo.GetAwaiterMethod); Assert.Null(moveNextAwaitInfo.IsCompletedProperty); Assert.Null(moveNextAwaitInfo.GetResultMethod); Assert.False(moveNextAwaitInfo.IsDynamic); var disposeAwaitInfo = info.DisposeAwaitableInfo; Assert.Null(disposeAwaitInfo.GetAwaiterMethod); Assert.Null(disposeAwaitInfo.IsCompletedProperty); Assert.Null(disposeAwaitInfo.GetResultMethod); Assert.False(disposeAwaitInfo.IsDynamic); } } }