-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Report diagnostics from TryFindDisposePatternMethod
when binding foreach
loop
#75422
Changes from 4 commits
9bab481
ed0cb34
bbd8ba6
adfc9f2
c31ec4e
0139aac
75a746a
92328fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4821,8 +4821,8 @@ public static class Extensions | |
CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(1) Got(1,-1) NextAsync(1) Current(2) Got(2,-2) NextAsync(2) Dispose(3) Done"); | ||
} | ||
|
||
[Fact] | ||
public void TestWithPatternAndObsolete() | ||
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/30257")] | ||
public void TestWithPatternAndObsolete_WithDisposableInterface() | ||
{ | ||
string source = @" | ||
using System.Threading.Tasks; | ||
|
@@ -4852,6 +4852,54 @@ public sealed class AsyncEnumerator : System.IAsyncDisposable | |
}"; | ||
var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); | ||
comp.VerifyDiagnostics( | ||
// (7,15): warning CS0612: 'C.AsyncEnumerator.DisposeAsync()' is obsolete | ||
// await foreach (var i in new C()) | ||
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "foreach").WithArguments("C.AsyncEnumerator.DisposeAsync()").WithLocation(7, 15), | ||
// (7,15): warning CS0612: 'C.GetAsyncEnumerator(CancellationToken)' is obsolete | ||
// await foreach (var i in new C()) | ||
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "foreach").WithArguments("C.GetAsyncEnumerator(System.Threading.CancellationToken)").WithLocation(7, 15), | ||
// (7,15): warning CS0612: 'C.AsyncEnumerator.MoveNextAsync()' is obsolete | ||
// await foreach (var i in new C()) | ||
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "foreach").WithArguments("C.AsyncEnumerator.MoveNextAsync()").WithLocation(7, 15), | ||
// (7,15): warning CS0612: 'C.AsyncEnumerator.Current' is obsolete | ||
// await foreach (var i in new C()) | ||
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "foreach").WithArguments("C.AsyncEnumerator.Current").WithLocation(7, 15)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
|
||
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/30257")] | ||
public void TestWithPatternAndObsolete_WithoutDisposableInterface() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider testing with explicit interface implementation of the DisposeAsync method. #Resolved There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you add this test? I couldn't find it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My mistake. Added now :-) |
||
{ | ||
string source = @" | ||
using System.Threading.Tasks; | ||
class C | ||
{ | ||
static async System.Threading.Tasks.Task Main() | ||
{ | ||
await foreach (var i in new C()) | ||
{ | ||
} | ||
} | ||
[System.Obsolete] | ||
public AsyncEnumerator GetAsyncEnumerator(System.Threading.CancellationToken token = default) | ||
{ | ||
throw null; | ||
} | ||
[System.Obsolete] | ||
public sealed class AsyncEnumerator | ||
{ | ||
[System.Obsolete] | ||
public int Current { get => throw null; } | ||
[System.Obsolete] | ||
public Task<bool> MoveNextAsync() => throw null; | ||
[System.Obsolete] | ||
public ValueTask DisposeAsync() => throw null; | ||
} | ||
}"; | ||
var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); | ||
comp.VerifyDiagnostics( | ||
// (7,15): warning CS0612: 'C.AsyncEnumerator.DisposeAsync()' is obsolete | ||
// await foreach (var i in new C()) | ||
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "foreach").WithArguments("C.AsyncEnumerator.DisposeAsync()").WithLocation(7, 15), | ||
// (7,15): warning CS0612: 'C.GetAsyncEnumerator(CancellationToken)' is obsolete | ||
// await foreach (var i in new C()) | ||
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "foreach").WithArguments("C.GetAsyncEnumerator(System.Threading.CancellationToken)").WithLocation(7, 15), | ||
|
@@ -4862,7 +4910,35 @@ public sealed class AsyncEnumerator : System.IAsyncDisposable | |
// await foreach (var i in new C()) | ||
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "foreach").WithArguments("C.AsyncEnumerator.Current").WithLocation(7, 15) | ||
); | ||
// Note: Obsolete on DisposeAsync is not reported since always called through IAsyncDisposable interface | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the comment was incorrect - we do not go through IAsyncDisposable interface? #Resolved There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this was changed in PR but this comment in test was missed |
||
} | ||
|
||
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/30257")] | ||
public void TestWithPatternAndObsolete_WithExplicitInterfaceImplementation() | ||
{ | ||
string source = @" | ||
using System.Threading.Tasks; | ||
class C | ||
{ | ||
static async System.Threading.Tasks.Task Main() | ||
{ | ||
await foreach (var i in new C()) | ||
{ | ||
} | ||
} | ||
public AsyncEnumerator GetAsyncEnumerator(System.Threading.CancellationToken token = default) | ||
{ | ||
throw null; | ||
} | ||
public sealed class AsyncEnumerator : System.IAsyncDisposable | ||
{ | ||
public int Current { get => throw null; } | ||
public Task<bool> MoveNextAsync() => throw null; | ||
[System.Obsolete] | ||
ValueTask System.IAsyncDisposable.DisposeAsync() => throw null; | ||
} | ||
}"; | ||
var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); | ||
comp.VerifyEmitDiagnostics(); | ||
} | ||
|
||
[Fact] | ||
|
@@ -8495,6 +8571,9 @@ public static class Extensions | |
}"; | ||
var comp = CreateCompilationWithMscorlib46(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9); | ||
comp.VerifyDiagnostics( | ||
// (8,15): warning CS0612: 'C.Enumerator.DisposeAsync()' is obsolete | ||
// await foreach (var i in new C()) | ||
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "foreach").WithArguments("C.Enumerator.DisposeAsync()").WithLocation(8, 15), | ||
// (8,15): warning CS0612: 'Extensions.GetAsyncEnumerator(C)' is obsolete | ||
// await foreach (var i in new C()) | ||
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "foreach").WithArguments("Extensions.GetAsyncEnumerator(C)").WithLocation(8, 15), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am curious what effect this is going to have on collection expressions and params collections. Is this diagnostics going to be meaningful for them? Consider adding tests. #Closed