Skip to content

Commit

Permalink
Add Analyzer (currently disabled) for target-typed new with throw
Browse files Browse the repository at this point in the history
  • Loading branch information
YoshiRulz committed Jul 8, 2024
1 parent 53fcb93 commit 5fd840e
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .global.editorconfig.ini
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ dotnet_diagnostic.BHI1004.severity = error
dotnet_diagnostic.BHI1005.severity = error
# Do not discard local variables
dotnet_diagnostic.BHI1006.severity = error
# Don't use target-typed new for throw expressions
dotnet_diagnostic.BHI1007.severity = suggestion
# Don't call this.GetType() in sealed type, use typeof operator
dotnet_diagnostic.BHI1100.severity = error
# Don't call this.GetType(), use typeof operator (or replace subtype check with better encapsulation)
Expand Down
58 changes: 58 additions & 0 deletions ExternalProjects/BizHawk.Analyzer/NoTargetTypedThrowAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
namespace BizHawk.Analyzers;

using System.Collections.Immutable;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class NoTargetTypedThrowAnalyzer : DiagnosticAnalyzer
{
private const string ERR_MSG_IMPLICIT = "Specify `Exception` (or a more precise type) explicitly";

private static readonly DiagnosticDescriptor DiagNoTargetTypedThrow = new(
id: "BHI1007",
title: "Don't use target-typed new for throw expressions",
messageFormat: "{0}",
category: "Usage",
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(DiagNoTargetTypedThrow);

public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterOperationAction(
oac =>
{
var exceptionOp = ((IThrowOperation) oac.Operation).Exception;
if (exceptionOp is null) return; // re-`throw;`
void Fail(string message)
=> oac.ReportDiagnostic(Diagnostic.Create(DiagNoTargetTypedThrow, exceptionOp.Syntax.GetLocation(), message));
switch (exceptionOp.Kind)
{
case OperationKind.ObjectCreation:
case OperationKind.Invocation:
case OperationKind.PropertyReference:
case OperationKind.LocalReference:
return;
case OperationKind.Conversion:
if (((IConversionOperation) exceptionOp).Operand.Syntax
.IsKind(SyntaxKind.ImplicitObjectCreationExpression))
{
break;
}
return;
default:
Fail($"Argument to throw expression was of an unexpected kind: {exceptionOp.GetType().FullName}");
return;
}
Fail(ERR_MSG_IMPLICIT);
},
OperationKind.Throw);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace BizHawk.Tests.Analyzers;

using System.Threading.Tasks;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Verify = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier<
BizHawk.Analyzers.NoTargetTypedThrowAnalyzer,
Microsoft.CodeAnalysis.Testing.DefaultVerifier>;

[TestClass]
public sealed class NoTargetTypedThrowAnalyzerTests
{
[TestMethod]
public Task CheckMisuseOfXORAssignment()
=> Verify.VerifyAnalyzerAsync("""
using System;
public static class Cases {
// not present: throwing a local, which is apparently necessary in Win32 interop
private static void V()
=> throw ExceptionHelperProp;
private static void W()
=> throw ExceptionHelperMethod();
private static void X() {
try {
Z();
} catch (Exception) {
throw;
}
}
private static void Y()
=> throw new Exception();
private static void Z()
=> throw new NotImplementedException();
private static void A()
=> throw {|BHI1007:new()|};
private static Exception ExceptionHelperMethod()
=> new();
private static Exception ExceptionHelperProp
=> new();
}
""");
}
Binary file modified References/BizHawk.Analyzer.dll
Binary file not shown.

0 comments on commit 5fd840e

Please sign in to comment.