Add Analyzer rule to prohibit `typeof(T).ToString()`
This commit is contained in:
parent
f3f90a4cd5
commit
a2fef59fe1
|
@ -22,6 +22,12 @@
|
|||
<!-- Don't call this.GetType(), use typeof operator (or replace subtype check with better encapsulation) -->
|
||||
<Rule Id="BHI1101" Action="Error" />
|
||||
|
||||
<!-- Don't call typeof(T).Name, use nameof operator -->
|
||||
<Rule Id="BHI1102" Action="Error" />
|
||||
|
||||
<!-- Don't call typeof(T).ToString(), use nameof operator or typeof(T).FullName -->
|
||||
<Rule Id="BHI1103" Action="Error" />
|
||||
|
||||
<!-- Throw NotImplementedException from methods/props marked [FeatureNotImplemented] -->
|
||||
<Rule Id="BHI3300" Action="Error" />
|
||||
</Rules>
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
namespace BizHawk.Analyzers;
|
||||
|
||||
using System.Collections.Immutable;
|
||||
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
|
||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||
public sealed class UseNameofOperatorAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
private static readonly DiagnosticDescriptor DiagNoToStringOnType = new(
|
||||
id: "BHI1103",
|
||||
title: "Don't call typeof(T).ToString(), use nameof operator or typeof(T).FullName",
|
||||
messageFormat: "Replace typeof({0}){1} with either nameof({0}) or typeof({0}).FullName",
|
||||
category: "Usage",
|
||||
defaultSeverity: DiagnosticSeverity.Warning,
|
||||
isEnabledByDefault: true);
|
||||
|
||||
private static readonly DiagnosticDescriptor DiagUseNameof = new(
|
||||
id: "BHI1102",
|
||||
title: "Don't call typeof(T).Name, use nameof operator",
|
||||
messageFormat: "Replace typeof({0}).Name with nameof({0})",
|
||||
category: "Usage",
|
||||
defaultSeverity: DiagnosticSeverity.Error,
|
||||
isEnabledByDefault: true);
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(DiagNoToStringOnType, DiagUseNameof);
|
||||
|
||||
public override void Initialize(AnalysisContext context)
|
||||
{
|
||||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
||||
context.EnableConcurrentExecution();
|
||||
ISymbol? memberInfoDotNameSym = null;
|
||||
ISymbol? typeDotToStringSym = null;
|
||||
context.RegisterSyntaxNodeAction(
|
||||
snac =>
|
||||
{
|
||||
memberInfoDotNameSym ??= snac.Compilation.GetTypeByMetadataName("System.Reflection.MemberInfo")!.GetMembers("Name")[0];
|
||||
typeDotToStringSym ??= snac.Compilation.GetTypeByMetadataName("System.Type")!.GetMembers("ToString")[0];
|
||||
var toes = (TypeOfExpressionSyntax) snac.Node;
|
||||
switch (toes.Parent)
|
||||
{
|
||||
case BinaryExpressionSyntax bes:
|
||||
if ((ReferenceEquals(toes, bes.Left) ? bes.Right : bes.Left) is LiteralExpressionSyntax { Token.RawKind: (int) SyntaxKind.StringLiteralToken })
|
||||
{
|
||||
snac.ReportDiagnostic(Diagnostic.Create(DiagNoToStringOnType, toes.GetLocation(), toes.Type.GetText(), " in string concatenation"));
|
||||
}
|
||||
break;
|
||||
case InterpolationSyntax:
|
||||
snac.ReportDiagnostic(Diagnostic.Create(DiagNoToStringOnType, toes.GetLocation(), toes.Type.GetText(), " in string interpolation"));
|
||||
break;
|
||||
case MemberAccessExpressionSyntax maes1:
|
||||
var accessed = snac.SemanticModel.GetSymbolInfo(maes1.Name).Symbol;
|
||||
if (memberInfoDotNameSym.Matches(accessed))
|
||||
{
|
||||
snac.ReportDiagnostic(Diagnostic.Create(DiagUseNameof, maes1.GetLocation(), toes.Type.GetText()));
|
||||
}
|
||||
else if (typeDotToStringSym.Matches(accessed))
|
||||
{
|
||||
snac.ReportDiagnostic(Diagnostic.Create(DiagNoToStringOnType, maes1.GetLocation(), toes.Type.GetText(), ".ToString()"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
SyntaxKind.TypeOfExpression);
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -131,7 +131,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
if (newTool is Form form) form.Owner = _owner;
|
||||
ServiceInjector.UpdateServices(_emulator.ServiceProvider, newTool);
|
||||
SetBaseProperties(newTool);
|
||||
var toolTypeName = typeof(T).ToString();
|
||||
var toolTypeName = typeof(T).FullName!;
|
||||
// auto settings
|
||||
if (newTool is IToolFormAutoConfig autoConfigTool)
|
||||
{
|
||||
|
|
|
@ -347,9 +347,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
|
|||
catch (Exception ex)
|
||||
{
|
||||
// exception during operation
|
||||
var e = ex;
|
||||
throw new Exception(typeof(DatacorderDevice).ToString() +
|
||||
"\n\nTape image file has a valid CDT header, but threw an exception whilst data was being parsed.\n\n" + e.ToString());
|
||||
throw new Exception($"{nameof(DatacorderDevice)}\n\nTape image file has a valid CDT header, but threw an exception whilst data was being parsed.\n\n{ex}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -775,8 +775,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
|
|||
|
||||
if (!found)
|
||||
{
|
||||
throw new Exception(typeof(DriveState).ToString() +
|
||||
"\n\nDisk image file could not be parsed. Potentially an unknown format.");
|
||||
throw new Exception($"{nameof(DriveState)}\n\nDisk image file could not be parsed. Potentially an unknown format.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,34 +24,25 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
|
|||
/// </summary>
|
||||
public virtual bool IsWriter => false;
|
||||
|
||||
protected abstract Type SelfType { get; }
|
||||
protected abstract string SelfTypeName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Serialization method
|
||||
/// </summary>
|
||||
public virtual void Read(byte[] data)
|
||||
{
|
||||
throw new NotImplementedException(SelfType +
|
||||
"Read operation is not implemented for this converter");
|
||||
}
|
||||
=> throw new NotImplementedException($"Read operation is not implemented for {SelfTypeName}");
|
||||
|
||||
/// <summary>
|
||||
/// DeSerialization method
|
||||
/// </summary>
|
||||
public virtual void Write(byte[] data)
|
||||
{
|
||||
throw new NotImplementedException(SelfType +
|
||||
"Write operation is not implemented for this converter");
|
||||
}
|
||||
=> throw new NotImplementedException($"Write operation is not implemented for {SelfTypeName}");
|
||||
|
||||
/// <summary>
|
||||
/// Serializer does a quick check, returns TRUE if file is detected as this type
|
||||
/// </summary>
|
||||
public virtual bool CheckType(byte[] data)
|
||||
{
|
||||
throw new NotImplementedException(SelfType.ToString() +
|
||||
"Check type operation is not implemented for this converter");
|
||||
}
|
||||
=> throw new NotImplementedException($"Check type operation is not implemented for {SelfTypeName}");
|
||||
|
||||
/// <summary>
|
||||
/// Converts an int32 value into a byte array
|
||||
|
|
|
@ -26,8 +26,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
|
|||
/// </summary>
|
||||
public override bool IsWriter => false;
|
||||
|
||||
protected override Type SelfType
|
||||
=> typeof(CdtConverter);
|
||||
protected override string SelfTypeName
|
||||
=> nameof(CdtConverter);
|
||||
|
||||
/// <summary>
|
||||
/// Working list of generated tape data blocks
|
||||
|
@ -167,8 +167,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
|
|||
if (ident != "ZXTape!" || eotm != 0x1A)
|
||||
{
|
||||
// this is not a valid TZX format file
|
||||
throw new Exception(typeof(CdtConverter) +
|
||||
"This is not a valid TZX format file");
|
||||
throw new Exception($"{nameof(CdtConverter)}: This is not a valid TZX format file");
|
||||
}
|
||||
|
||||
// iterate through each block
|
||||
|
|
|
@ -311,9 +311,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
catch (Exception ex)
|
||||
{
|
||||
// exception during operation
|
||||
var e = ex;
|
||||
throw new Exception(typeof(DatacorderDevice).ToString() +
|
||||
"\n\nTape image file has a valid TZX header, but threw an exception whilst data was being parsed.\n\n" + e.ToString());
|
||||
throw new Exception($"{nameof(DatacorderDevice)}\n\nTape image file has a valid TZX header, but threw an exception whilst data was being parsed.\n\n{ex}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,9 +329,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
catch (Exception ex)
|
||||
{
|
||||
// exception during operation
|
||||
var e = ex;
|
||||
throw new Exception(typeof(DatacorderDevice).ToString() +
|
||||
"\n\nTape image file has a valid PZX header, but threw an exception whilst data was being parsed.\n\n" + e.ToString());
|
||||
throw new Exception($"{nameof(DatacorderDevice)}\n\nTape image file has a valid PZX header, but threw an exception whilst data was being parsed.\n\n{ex}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,9 +347,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
catch (Exception ex)
|
||||
{
|
||||
// exception during operation
|
||||
var e = ex;
|
||||
throw new Exception(typeof(DatacorderDevice).ToString() +
|
||||
"\n\nTape image file has a valid CSW header, but threw an exception whilst data was being parsed.\n\n" + e.ToString());
|
||||
throw new Exception($"{nameof(DatacorderDevice)}\n\nTape image file has a valid CSW header, but threw an exception whilst data was being parsed.\n\n{ex}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,9 +365,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
catch (Exception ex)
|
||||
{
|
||||
// exception during operation
|
||||
var e = ex;
|
||||
throw new Exception(typeof(DatacorderDevice).ToString() +
|
||||
"\n\nTape image file has a valid WAV header, but threw an exception whilst data was being parsed.\n\n" + e.ToString());
|
||||
throw new Exception($"{nameof(DatacorderDevice)}\n\nTape image file has a valid WAV header, but threw an exception whilst data was being parsed.\n\n{ex}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -390,9 +382,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
catch (Exception ex)
|
||||
{
|
||||
// exception during operation
|
||||
var e = ex;
|
||||
throw new Exception(typeof(DatacorderDevice).ToString() +
|
||||
"\n\nAn exception was thrown whilst data from this tape image was being parsed as TAP.\n\n" + e.ToString());
|
||||
throw new Exception($"{nameof(DatacorderDevice)}\n\nAn exception was thrown whilst data from this tape image was being parsed as TAP.\n\n{ex}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -776,8 +776,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
|
||||
if (!found)
|
||||
{
|
||||
throw new Exception(typeof(DriveState).ToString() +
|
||||
"\n\nDisk image file could not be parsed. Potentially an unknown format.");
|
||||
throw new Exception($"{nameof(DriveState)}\n\nDisk image file could not be parsed. Potentially an unknown format.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,34 +26,25 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// </summary>
|
||||
public virtual bool IsWriter => false;
|
||||
|
||||
protected abstract Type SelfType { get; }
|
||||
protected abstract string SelfTypeName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Serialization method
|
||||
/// </summary>
|
||||
public virtual void Read(byte[] data)
|
||||
{
|
||||
throw new NotImplementedException(SelfType.ToString() +
|
||||
"Read operation is not implemented for this converter");
|
||||
}
|
||||
=> throw new NotImplementedException($"Read operation is not implemented for {SelfTypeName}");
|
||||
|
||||
/// <summary>
|
||||
/// DeSerialization method
|
||||
/// </summary>
|
||||
public virtual void Write(byte[] data)
|
||||
{
|
||||
throw new NotImplementedException(SelfType.ToString() +
|
||||
"Write operation is not implemented for this converter");
|
||||
}
|
||||
=> throw new NotImplementedException($"Write operation is not implemented for {SelfTypeName}");
|
||||
|
||||
/// <summary>
|
||||
/// Serializer does a quick check, returns TRUE if file is detected as this type
|
||||
/// </summary>
|
||||
public virtual bool CheckType(byte[] data)
|
||||
{
|
||||
throw new NotImplementedException(SelfType.ToString() +
|
||||
"Check type operation is not implemented for this converter");
|
||||
}
|
||||
=> throw new NotImplementedException($"Check type operation is not implemented for {SelfTypeName}");
|
||||
|
||||
/// <summary>
|
||||
/// Converts an int32 value into a byte array
|
||||
|
|
|
@ -32,8 +32,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// </summary>
|
||||
public override bool IsWriter => false;
|
||||
|
||||
protected override Type SelfType
|
||||
=> typeof(CswConverter);
|
||||
protected override string SelfTypeName
|
||||
=> nameof(CswConverter);
|
||||
|
||||
private readonly DatacorderDevice _datacorder;
|
||||
|
||||
|
@ -83,15 +83,13 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
if (ident.ToUpper() != "COMPRESSED SQUARE WAVE")
|
||||
{
|
||||
// this is not a valid CSW format file
|
||||
throw new Exception(typeof(CswConverter).ToString() +
|
||||
"This is not a valid CSW format file");
|
||||
throw new Exception($"{nameof(CswConverter)}: This is not a valid CSW format file");
|
||||
}
|
||||
|
||||
if (data[0x16] != 0x1a)
|
||||
{
|
||||
// invalid terminator code
|
||||
throw new Exception(typeof(CswConverter).ToString() +
|
||||
"This image reports as a CSW but has an invalid terminator code");
|
||||
throw new Exception($"{nameof(CswConverter)}: This image reports as a CSW but has an invalid terminator code");
|
||||
}
|
||||
|
||||
_position = 0;
|
||||
|
@ -185,13 +183,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
if (compressionType == 1)
|
||||
Array.Copy(data, _position, cswDataUncompressed, 0, cswDataUncompressed.Length);
|
||||
else
|
||||
throw new Exception(typeof(CswConverter).ToString() +
|
||||
"CSW Format unknown compression type");
|
||||
throw new Exception($"{nameof(CswConverter)}: CSW Format unknown compression type");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(typeof(CswConverter).ToString() +
|
||||
"CSW Format Version " + majorVer + "." + minorVer + " is not currently supported");
|
||||
throw new Exception($"{nameof(CswConverter)}: CSW Format Version {majorVer}.{minorVer} is not currently supported");
|
||||
}
|
||||
|
||||
// create the single tape block
|
||||
|
|
|
@ -27,8 +27,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// </summary>
|
||||
public override bool IsWriter => false;
|
||||
|
||||
protected override Type SelfType
|
||||
=> typeof(PzxConverter);
|
||||
protected override string SelfTypeName
|
||||
=> nameof(PzxConverter);
|
||||
|
||||
/// <summary>
|
||||
/// Working list of generated tape data blocks
|
||||
|
@ -99,8 +99,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
if (ident.ToUpper() != "PZXT")
|
||||
{
|
||||
// this is not a valid TZX format file
|
||||
throw new Exception(typeof(PzxConverter).ToString() +
|
||||
"This is not a valid PZX format file");
|
||||
throw new Exception($"{nameof(PzxConverter)}: This is not a valid PZX format file");
|
||||
}
|
||||
|
||||
_position = 0;
|
||||
|
|
|
@ -27,8 +27,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// </summary>
|
||||
public override bool IsWriter => false;
|
||||
|
||||
protected override Type SelfType
|
||||
=> typeof(TapConverter);
|
||||
protected override string SelfTypeName
|
||||
=> nameof(TapConverter);
|
||||
|
||||
private readonly DatacorderDevice _datacorder;
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// </summary>
|
||||
public override bool IsWriter => false;
|
||||
|
||||
protected override Type SelfType
|
||||
=> typeof(TzxConverter);
|
||||
protected override string SelfTypeName
|
||||
=> nameof(TzxConverter);
|
||||
|
||||
/// <summary>
|
||||
/// Working list of generated tape data blocks
|
||||
|
@ -205,8 +205,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
if (ident != "ZXTape!" || eotm != 0x1A)
|
||||
{
|
||||
// this is not a valid TZX format file
|
||||
throw new Exception(typeof(TzxConverter) +
|
||||
"This is not a valid TZX format file");
|
||||
throw new Exception($"{nameof(TzxConverter)}: This is not a valid TZX format file");
|
||||
}
|
||||
|
||||
// iterate through each block
|
||||
|
|
|
@ -28,8 +28,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// </summary>
|
||||
public override bool IsWriter => false;
|
||||
|
||||
protected override Type SelfType
|
||||
=> typeof(WavConverter);
|
||||
protected override string SelfTypeName
|
||||
=> nameof(WavConverter);
|
||||
|
||||
/// <summary>
|
||||
/// Position counter
|
||||
|
@ -77,8 +77,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
if (ident.ToUpper() != "WAVE")
|
||||
{
|
||||
// this is not a valid TZX format file
|
||||
throw new Exception(typeof(WavConverter).ToString() +
|
||||
"This is not a valid WAV format file");
|
||||
throw new Exception($"{nameof(WavConverter)}: This is not a valid WAV format file");
|
||||
}
|
||||
|
||||
//_position = 0;
|
||||
|
|
|
@ -293,7 +293,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
|||
private void CheckDisposed()
|
||||
{
|
||||
if (Context == IntPtr.Zero)
|
||||
throw new ObjectDisposedException(typeof(QuickNES).Name);
|
||||
throw new ObjectDisposedException(nameof(QuickNES));
|
||||
}
|
||||
|
||||
// Fix some incorrect ines header entries that QuickNES uses to load games.
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
public void SaveState(int statenum)
|
||||
{
|
||||
if (disposed) throw new ObjectDisposedException(typeof(GenDbgHlp).ToString());
|
||||
if (disposed) throw new ObjectDisposedException(nameof(GenDbgHlp));
|
||||
|
||||
data[statenum] ??= new byte[length];
|
||||
|
||||
|
@ -60,7 +60,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
public unsafe void Cmp(int statex, int statey)
|
||||
{
|
||||
if (disposed) throw new ObjectDisposedException(typeof(GenDbgHlp).ToString());
|
||||
if (disposed) throw new ObjectDisposedException(nameof(GenDbgHlp));
|
||||
List<Tuple<int, int>> bads = new List<Tuple<int, int>>();
|
||||
|
||||
byte[] x = data[statex];
|
||||
|
@ -134,7 +134,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
public List<Symbol> Find(IntPtr addr, int length)
|
||||
{
|
||||
if (disposed) throw new ObjectDisposedException(typeof(GenDbgHlp).ToString());
|
||||
if (disposed) throw new ObjectDisposedException(nameof(GenDbgHlp));
|
||||
Symbol min = new Symbol { addr = addr };
|
||||
Symbol max = new Symbol { addr = addr + length };
|
||||
|
||||
|
|
Loading…
Reference in New Issue