diff --git a/.global.editorconfig.ini b/.global.editorconfig.ini index a06ffaaee8..34c537797e 100644 --- a/.global.editorconfig.ini +++ b/.global.editorconfig.ini @@ -19,6 +19,8 @@ dotnet_diagnostic.BHI1005.severity = silent dotnet_diagnostic.BHI1006.severity = error # Don't use target-typed new for throw expressions dotnet_diagnostic.BHI1007.severity = error +# Do not use init setter +dotnet_diagnostic.BHI1008.severity = error # 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) diff --git a/ExternalProjects/BizHawk.Analyzer/HawkSourceAnalyzer.cs b/ExternalProjects/BizHawk.Analyzer/HawkSourceAnalyzer.cs index 7b53834a93..99603d5325 100644 --- a/ExternalProjects/BizHawk.Analyzer/HawkSourceAnalyzer.cs +++ b/ExternalProjects/BizHawk.Analyzer/HawkSourceAnalyzer.cs @@ -55,6 +55,14 @@ public class HawkSourceAnalyzer : DiagnosticAnalyzer defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true); + private static readonly DiagnosticDescriptor DiagNoInitAccessor = new( + id: "BHI1008", + title: "Do not use init setter", + messageFormat: "Use a regular `set`ter (or add a constructor parameter)", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: false); + private static readonly DiagnosticDescriptor DiagNoQueryExpression = new( id: "BHI1003", title: "Do not use query expression syntax", @@ -119,6 +127,7 @@ public class HawkSourceAnalyzer : DiagnosticAnalyzer DiagNoAnonClasses, DiagNoAnonDelegates, DiagNoDiscardingLocals, + DiagNoInitAccessor, DiagNoQueryExpression, DiagRecordImplicitlyRefType, DiagSwitchShouldThrowIOE, @@ -170,6 +179,9 @@ public class HawkSourceAnalyzer : DiagnosticAnalyzer } switch (snac.Node) { + case AccessorDeclarationSyntax ads: + if (ads.Keyword.ToString() is "init") DiagNoInitAccessor.ReportAt(ads, snac); + break; case AnonymousMethodExpressionSyntax: DiagNoAnonDelegates.ReportAt(snac.Node, snac); break; @@ -218,6 +230,7 @@ public class HawkSourceAnalyzer : DiagnosticAnalyzer SyntaxKind.AnonymousObjectCreationExpression, SyntaxKind.AnonymousMethodExpression, SyntaxKind.CollectionExpression, + SyntaxKind.InitAccessorDeclaration, SyntaxKind.InterpolatedStringExpression, SyntaxKind.ListPattern, SyntaxKind.QueryExpression, diff --git a/ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/HawkSourceAnalyzerTests.cs b/ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/HawkSourceAnalyzerTests.cs index 6fe7b9424e..1c2b94424e 100644 --- a/ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/HawkSourceAnalyzerTests.cs +++ b/ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/HawkSourceAnalyzerTests.cs @@ -101,6 +101,17 @@ public sealed class HawkSourceAnalyzerTests } """); + [TestMethod] + public Task CheckMisuseOfInitAccessor() + => Verify.VerifyAnalyzerAsync(""" + public sealed class Cases { + public int A { get; {|BHI1008:init;|} } + } + namespace System.Runtime.CompilerServices { + public static class IsExternalInit {} // this sample is compiled for lowest-common-denominator of `netstandard2.0`, so `init` accessor gives an error without this + } + """); + [TestMethod] public Task CheckMisuseOfInterpolatedString() => Verify.VerifyAnalyzerAsync(""" diff --git a/References/BizHawk.Analyzer.dll b/References/BizHawk.Analyzer.dll index 87d944b9e6..d912a3b306 100644 Binary files a/References/BizHawk.Analyzer.dll and b/References/BizHawk.Analyzer.dll differ diff --git a/src/BizHawk.Client.Common/FilesystemFilterSet.cs b/src/BizHawk.Client.Common/FilesystemFilterSet.cs index f1a41b07ff..09bb9b4898 100644 --- a/src/BizHawk.Client.Common/FilesystemFilterSet.cs +++ b/src/BizHawk.Client.Common/FilesystemFilterSet.cs @@ -9,9 +9,9 @@ namespace BizHawk.Client.Common { private string? _ser = null; - public bool AppendAllFilesEntry { get; init; } = true; + public bool AppendAllFilesEntry { get; set; } = true; - public string? CombinedEntryDesc { get; init; } = null; + public string? CombinedEntryDesc { get; set; } = null; private IReadOnlyCollection CombinedExts => Filters.SelectMany(static filter => filter.Extensions).Distinct().Order().ToList(); diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs index 443235d49f..c519a1afc3 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs @@ -107,9 +107,11 @@ namespace BizHawk.Client.EmuHawk private readonly uint _domainAddrStart; // addr of _domain where bank begins private readonly uint _addressMangler; // of course, let's *not* correct internal core byteswapping! - public ReadMemoryFunc ReadFunc { get; protected init; } - public WriteMemoryFunc WriteFunc { get; protected init; } - public ReadMemoryBlockFunc ReadBlockFunc { get; protected init; } + public virtual ReadMemoryFunc ReadFunc { get; } + + public virtual WriteMemoryFunc WriteFunc { get; } + + public virtual ReadMemoryBlockFunc ReadBlockFunc { get; } public uint StartAddress; // this is set for our rcheevos impl public readonly uint BankSize; @@ -192,13 +194,17 @@ namespace BizHawk.Client.EmuHawk private class NullMemFunctions : MemFunctions { + public override ReadMemoryFunc ReadFunc + => null; + + public override WriteMemoryFunc WriteFunc + => null; + + public override ReadMemoryBlockFunc ReadBlockFunc + => null; + public NullMemFunctions(long bankSize) - : base(null, 0, bankSize) - { - ReadFunc = null; - WriteFunc = null; - ReadBlockFunc = null; - } + : base(null, 0, bankSize) {} } // this is a complete hack because the libretro Intelli core sucks and so achievements are made expecting this format diff --git a/src/BizHawk.Client.EmuHawk/config/SNES/BSNESOptions.cs b/src/BizHawk.Client.EmuHawk/config/SNES/BSNESOptions.cs index aa447d8e46..57ba126b56 100644 --- a/src/BizHawk.Client.EmuHawk/config/SNES/BSNESOptions.cs +++ b/src/BizHawk.Client.EmuHawk/config/SNES/BSNESOptions.cs @@ -97,31 +97,31 @@ namespace BizHawk.Client.EmuHawk private bool AlwaysDoubleSize { get => cbDoubleSize.Checked; - init => cbDoubleSize.Checked = value; + set => cbDoubleSize.Checked = value; } private bool CropSGBFrame { get => cbCropSGBFrame.Checked; - init => cbCropSGBFrame.Checked = value; + set => cbCropSGBFrame.Checked = value; } private bool NoPPUSpriteLimit { get => cbNoPPUSpriteLimit.Checked; - init => cbNoPPUSpriteLimit.Checked = value; + set => cbNoPPUSpriteLimit.Checked = value; } private bool ShowOverscan { get => cbShowOverscan.Checked; - init => cbShowOverscan.Checked = value; + set => cbShowOverscan.Checked = value; } private bool ShowCursor { get => cbShowCursor.Checked; - init => cbShowCursor.Checked = value; + set => cbShowCursor.Checked = value; } private BsnesApi.ASPECT_RATIO_CORRECTION AspectRatioCorrection => (BsnesApi.ASPECT_RATIO_CORRECTION)AspectRatioCorrectionBox.SelectedIndex; @@ -129,43 +129,43 @@ namespace BizHawk.Client.EmuHawk private bool Hotfixes { get => cbGameHotfixes.Checked; - init => cbGameHotfixes.Checked = value; + set => cbGameHotfixes.Checked = value; } private bool FastPPU { get => cbFastPPU.Checked; - init => cbDoubleSize.Enabled = cbNoPPUSpriteLimit.Enabled = cbFastPPU.Checked = value; + set => cbDoubleSize.Enabled = cbNoPPUSpriteLimit.Enabled = cbFastPPU.Checked = value; } private bool FastDSP { get => cbFastDSP.Checked; - init => cbFastDSP.Checked = value; + set => cbFastDSP.Checked = value; } private bool FastCoprocessors { get => cbFastCoprocessor.Checked; - init => cbFastCoprocessor.Checked = value; + set => cbFastCoprocessor.Checked = value; } private bool UseSGB2 { get => cbUseSGB2.Checked; - init => cbUseSGB2.Checked = value; + set => cbUseSGB2.Checked = value; } private bool UseRealTime { get => cbUseRealTime.Checked; - init => cbUseRealTime.Checked = value; + set => cbUseRealTime.Checked = value; } private DateTime InitialTime { get => dtpInitialTime.Value; - init => dtpInitialTime.Value = value; + set => dtpInitialTime.Value = value; } private BsnesApi.ENTROPY Entropy => (BsnesApi.ENTROPY) EntropyBox.SelectedIndex; @@ -174,19 +174,77 @@ namespace BizHawk.Client.EmuHawk private BsnesCore.SATELLAVIEW_CARTRIDGE SatellaviewCartridge => (BsnesCore.SATELLAVIEW_CARTRIDGE)SatellaviewCartridgeBox.SelectedIndex; - private bool ShowObj1 { get => Obj1Checkbox.Checked; init => Obj1Checkbox.Checked = value; } - private bool ShowObj2 { get => Obj2Checkbox.Checked; init => Obj2Checkbox.Checked = value; } - private bool ShowObj3 { get => Obj3Checkbox.Checked; init => Obj3Checkbox.Checked = value; } - private bool ShowObj4 { get => Obj4Checkbox.Checked; init => Obj4Checkbox.Checked = value; } + private bool ShowObj1 + { + get => Obj1Checkbox.Checked; + set => Obj1Checkbox.Checked = value; + } - private bool ShowBg1_0 { get => Bg1_0Checkbox.Checked; init => Bg1_0Checkbox.Checked = value; } - private bool ShowBg1_1 { get => Bg1_1Checkbox.Checked; init => Bg1_1Checkbox.Checked = value; } - private bool ShowBg2_0 { get => Bg2_0Checkbox.Checked; init => Bg2_0Checkbox.Checked = value; } - private bool ShowBg2_1 { get => Bg2_1Checkbox.Checked; init => Bg2_1Checkbox.Checked = value; } - private bool ShowBg3_0 { get => Bg3_0Checkbox.Checked; init => Bg3_0Checkbox.Checked = value; } - private bool ShowBg3_1 { get => Bg3_1Checkbox.Checked; init => Bg3_1Checkbox.Checked = value; } - private bool ShowBg4_0 { get => Bg4_0Checkbox.Checked; init => Bg4_0Checkbox.Checked = value; } - private bool ShowBg4_1 { get => Bg4_1Checkbox.Checked; init => Bg4_1Checkbox.Checked = value; } + private bool ShowObj2 + { + get => Obj2Checkbox.Checked; + set => Obj2Checkbox.Checked = value; + } + + private bool ShowObj3 + { + get => Obj3Checkbox.Checked; + set => Obj3Checkbox.Checked = value; + } + + private bool ShowObj4 + { + get => Obj4Checkbox.Checked; + set => Obj4Checkbox.Checked = value; + } + + private bool ShowBg1_0 + { + get => Bg1_0Checkbox.Checked; + set => Bg1_0Checkbox.Checked = value; + } + + private bool ShowBg1_1 + { + get => Bg1_1Checkbox.Checked; + set => Bg1_1Checkbox.Checked = value; + } + + private bool ShowBg2_0 + { + get => Bg2_0Checkbox.Checked; + set => Bg2_0Checkbox.Checked = value; + } + + private bool ShowBg2_1 + { + get => Bg2_1Checkbox.Checked; + set => Bg2_1Checkbox.Checked = value; + } + + private bool ShowBg3_0 + { + get => Bg3_0Checkbox.Checked; + set => Bg3_0Checkbox.Checked = value; + } + + private bool ShowBg3_1 + { + get => Bg3_1Checkbox.Checked; + set => Bg3_1Checkbox.Checked = value; + } + + private bool ShowBg4_0 + { + get => Bg4_0Checkbox.Checked; + set => Bg4_0Checkbox.Checked = value; + } + + private bool ShowBg4_1 + { + get => Bg4_1Checkbox.Checked; + set => Bg4_1Checkbox.Checked = value; + } private void BtnOk_Click(object sender, EventArgs e) { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesControllers.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesControllers.cs index 6d0b6d2f05..6c6712ee77 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesControllers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesControllers.cs @@ -17,10 +17,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES BSNES_INPUT_DEVICE.None => new BsnesUnpluggedController(), BSNES_INPUT_DEVICE.Gamepad => new BsnesController(), BSNES_INPUT_DEVICE.ExtendedGamepad => new BsnesExtendedController(), - BSNES_INPUT_DEVICE.Mouse => new BsnesMouseController - { - LimitAnalogChangeSensitivity = ss.LimitAnalogChangeSensitivity - }, + BSNES_INPUT_DEVICE.Mouse => new BsnesMouseController(LimitAnalogChangeSensitivity: ss.LimitAnalogChangeSensitivity), BSNES_INPUT_DEVICE.SuperMultitap => new BsnesMultitapController(), BSNES_INPUT_DEVICE.Payload => new BsnesPayloadController(), BSNES_INPUT_DEVICE.SuperScope => new BsnesSuperScopeController(), @@ -171,14 +168,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES } } - internal class BsnesMouseController : IBsnesController + internal class BsnesMouseController(bool LimitAnalogChangeSensitivity = true) : IBsnesController { private static readonly ControllerDefinition _definition = new ControllerDefinition("(SNES Controller fragment)") { BoolButtons = { "0Mouse Left", "0Mouse Right" } } .AddXYPair("0Mouse {0}", AxisPairOrientation.RightAndDown, (-127).RangeTo(127), 0); public ControllerDefinition Definition => _definition; - public bool LimitAnalogChangeSensitivity { get; init; } = true; public short GetState(IController controller, int index, int id) { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs index cea40cdc22..170202ad6a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -642,24 +642,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy { throw new InvalidOperationException("Unexpected error in gambatte_getmemoryarea"); } - return new GPUMemoryAreas - { - Vram = _vram, - Oam = _oam, - Sppal = _sppal, - Bgpal = _bgpal, - }; + return new GPUMemoryAreas(vram: _vram, oam: _oam, sppal: _sppal, bgpal: _bgpal); } - private class GPUMemoryAreas : IGPUMemoryAreas + private sealed class GPUMemoryAreas(IntPtr vram, IntPtr oam, IntPtr sppal, IntPtr bgpal) : IGPUMemoryAreas { - public IntPtr Vram { get; init; } + public IntPtr Vram + => vram; - public IntPtr Oam { get; init; } + public IntPtr Oam + => oam; - public IntPtr Sppal { get; init; } + public IntPtr Sppal + => sppal; - public IntPtr Bgpal { get; init; } + public IntPtr Bgpal + => bgpal; public void Dispose() {} } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs index f5376281c1..9b14e674c9 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs @@ -350,45 +350,45 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES public BGInfos BG = new BGInfos(); - public int Mode { get; init; } - public bool Mode1_BG3_Priority { get; init; } + public int Mode { get; internal set; } + public bool Mode1_BG3_Priority { get; internal set; } - public bool SETINI_Mode7ExtBG { get; init; } - public bool SETINI_HiRes { get; init; } - public bool SETINI_Overscan { get; init; } - public bool SETINI_ObjInterlace { get; init; } - public bool SETINI_ScreenInterlace { get; init; } + public bool SETINI_Mode7ExtBG { get; internal set; } + public bool SETINI_HiRes { get; internal set; } + public bool SETINI_Overscan { get; internal set; } + public bool SETINI_ObjInterlace { get; internal set; } + public bool SETINI_ScreenInterlace { get; internal set; } - public int CGWSEL_ColorMask { get; init; } - public int CGWSEL_ColorSubMask { get; init; } - public int CGWSEL_AddSubMode { get; init; } - public bool CGWSEL_DirectColor { get; init; } - public int CGADSUB_AddSub { get; init; } - public bool CGADSUB_Half { get; init; } + public int CGWSEL_ColorMask { get; internal set; } + public int CGWSEL_ColorSubMask { get; internal set; } + public int CGWSEL_AddSubMode { get; internal set; } + public bool CGWSEL_DirectColor { get; internal set; } + public int CGADSUB_AddSub { get; internal set; } + public bool CGADSUB_Half { get; internal set; } - public int OBSEL_Size { get; init; } - public int OBSEL_NameSel { get; init; } - public int OBSEL_NameBase { get; init; } + public int OBSEL_Size { get; internal set; } + public int OBSEL_NameSel { get; internal set; } + public int OBSEL_NameBase { get; internal set; } - public int OBJTable0Addr { get; init; } - public int OBJTable1Addr { get; init; } + public int OBJTable0Addr { get; internal set; } + public int OBJTable1Addr { get; internal set; } - public bool OBJ_MainEnabled { get; init; } - public bool OBJ_SubEnabled { get; init; } - public bool OBJ_MathEnabled { get; init; } - public bool BK_MathEnabled { get; init; } + public bool OBJ_MainEnabled { get; internal set; } + public bool OBJ_SubEnabled { get; internal set; } + public bool OBJ_MathEnabled { get; internal set; } + public bool BK_MathEnabled { get; internal set; } - public int M7HOFS { get; init; } - public int M7VOFS { get; init; } - public int M7A { get; init; } - public int M7B { get; init; } - public int M7C { get; init; } - public int M7D { get; init; } - public int M7X { get; init; } - public int M7Y { get; init; } - public int M7SEL_REPEAT { get; init; } - public bool M7SEL_HFLIP { get; init; } - public bool M7SEL_VFLIP { get; init; } + public int M7HOFS { get; internal set; } + public int M7VOFS { get; internal set; } + public int M7A { get; internal set; } + public int M7B { get; internal set; } + public int M7C { get; internal set; } + public int M7D { get; internal set; } + public int M7X { get; internal set; } + public int M7Y { get; internal set; } + public int M7SEL_REPEAT { get; internal set; } + public bool M7SEL_HFLIP { get; internal set; } + public bool M7SEL_VFLIP { get; internal set; } } public static readonly int[,] ModeBpps = { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.cs index 7422996869..37de9285ba 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.cs @@ -270,25 +270,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy { throw new InvalidOperationException("Unexpected error in sameboy_getmemoryarea"); } - - return new GPUMemoryAreas() - { - Vram = _vram, - Oam = _oam, - Sppal = _sppal, - Bgpal = _bgpal - }; + return new GPUMemoryAreas(vram: _vram, oam: _oam, sppal: _sppal, bgpal: _bgpal); } - private class GPUMemoryAreas : IGPUMemoryAreas + private sealed class GPUMemoryAreas(IntPtr vram, IntPtr oam, IntPtr sppal, IntPtr bgpal) : IGPUMemoryAreas { - public IntPtr Vram { get; init; } + public IntPtr Vram + => vram; - public IntPtr Oam { get; init; } + public IntPtr Oam + => oam; - public IntPtr Sppal { get; init; } + public IntPtr Sppal + => sppal; - public IntPtr Bgpal { get; init; } + public IntPtr Bgpal + => bgpal; public void Dispose() {} }