diff --git a/docs/Rules/MA0137.md b/docs/Rules/MA0137.md index e3e706c55..90df90a4d 100644 --- a/docs/Rules/MA0137.md +++ b/docs/Rules/MA0137.md @@ -12,3 +12,17 @@ Task FooAsync() => Task.CompletedTask; // non-compliant Task Foo() => Task.CompletedTask; ```` + +# Configuration + +By default, test methods (methods decorated with test framework attributes such as `[Fact]`, `[Test]`, `[TestMethod]`, etc.) are excluded from this rule. You can change this behavior using the `.editorconfig` file: + +````editorconfig +MA0137.exclude_test_methods = true # default value +```` + +Set to `false` to also report diagnostics on test methods: + +````editorconfig +MA0137.exclude_test_methods = false +```` diff --git a/src/Meziantou.Analyzer/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzer.cs b/src/Meziantou.Analyzer/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzer.cs index 58b34cc81..f99005465 100644 --- a/src/Meziantou.Analyzer/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzer.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Meziantou.Analyzer.Configurations; using Meziantou.Analyzer.Internals; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; @@ -81,7 +82,7 @@ public void AnalyzeSymbol(SymbolAnalysisContext context) if (method.IsEqualTo(context.Compilation.GetEntryPoint(context.CancellationToken))) return; - if (MustIgnoreSymbol(method)) + if (MustIgnoreSymbol(context.Options, method)) return; var hasAsyncSuffix = method.Name.EndsWith("Async", StringComparison.Ordinal); @@ -145,12 +146,13 @@ public void AnalyzeLocalFunction(OperationAnalysisContext context) } } - private bool MustIgnoreSymbol(IMethodSymbol symbol) + private bool MustIgnoreSymbol(AnalyzerOptions options, IMethodSymbol symbol) { if (symbol.HasAttribute(_benchmarkSymbol)) return true; - if (symbol.IsUnitTestMethod()) + var excludeTestMethods = options.GetConfigurationValue(symbol, "MA0137.exclude_test_methods", defaultValue: true); + if (excludeTestMethods && symbol.IsUnitTestMethod()) return true; return false; diff --git a/tests/Meziantou.Analyzer.Test/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzerTests.cs b/tests/Meziantou.Analyzer.Test/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzerTests.cs index 6dc62d9dd..f2e2cb3f7 100644 --- a/tests/Meziantou.Analyzer.Test/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzerTests.cs +++ b/tests/Meziantou.Analyzer.Test/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzerTests.cs @@ -170,4 +170,32 @@ class TypeName """) .AddXUnitApi() .ValidateAsync(); + + [Fact] + public Task IgnoreTestMethods_ExcludeTestMethodsTrue() + => CreateProjectBuilder() + .WithSourceCode(""" + class TypeName + { + [Xunit.Fact] + System.Threading.Tasks.Task Foo() => throw null; + } + """) + .AddXUnitApi() + .AddAnalyzerConfiguration("MA0137.exclude_test_methods", "true") + .ValidateAsync(); + + [Fact] + public Task IgnoreTestMethods_ExcludeTestMethodsFalse() + => CreateProjectBuilder() + .WithSourceCode(""" + class TypeName + { + [Xunit.Fact] + System.Threading.Tasks.Task {|MA0137:Foo|}() => throw null; + } + """) + .AddXUnitApi() + .AddAnalyzerConfiguration("MA0137.exclude_test_methods", "false") + .ValidateAsync(); }