Skip to content

Commit 790bef2

Browse files
committed
alternative implementation, as well as an additional test for VB
1 parent f6fc3b0 commit 790bef2

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DisposableFieldsShouldBeDisposedTests.cs

+39
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,45 @@ function DisposeAsync() as ValueTask implements IAsyncDisposable.DisposeAsync
727727
return stream.DisposeAsync()
728728
end function
729729
end class
730+
"
731+
}.RunAsync();
732+
733+
await new VerifyVB.Test
734+
{
735+
ReferenceAssemblies = AdditionalMetadataReferences.DefaultWithAsyncInterfaces,
736+
TestCode = @"
737+
Imports System
738+
Imports System.IO
739+
Imports System.Net.Http
740+
Imports System.Threading.Tasks
741+
742+
class FileStream2
743+
implements IAsyncDisposable
744+
public function DisposeAsync() as ValueTask implements IAsyncDisposable.DisposeAsync
745+
return nothing
746+
end function
747+
end class
748+
749+
public class Test
750+
implements IAsyncDisposable, IDisposable
751+
752+
private readonly client as HttpClient
753+
private readonly stream as FileStream2
754+
755+
public sub new()
756+
client = new HttpClient
757+
stream = new FileStream2
758+
end sub
759+
760+
public sub Dispose() implements IDisposable.Dispose
761+
client.Dispose()
762+
end sub
763+
764+
rem arbitrary implementation name
765+
function DisposeOtherAsync() as ValueTask implements IAsyncDisposable.DisposeAsync
766+
return stream.DisposeAsync()
767+
end function
768+
end class
730769
"
731770
}.RunAsync();
732771
}

src/Utilities/Compiler/Extensions/IMethodSymbolExtensions.cs

+7-14
Original file line numberDiff line numberDiff line change
@@ -219,19 +219,12 @@ public static bool IsAsyncDisposeImplementation([NotNullWhen(returnValue: true)]
219219
method.IsImplementationOfInterfaceMethod(null, iAsyncDisposable, "DisposeAsync");
220220
}
221221

222-
/// <summary>
223-
/// Checks the name of the method of an implicit interface implementation (so, as is) or an explicit interface implementation (which also contains the interface as a prefix).
224-
/// </summary>
225-
private static bool IsImplicitOrExplicitInterfaceImplementationName(this IMethodSymbol method, string name, string interfacePrefix)
226-
=> (method.Name == name && method.MethodKind is MethodKind.Ordinary) ||
227-
(method.Name == $"{interfacePrefix}.{name}" && method.MethodKind is MethodKind.ExplicitInterfaceImplementation);
228-
229222
/// <summary>
230223
/// Checks if the given method has the signature "void Dispose()".
231224
/// </summary>
232225
private static bool HasDisposeMethodSignature(this IMethodSymbol method)
233226
{
234-
return method.IsImplicitOrExplicitInterfaceImplementationName("Dispose", "System.IDisposable") &&
227+
return method.Name == "Dispose" && method.MethodKind == MethodKind.Ordinary &&
235228
method.ReturnsVoid && method.Parameters.IsEmpty;
236229
}
237230

@@ -250,7 +243,7 @@ public static bool HasDisposeSignatureByConvention(this IMethodSymbol method)
250243
/// </summary>
251244
public static bool HasDisposeBoolMethodSignature(this IMethodSymbol method)
252245
{
253-
if (method.IsImplicitOrExplicitInterfaceImplementationName("Dispose", "System.IDisposable") &&
246+
if (method.Name == "Dispose" && method.MethodKind == MethodKind.Ordinary &&
254247
method.ReturnsVoid && method.Parameters.Length == 1)
255248
{
256249
IParameterSymbol parameter = method.Parameters[0];
@@ -267,8 +260,7 @@ public static bool HasDisposeBoolMethodSignature(this IMethodSymbol method)
267260
/// </summary>
268261
private static bool HasDisposeCloseMethodSignature(this IMethodSymbol method)
269262
{
270-
return method.Name == "Close" &&
271-
method.MethodKind is MethodKind.Ordinary &&
263+
return method.Name == "Close" && method.MethodKind == MethodKind.Ordinary &&
272264
method.ReturnsVoid && method.Parameters.IsEmpty;
273265
}
274266

@@ -286,7 +278,8 @@ private static bool HasDisposeAsyncMethodSignature(this IMethodSymbol method,
286278
INamedTypeSymbol? task,
287279
INamedTypeSymbol? valueTask)
288280
{
289-
return method.IsImplicitOrExplicitInterfaceImplementationName("DisposeAsync", "System.IAsyncDisposable") &&
281+
return method.Name == "DisposeAsync" &&
282+
method.MethodKind == MethodKind.Ordinary &&
290283
method.Parameters.IsEmpty &&
291284
(SymbolEqualityComparer.Default.Equals(method.ReturnType, task) ||
292285
SymbolEqualityComparer.Default.Equals(method.ReturnType, valueTask));
@@ -298,7 +291,7 @@ private static bool HasDisposeAsyncMethodSignature(this IMethodSymbol method,
298291
private static bool HasOverriddenDisposeCoreAsyncMethodSignature(this IMethodSymbol method, [NotNullWhen(returnValue: true)] INamedTypeSymbol? task)
299292
{
300293
return method.Name == "DisposeCoreAsync" &&
301-
method.MethodKind is MethodKind.Ordinary &&
294+
method.MethodKind == MethodKind.Ordinary &&
302295
method.IsOverride &&
303296
SymbolEqualityComparer.Default.Equals(method.ReturnType, task) &&
304297
method.Parameters.Length == 1 &&
@@ -344,7 +337,7 @@ public static DisposeMethodKind GetDisposeMethodKind(
344337
{
345338
return DisposeMethodKind.DisposeBool;
346339
}
347-
else if (method.HasDisposeAsyncMethodSignature(task, valueTask))
340+
else if (method.IsAsyncDisposeImplementation(iAsyncDisposable, valueTask) || method.HasDisposeAsyncMethodSignature(task, valueTask))
348341
{
349342
return DisposeMethodKind.DisposeAsync;
350343
}

0 commit comments

Comments
 (0)