diff --git a/IDisposableAnalyzers.Test/IDISP010CallBaseDisposeTests/Valid.cs b/IDisposableAnalyzers.Test/IDISP010CallBaseDisposeTests/Valid.cs index ebbdb7f6..75372520 100644 --- a/IDisposableAnalyzers.Test/IDISP010CallBaseDisposeTests/Valid.cs +++ b/IDisposableAnalyzers.Test/IDISP010CallBaseDisposeTests/Valid.cs @@ -236,6 +236,71 @@ protected override void Dispose(bool disposing) RoslynAssert.Valid(Analyzer, DisposableCode, baseClass, code); } + [Test] + public static void WhenBaseDisposeIsAbstract() + { + var baseClass = @" +namespace N +{ + using System; + + public abstract class BaseClass : IDisposable + { + /// + public abstract void Dispose(); + } +}"; + var code = @" +namespace N +{ + using System; + + public class C : BaseClass + { + private readonly IDisposable disposable = new Disposable(); + private bool disposed; + + public override void Dispose() + { + if (this.disposed) + { + return; + } + + this.disposed = true; + this.disposable.Dispose(); + } + } +}"; + + RoslynAssert.Valid(Analyzer, DisposableCode, baseClass, code); + } + + [Test] + public static void WhenBaseDisposeIsAbstractAndExternal() + { + var code = @" +using System; +using System.Buffers; + +sealed class Manager : MemoryManager + { + /// + public override void Unpin() { } + + /// + public override MemoryHandle Pin(int elementIndex = 0) => default; + + /// + public override Span GetSpan() => default; + + /// + protected override void Dispose(bool disposing) { } // <-- lint occurs here + }"; + + RoslynAssert.Valid(Analyzer, code); + } + [Test] public static void WhenNoBaseClass() { diff --git a/IDisposableAnalyzers/Analyzers/DisposeMethodAnalyzer.cs b/IDisposableAnalyzers/Analyzers/DisposeMethodAnalyzer.cs index 6138de9a..3d8c3bc0 100644 --- a/IDisposableAnalyzers/Analyzers/DisposeMethodAnalyzer.cs +++ b/IDisposableAnalyzers/Analyzers/DisposeMethodAnalyzer.cs @@ -112,7 +112,7 @@ private static bool IsInterfaceImplementation(IMethodSymbol method) private static bool ShouldCallBase(SymbolAndDeclaration method, SyntaxNodeAnalysisContext context) { - if (method is { Symbol: { IsOverride: true, OverriddenMethod: { } overridden } } && + if (method is { Symbol: { IsOverride: true, OverriddenMethod: { IsAbstract: false } overridden } } && DisposeMethod.FindBaseCall(method.Declaration, context.SemanticModel, context.CancellationToken) is null) { if (overridden.DeclaringSyntaxReferences.Length == 0)