diff --git a/src/Analyzers/MSTest.Analyzers/PreferTestCleanupOverDisposeAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/PreferTestCleanupOverDisposeAnalyzer.cs index 1e22fec61a..b63e66970d 100644 --- a/src/Analyzers/MSTest.Analyzers/PreferTestCleanupOverDisposeAnalyzer.cs +++ b/src/Analyzers/MSTest.Analyzers/PreferTestCleanupOverDisposeAnalyzer.cs @@ -40,22 +40,28 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(context => { - if (context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable, out INamedTypeSymbol? idisposableSymbol)) + if (context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable, out INamedTypeSymbol? idisposableSymbol) && + context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingTestClassAttribute, out INamedTypeSymbol? testClassAttributeSymbol)) { INamedTypeSymbol? iasyncDisposableSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIAsyncDisposable); INamedTypeSymbol? valueTaskSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksValueTask); - context.RegisterSymbolAction(context => AnalyzeSymbol(context, idisposableSymbol, iasyncDisposableSymbol, valueTaskSymbol), SymbolKind.Method); + context.RegisterSymbolAction(context => AnalyzeSymbol(context, testClassAttributeSymbol, idisposableSymbol, iasyncDisposableSymbol, valueTaskSymbol), SymbolKind.Method); } }); } - private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol idisposableSymbol, INamedTypeSymbol? iasyncDisposableSymbol, + private static void AnalyzeSymbol( + SymbolAnalysisContext context, + INamedTypeSymbol testClassAttributeSymbol, + INamedTypeSymbol idisposableSymbol, + INamedTypeSymbol? iasyncDisposableSymbol, INamedTypeSymbol? valueTaskSymbol) { var methodSymbol = (IMethodSymbol)context.Symbol; - if (methodSymbol.IsAsyncDisposeImplementation(iasyncDisposableSymbol, valueTaskSymbol) - || methodSymbol.IsDisposeImplementation(idisposableSymbol)) + if (methodSymbol.ContainingType.GetAttributes().Any(x => x.AttributeClass.Inherits(testClassAttributeSymbol)) && + (methodSymbol.IsAsyncDisposeImplementation(iasyncDisposableSymbol, valueTaskSymbol) + || methodSymbol.IsDisposeImplementation(idisposableSymbol))) { context.ReportDiagnostic(methodSymbol.CreateDiagnostic(Rule)); } diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/PreferTestCleanupOverDisposeAnalyzerTests.cs b/test/UnitTests/MSTest.Analyzers.UnitTests/PreferTestCleanupOverDisposeAnalyzerTests.cs index 6681623645..fcee06522e 100644 --- a/test/UnitTests/MSTest.Analyzers.UnitTests/PreferTestCleanupOverDisposeAnalyzerTests.cs +++ b/test/UnitTests/MSTest.Analyzers.UnitTests/PreferTestCleanupOverDisposeAnalyzerTests.cs @@ -10,6 +10,24 @@ namespace MSTest.Analyzers.Test; [TestClass] public sealed class PreferTestCleanupOverDisposeAnalyzerTests { + [TestMethod] + public async Task WhenNonTestClassHasDispose_NoDiagnostic() + { + string code = """ + using System; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + public class MyNonTestClass : IDisposable + { + public void Dispose() + { + } + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, code); + } + [TestMethod] public async Task WhenTestClassHasDispose_Diagnostic() {