Skip to content

Commit

Permalink
New rule (disabled by default) to detect async void methods
Browse files Browse the repository at this point in the history
  • Loading branch information
meziantou committed Apr 18, 2024
1 parent 571aeb4 commit 3f9828d
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 2 deletions.
3 changes: 2 additions & 1 deletion README.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ If you are already using other analyzers, you can check [which rules are duplica
|[MA0151](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0151.md)|Usage|DebuggerDisplay must contain valid members|⚠️|✔️||
|[MA0152](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0152.md)|Performance|Use Unwrap instead of using await twice|ℹ️|✔️||
|[MA0153](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0153.md)|Design|Do not log symbols decorated with DataClassificationAttribute directly|⚠️|✔️||
|[MA0154](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0154.md)|Design|Use langword in XML comment|ℹ️|✔️||
|[MA0154](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0154.md)|Design|Use langword in XML comment|ℹ️|✔️|✔️|
|[MA0155](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0155.md)|Design|Do not use async void methods|⚠️|||

<!-- rules -->

Expand Down
9 changes: 8 additions & 1 deletion docs/README.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@
|[MA0151](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0151.md)|Usage|DebuggerDisplay must contain valid members|<span title='Warning'>⚠️</span>|✔️||
|[MA0152](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0152.md)|Performance|Use Unwrap instead of using await twice|<span title='Info'>ℹ️</span>|✔️||
|[MA0153](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0153.md)|Design|Do not log symbols decorated with DataClassificationAttribute directly|<span title='Warning'>⚠️</span>|✔️||
|[MA0154](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0154.md)|Design|Use langword in XML comment|<span title='Info'>ℹ️</span>|✔️||
|[MA0154](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0154.md)|Design|Use langword in XML comment|<span title='Info'>ℹ️</span>|✔️|✔️|
|[MA0155](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0155.md)|Design|Do not use async void methods|<span title='Warning'>⚠️</span>|||

|Id|Suppressed rule|Justification|
|--|---------------|-------------|
Expand Down Expand Up @@ -622,6 +623,9 @@ dotnet_diagnostic.MA0153.severity = warning
# MA0154: Use langword in XML comment
dotnet_diagnostic.MA0154.severity = suggestion
# MA0155: Do not use async void methods
dotnet_diagnostic.MA0155.severity = none
```

# .editorconfig - all rules disabled
Expand Down Expand Up @@ -1085,4 +1089,7 @@ dotnet_diagnostic.MA0153.severity = none
# MA0154: Use langword in XML comment
dotnet_diagnostic.MA0154.severity = none
# MA0155: Do not use async void methods
dotnet_diagnostic.MA0155.severity = none
```
15 changes: 15 additions & 0 deletions docs/Rules/MA0155.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# MA0155 - Do not use async void methods

```c#
// not-compliant
async void SomeMethod()
{
await Task.Delay(1000);
}

// ok
async Task SomeMethod()
{
await Task.Delay(1000);
}
```
38 changes: 38 additions & 0 deletions src/Meziantou.Analyzer/Rules/DoNotUseAsyncVoidAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;

namespace Meziantou.Analyzer.Rules;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class DoNotUseAsyncVoidAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor Rule = new(
RuleIdentifiers.DoNotUseAsyncVoid,
title: "Do not use async void methods",
messageFormat: "Do not use async void methods",
RuleCategories.Design,
DiagnosticSeverity.Warning,
isEnabledByDefault: false,
description: "",
helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.DoNotUseAsyncVoid));

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);

public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.Method);
}

private static void AnalyzeSymbol(SymbolAnalysisContext context)
{
var symbol = (IMethodSymbol)context.Symbol;
if (symbol is { ReturnsVoid: true, IsAsync: true })
{
context.ReportDiagnostic(Rule, symbol);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Threading.Tasks;
using Meziantou.Analyzer.Rules;
using TestHelper;
using Xunit;

namespace Meziantou.Analyzer.Test.Rules;
public sealed class DoNotUseAsyncVoidAnalyzerTests
{
private static ProjectBuilder CreateProjectBuilder()
{
return new ProjectBuilder()
.WithAnalyzer<DoNotUseAsyncVoidAnalyzer>()
.WithTargetFramework(TargetFramework.Net8_0);
}

[Fact]
public async Task Method_Void()
{
await CreateProjectBuilder()
.WithSourceCode("""
class Sample
{
void A() => throw null;
}
""")
.ValidateAsync();
}

[Fact]
public async Task Method_AsyncVoid()
{
await CreateProjectBuilder()
.WithSourceCode("""
class Sample
{
async void [|A|]() => throw null;
}
""")
.ValidateAsync();
}

[Fact]
public async Task Method_AsyncTask()
{
await CreateProjectBuilder()
.WithSourceCode("""
class Sample
{
async System.Threading.Tasks.Task A() => throw null;
}
""")
.ValidateAsync();
}

}

0 comments on commit 3f9828d

Please sign in to comment.