From fa361ce06ca8e5cd8cb4e755e200e43876299165 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Sat, 14 Sep 2024 02:31:34 +1000 Subject: [PATCH] Add Analyzer for finding errors with ternaries in interpolated strings why is this not part of the SDK --- .global.editorconfig.ini | 3 + .../TernaryInferredTypeMismatchAnalyzer.cs | 89 ++++++++++++++++++ ...ernaryInferredTypeMismatchAnalyzerTests.cs | 34 +++++++ References/BizHawk.Analyzer.dll | Bin 40448 -> 42496 bytes src/BizHawk.Client.EmuHawk/MainForm.cs | 2 +- .../SatellaviewFileTypeDetector.cs | 2 +- .../CPUs/FairchildF8/F3850.Disassembler.cs | 2 +- .../CPUs/Z80A/NewDisassembler.cs | 2 +- 8 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 ExternalProjects/BizHawk.Analyzer/TernaryInferredTypeMismatchAnalyzer.cs create mode 100644 ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/TernaryInferredTypeMismatchAnalyzerTests.cs diff --git a/.global.editorconfig.ini b/.global.editorconfig.ini index 3cada92f05..da5694e99c 100644 --- a/.global.editorconfig.ini +++ b/.global.editorconfig.ini @@ -36,6 +36,9 @@ dotnet_diagnostic.BHI1120.severity = silent # Check result of IDictionary.TryGetValue, or discard it if default(T) is desired dotnet_diagnostic.BHI1200.severity = error +# Inferred type of bramches of ternary expression in interpolation don't match +dotnet_diagnostic.BHI1210.severity = error + # Call to FirstOrDefault when elements are of a value type; FirstOrNull may have been intended dotnet_diagnostic.BHI3100.severity = error # Use .Order()/.OrderDescending() shorthand diff --git a/ExternalProjects/BizHawk.Analyzer/TernaryInferredTypeMismatchAnalyzer.cs b/ExternalProjects/BizHawk.Analyzer/TernaryInferredTypeMismatchAnalyzer.cs new file mode 100644 index 0000000000..435981214f --- /dev/null +++ b/ExternalProjects/BizHawk.Analyzer/TernaryInferredTypeMismatchAnalyzer.cs @@ -0,0 +1,89 @@ +namespace BizHawk.Analyzers; + +using System.Collections.Immutable; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Operations; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class TernaryInferredTypeMismatchAnalyzer : DiagnosticAnalyzer +{ + private static readonly DiagnosticDescriptor DiagTernaryInferredTypeMismatch = new( + id: "BHI1210", + title: "Inferred type of bramches of ternary expression in interpolation don't match", +// messageFormat: "Inferred type of ternary expression is object (missing ToString call?)", + messageFormat: "{0}", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true); + + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagTernaryInferredTypeMismatch); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterCompilationStartAction(initContext => + { + var objectSym = initContext.Compilation.GetTypeByMetadataName("System.Object")!; + var stringSym = initContext.Compilation.GetTypeByMetadataName("System.String")!; + initContext.RegisterOperationAction(oac => + { + var ifelseOrTernaryOp = (IConditionalOperation) oac.Operation; + if (ifelseOrTernaryOp.WhenFalse is null) return; + var parent = ifelseOrTernaryOp.Parent!; + if (parent.Kind is OperationKind.Conversion) parent = parent.Parent!; + if (parent.Kind is not OperationKind.Interpolation) return; + var ternaryOp = ifelseOrTernaryOp; + var typeTernary = ternaryOp.Type!; +#if false // never hit; either both branches are string and there are no conversions, or conversions are necessary + if (stringSym.Matches(typeTernary)) return; +#endif + var lhs = ternaryOp.WhenTrue; + var rhs = ternaryOp.WhenFalse; + + static IOperation TrimImplicitCast(IOperation op) + => op is IConversionOperation { Conversion.IsImplicit: true } implCastOp ? implCastOp.Operand : op; + var typeLHS = TrimImplicitCast(lhs).Type!; + var typeRHS = TrimImplicitCast(rhs).Type!; + if (typeLHS.Matches(typeRHS)) return; // unnecessary conversion operators on each branch? seen with `? this : this` + + const string ERR_MSG_OBJECT = "missing ToString means ternary branches are upcast to object"; + var fatal = false; + IOperation flaggedOp = ternaryOp; + string message; + if (stringSym.Matches(typeLHS)) + { + flaggedOp = rhs; + message = ERR_MSG_OBJECT; + } + else if (stringSym.Matches(typeRHS)) + { + flaggedOp = lhs; + message = ERR_MSG_OBJECT; + } + else if (objectSym.Matches(typeTernary)) + { + fatal = true; + message = "ternary branches are upcast to object! add ToString calls, or convert one to the other's type"; + } + else + { + // if one's already an e.g. int literal, flag the e.g. char literal + if (typeTernary.Matches(typeLHS)) flaggedOp = rhs; + else if (typeTernary.Matches(typeRHS)) flaggedOp = lhs; + message = $"ternary branches are converted to {typeTernary} before serialisation, possibly unintended"; + } + oac.ReportDiagnostic(Diagnostic.Create( + DiagTernaryInferredTypeMismatch, + flaggedOp.Syntax.GetLocation(), + fatal ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning, + additionalLocations: null, + properties: null, + messageArgs: message)); + }, + OperationKind.Conditional); + }); + } +} diff --git a/ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/TernaryInferredTypeMismatchAnalyzerTests.cs b/ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/TernaryInferredTypeMismatchAnalyzerTests.cs new file mode 100644 index 0000000000..f638806fa2 --- /dev/null +++ b/ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/TernaryInferredTypeMismatchAnalyzerTests.cs @@ -0,0 +1,34 @@ +namespace BizHawk.Tests.Analyzers; + +using System.Threading.Tasks; + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using Verify = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier< + BizHawk.Analyzers.TernaryInferredTypeMismatchAnalyzer, + Microsoft.CodeAnalysis.Testing.DefaultVerifier>; + +[TestClass] +public sealed class TernaryInferredTypeMismatchAnalyzerTests +{ + [TestMethod] + public Task CheckMisuseOfTernariesInInterpolations() + => Verify.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System.Diagnostics; + public static class Cases { + private static string X(bool cond) + => $"{(cond ? 'p'.ToString() : 9.ToString())}"; + private static string Y(bool cond) + => $"{(cond ? "p" : 9.ToString())}"; + private static string Z(bool cond) + => $"{(cond ? "p" : "q")}"; + private static string A(bool cond) + => $"{(cond ? "p" : {|BHI1210:9|})}"; + private static string B(bool cond) + => $"{(cond ? {|BHI1210:'p'|} : 9)}"; + private static string C(bool cond, Process p, Queue q) + => $"{({|BHI1210:cond ? p : q|})}"; + } + """); +} diff --git a/References/BizHawk.Analyzer.dll b/References/BizHawk.Analyzer.dll index 600c82f8d9f2ea2b4d07a099bffff3ab60260b7b..5b0f2b86acc31729097f795364b6d483f821c12f 100644 GIT binary patch delta 17297 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 diff --git a/src/BizHawk.Client.EmuHawk/MainForm.cs b/src/BizHawk.Client.EmuHawk/MainForm.cs index 21f53d04ef..4f898e51d1 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.cs @@ -68,7 +68,7 @@ namespace BizHawk.Client.EmuHawk var temp = new ToolStripMenuItemEx { Tag = i, - Text = $"{(quotient > 0 ? quotient : "")}&{remainder}x" + Text = $"{(quotient is not 0L ? quotient.ToString() : string.Empty)}&{remainder}x", }; temp.Click += this.WindowSize_Click; WindowSizeSubMenu.DropDownItems.Insert(i - 1, temp); diff --git a/src/BizHawk.Emulation.Common/filetype_detectors/SatellaviewFileTypeDetector.cs b/src/BizHawk.Emulation.Common/filetype_detectors/SatellaviewFileTypeDetector.cs index c8913be515..1d7d8cc1a2 100644 --- a/src/BizHawk.Emulation.Common/filetype_detectors/SatellaviewFileTypeDetector.cs +++ b/src/BizHawk.Emulation.Common/filetype_detectors/SatellaviewFileTypeDetector.cs @@ -87,7 +87,7 @@ namespace BizHawk.Emulation.Common => _header = header; public override string ToString() - => $"[{ContentTypeField >> 4:X1}] {Title} r{Revision} ({(IsSelfDestructing ? RemainingPlays : "unlimited")} plays left)"; + => $"[{ContentTypeField >> 4:X1}] {Title} r{Revision} ({(IsSelfDestructing ? RemainingPlays.ToString() : "unlimited")} plays left)"; public bool VerifyChecksum(ReadOnlySpan rom) => true; //TODO need to parse page mapping from offset 0x20..0x23 in order to calculate this diff --git a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs index 602b1c3fb4..e634ff8bc4 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs @@ -28,7 +28,7 @@ namespace BizHawk.Emulation.Cores.Components.FairchildF8 if (format.ContainsOrdinal('d')) { var b = unchecked((sbyte)read(addr++)); - format = format.Replace("d", $"{(b < 0 ? '-' : '+')}{(b < 0 ? -b : b):X2}h"); + format = format.Replace("d", $"{(b < 0 ? '-' : '+')}{Math.Abs((short) b):X2}h"); } return format; diff --git a/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs index 405d818794..1a701b8bb5 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs @@ -374,7 +374,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A if (format.ContainsOrdinal('d')) { var b = unchecked ((sbyte) read(addr++)); - format = format.Replace("d", $"{(b < 0 ? '-' : '+')}{(b < 0 ? -b : b):X2}h"); + format = format.Replace("d", $"{(b < 0 ? '-' : '+')}{Math.Abs((short) b):X2}h"); } return format;