diff --git a/.editorconfig b/.editorconfig index deb2065..cc3c781 100644 --- a/.editorconfig +++ b/.editorconfig @@ -149,6 +149,16 @@ dotnet_diagnostic.IDE0043.severity = warning # IDE0044: Make field readonly dotnet_diagnostic.IDE0044.severity = warning +dotnet_diagnostic.CA1000.severity = none +dotnet_diagnostic.CA1016.severity = none +dotnet_diagnostic.CA1711.severity = none +dotnet_diagnostic.CA1716.severity = none +dotnet_diagnostic.CA1720.severity = none + +[Reactor.Benchmarks/*.cs] +dotnet_diagnostic.CA1707.severity = none +dotnet_diagnostic.CA1822.severity = none + # CSharp code style settings: [*.cs] # Newline settings diff --git a/Directory.Build.props b/Directory.Build.props index c18cbd4..3052ee6 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -21,4 +21,19 @@ + + + true + latest + recommended + true + + + + + + + + $(MSBuildThisFileDirectory)\stylecop.ruleset + diff --git a/Reactor.Benchmarks/AssetBundleBenchmarks.cs b/Reactor.Benchmarks/AssetBundleBenchmarks.cs index ec9d4bc..e80e177 100644 --- a/Reactor.Benchmarks/AssetBundleBenchmarks.cs +++ b/Reactor.Benchmarks/AssetBundleBenchmarks.cs @@ -84,7 +84,7 @@ public class AssetBundleBenchmarks var length = (int) stream.Length; var array = new Il2CppStructArray(length); - if (stream.Read(array.ToSpan()) < length) throw new Exception("Failed to read in full"); + if (stream.Read(array.ToSpan()) < length) throw new IOException("Failed to read in full"); return LoadAll(AssetBundle.LoadFromMemory(array)); } diff --git a/Reactor.Example/ExampleRpc.cs b/Reactor.Example/ExampleRpc.cs index c60b8ec..2eaf2ff 100644 --- a/Reactor.Example/ExampleRpc.cs +++ b/Reactor.Example/ExampleRpc.cs @@ -11,15 +11,7 @@ public class ExampleRpc : PlayerCustomRpc { } - public readonly struct Data - { - public readonly string Message; - - public Data(string message) - { - Message = message; - } - } + public readonly record struct Data(string Message); public override RpcLocalHandling LocalHandling => RpcLocalHandling.None; diff --git a/Reactor.Networking.Shared/Mod.cs b/Reactor.Networking.Shared/Mod.cs index 7a600bb..76a57b9 100644 --- a/Reactor.Networking.Shared/Mod.cs +++ b/Reactor.Networking.Shared/Mod.cs @@ -8,7 +8,7 @@ using System.Text; namespace Reactor.Networking; -public readonly struct Mod +public readonly struct Mod : IEquatable { public Mod(string id, string version, ModFlags flags, string? name = null) { diff --git a/Reactor/Compiler/IsUnmanagedAttribute.cs b/Reactor/Compiler/IsUnmanagedAttribute.cs index 4c137c3..067161a 100644 --- a/Reactor/Compiler/IsUnmanagedAttribute.cs +++ b/Reactor/Compiler/IsUnmanagedAttribute.cs @@ -7,6 +7,7 @@ namespace System.Runtime.CompilerServices; /// It should be generated automatically, but for whatever reason its not. /// [Obsolete("Do not use directly.", true)] -internal class IsUnmanagedAttribute : Attribute +[AttributeUsage(AttributeTargets.All)] +internal sealed class IsUnmanagedAttribute : Attribute { } diff --git a/Reactor/Localization/CustomStringName.cs b/Reactor/Localization/CustomStringName.cs index 404f5f5..d2e3b6e 100644 --- a/Reactor/Localization/CustomStringName.cs +++ b/Reactor/Localization/CustomStringName.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Globalization; using System.Linq; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; @@ -43,7 +44,7 @@ public class CustomStringName if (customStringName != null) { - __result = string.Format(customStringName.Value, parts); + __result = string.Format(CultureInfo.InvariantCulture, customStringName.Value, parts); return false; } diff --git a/Reactor/Networking/Attributes/MessageConverterAttribute.cs b/Reactor/Networking/Attributes/MessageConverterAttribute.cs index dda11c4..f792211 100644 --- a/Reactor/Networking/Attributes/MessageConverterAttribute.cs +++ b/Reactor/Networking/Attributes/MessageConverterAttribute.cs @@ -8,7 +8,7 @@ using Reactor.Networking.Serialization; namespace Reactor.Networking.Attributes; [AttributeUsage(AttributeTargets.Class)] -public class MessageConverterAttribute : Attribute +public sealed class MessageConverterAttribute : Attribute { private static readonly HashSet _registeredAssemblies = new(); diff --git a/Reactor/Networking/Attributes/MethodRpcAttribute.cs b/Reactor/Networking/Attributes/MethodRpcAttribute.cs index cf276a3..3eb0ffe 100644 --- a/Reactor/Networking/Attributes/MethodRpcAttribute.cs +++ b/Reactor/Networking/Attributes/MethodRpcAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -11,7 +11,7 @@ using Reactor.Utilities; namespace Reactor.Networking.Attributes; [AttributeUsage(AttributeTargets.Method)] -public class MethodRpcAttribute : Attribute +public sealed class MethodRpcAttribute : Attribute { private static readonly HashSet _registeredAssemblies = new(); diff --git a/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs b/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs index e41c546..0f1d8a0 100644 --- a/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs +++ b/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs @@ -5,7 +5,7 @@ using System.Reflection; namespace Reactor.Networking.Attributes; [AttributeUsage(AttributeTargets.Class)] -public class ReactorModFlagsAttribute : Attribute +public sealed class ReactorModFlagsAttribute : Attribute { public ModFlags Flags { get; } diff --git a/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs b/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs index 37ccb96..fd19434 100644 --- a/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs +++ b/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs @@ -12,7 +12,7 @@ namespace Reactor.Networking.Attributes; /// Utility attribute for automatically registering CustomRpc /// [AttributeUsage(AttributeTargets.Class)] -public class RegisterCustomRpcAttribute : Attribute +public sealed class RegisterCustomRpcAttribute : Attribute { private static readonly HashSet _registeredAssemblies = new(); diff --git a/Reactor/Networking/ModList.cs b/Reactor/Networking/ModList.cs index 84c2adf..2b1c174 100644 --- a/Reactor/Networking/ModList.cs +++ b/Reactor/Networking/ModList.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using BepInEx; @@ -93,8 +94,8 @@ public static class ModList foreach (var mod in Current) { debug.AppendLine(); - debug.Append($" - {mod.Id} version: {mod.Version}, flags: {mod.Flags}"); - if (mod.IsRequiredOnAllClients) debug.Append($", netId: {mod.GetNetId()}"); + debug.Append(CultureInfo.InvariantCulture, $" - {mod.Id} version: {mod.Version}, flags: {mod.Flags}"); + if (mod.IsRequiredOnAllClients) debug.Append(CultureInfo.InvariantCulture, $", netId: {mod.GetNetId()}"); } Debug(debug.ToString()); diff --git a/Reactor/Networking/Patches/ClientPatches.cs b/Reactor/Networking/Patches/ClientPatches.cs index 58e4f13..aa1a4af 100644 --- a/Reactor/Networking/Patches/ClientPatches.cs +++ b/Reactor/Networking/Patches/ClientPatches.cs @@ -125,7 +125,6 @@ internal static class ClientPatches Debug("Injecting ReactorHandshakeC2S to CoSendSceneChange"); ReactorHeader.Write(writer); ModdedHandshakeC2S.Serialize(writer, ModList.Current); - // writer.EndMessage(); writer.EndMessage(); @@ -206,7 +205,6 @@ internal static class ClientPatches ReactorHeader.Write(msg); ModdedHandshakeS2C.Serialize(msg, "Among Us", Application.version, 0); // TODO } - // msg.EndMessage(); diff --git a/Reactor/Networking/Rpc/CustomRpcManager.cs b/Reactor/Networking/Rpc/CustomRpcManager.cs index a83cf16..1406969 100644 --- a/Reactor/Networking/Rpc/CustomRpcManager.cs +++ b/Reactor/Networking/Rpc/CustomRpcManager.cs @@ -15,7 +15,7 @@ public class CustomRpcManager public const byte CallId = byte.MaxValue; private readonly List _list = new(); - internal readonly Dictionary>> _map = new(); + private readonly Dictionary>> _map = new(); public IReadOnlyList List => _list.AsReadOnly(); diff --git a/Reactor/Networking/Rpc/Rpc.cs b/Reactor/Networking/Rpc/Rpc.cs index e1f7c18..ee09389 100644 --- a/Reactor/Networking/Rpc/Rpc.cs +++ b/Reactor/Networking/Rpc/Rpc.cs @@ -12,7 +12,7 @@ public static class Rpc where T : UnsafeCustomRpc { if (_instance == null) { - throw new Exception($"{typeof(T).FullName} isn't registered"); + throw new InvalidOperationException($"{typeof(T).FullName} isn't registered"); } return _instance; @@ -22,7 +22,7 @@ public static class Rpc where T : UnsafeCustomRpc { if (_instance != null) { - throw new Exception($"{typeof(T).FullName} is already registered"); + throw new InvalidOperationException($"{typeof(T).FullName} is already registered"); } _instance = value; diff --git a/Reactor/Patches/Miscellaneous/FreeNamePatch.cs b/Reactor/Patches/Miscellaneous/FreeNamePatch.cs index 37c869a..bdd900e 100644 --- a/Reactor/Patches/Miscellaneous/FreeNamePatch.cs +++ b/Reactor/Patches/Miscellaneous/FreeNamePatch.cs @@ -23,7 +23,7 @@ internal static class FreeNamePatch { SceneManager.add_sceneLoaded((Action) ((scene, _) => { - if (!scene.name.Equals("MMOnline")) return; + if (!scene.name.Equals("MMOnline", StringComparison.Ordinal)) return; if (!TryMoveObjects()) return; var editName = DestroyableSingleton.Instance.accountTab.editNameScreen; diff --git a/Reactor/Patches/ReactorVersionShower.cs b/Reactor/Patches/ReactorVersionShower.cs index b564138..f5ac84f 100644 --- a/Reactor/Patches/ReactorVersionShower.cs +++ b/Reactor/Patches/ReactorVersionShower.cs @@ -56,7 +56,7 @@ public static class ReactorVersionShower private static string ToStringWithoutBuild(Version version) { - return $"{version.Major}.{version.Minor}.{version.Patch}{(version.PreRelease == null ? "" : $"-{version.PreRelease}")}"; + return $"{version.Major}.{version.Minor}.{version.Patch}{(version.PreRelease == null ? string.Empty : $"-{version.PreRelease}")}"; } public static void UpdateText() diff --git a/Reactor/ReactorPlugin.cs b/Reactor/ReactorPlugin.cs index fe5b3cd..ec5d606 100644 --- a/Reactor/ReactorPlugin.cs +++ b/Reactor/ReactorPlugin.cs @@ -72,7 +72,7 @@ public partial class ReactorPlugin : BasePlugin } [RegisterInIl2Cpp] - public class ReactorComponent : MonoBehaviour + private class ReactorComponent : MonoBehaviour { [HideFromIl2Cpp] public ReactorPlugin? Plugin { get; internal set; } diff --git a/Reactor/Utilities/AssetBundleManager.cs b/Reactor/Utilities/AssetBundleManager.cs index 6507bca..6cc0d43 100644 --- a/Reactor/Utilities/AssetBundleManager.cs +++ b/Reactor/Utilities/AssetBundleManager.cs @@ -69,14 +69,14 @@ public static class AssetBundleManager private static bool TryLoadResource(Assembly assembly, string fileName, [NotNullWhen(true)] out Il2CppStructArray? data) { - var resourceName = assembly.GetManifestResourceNames().SingleOrDefault(n => n.EndsWith(fileName)); + var resourceName = assembly.GetManifestResourceNames().SingleOrDefault(n => n.EndsWith(fileName, StringComparison.Ordinal)); if (resourceName != null) { - using var stream = assembly.GetManifestResourceStream(resourceName) ?? throw new NullReferenceException("Resource stream was null"); + using var stream = assembly.GetManifestResourceStream(resourceName) ?? throw new InvalidOperationException("Resource stream was null"); var length = (int) stream.Length; data = new Il2CppStructArray(length); - if (stream.Read(data.ToSpan()) < length) throw new Exception("Failed to read in full"); + if (stream.Read(data.ToSpan()) < length) throw new IOException("Failed to read in full"); return true; } diff --git a/Reactor/Utilities/Coroutines.cs b/Reactor/Utilities/Coroutines.cs index b1531d5..319bf0f 100644 --- a/Reactor/Utilities/Coroutines.cs +++ b/Reactor/Utilities/Coroutines.cs @@ -24,6 +24,7 @@ public static class Coroutines Instance = this; } + [SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "OnDestroy is an unity event and can't be static")] private void OnDestroy() { Instance = null; diff --git a/Reactor/Utilities/Dispatcher.cs b/Reactor/Utilities/Dispatcher.cs index 9ecc4ba..aedf8c6 100644 --- a/Reactor/Utilities/Dispatcher.cs +++ b/Reactor/Utilities/Dispatcher.cs @@ -7,15 +7,11 @@ using UnityEngine; namespace Reactor.Utilities; [RegisterInIl2Cpp] -public class Dispatcher : MonoBehaviour +public sealed class Dispatcher : MonoBehaviour { - public Dispatcher(IntPtr ptr) : base(ptr) - { - } - public static Dispatcher Instance { get; private set; } = null!; - private static readonly Queue _queue = new(); + private readonly Queue _queue = new(); private void Awake() { diff --git a/Reactor/Utilities/Extensions/ReflectionExtensions.cs b/Reactor/Utilities/Extensions/ReflectionExtensions.cs index cde4408..db66c6f 100644 --- a/Reactor/Utilities/Extensions/ReflectionExtensions.cs +++ b/Reactor/Utilities/Extensions/ReflectionExtensions.cs @@ -48,7 +48,7 @@ public static class ReflectionExtensions return t; } - throw new Exception("Failed to find a system type for " + type.AssemblyQualifiedName); + throw new TypeLoadException("Failed to find a system type for " + type.AssemblyQualifiedName); } public static MethodInfo EnumeratorMoveNext(Type type, string methodName) diff --git a/Reactor/Utilities/Extensions/StreamExtensions.cs b/Reactor/Utilities/Extensions/StreamExtensions.cs index 0c73bfc..dd7b80e 100644 --- a/Reactor/Utilities/Extensions/StreamExtensions.cs +++ b/Reactor/Utilities/Extensions/StreamExtensions.cs @@ -15,10 +15,6 @@ public static class StreamExtensions { private readonly Stream _stream; -#pragma warning disable 8618 - public StreamWrapper(IntPtr ptr) : base(ptr) { } -#pragma warning restore 8618 - public StreamWrapper(Stream stream) : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody(this); diff --git a/Reactor/Utilities/Il2CppEqualityComparer.cs b/Reactor/Utilities/Il2CppEqualityComparer.cs index 9500ea6..9096f7e 100644 --- a/Reactor/Utilities/Il2CppEqualityComparer.cs +++ b/Reactor/Utilities/Il2CppEqualityComparer.cs @@ -20,18 +20,20 @@ public sealed class Il2CppEqualityComparer : IEqualityComparer where T : I { } - public int GetHashCode(T value) + /// + public int GetHashCode(T obj) { - return RuntimeHelpers.GetHashCode(value); + return RuntimeHelpers.GetHashCode(obj); } - public bool Equals(T? left, T? right) + /// + public bool Equals(T? x, T? y) { - if (left == null || right == null) + if (x == null || y == null) { - return left == null && right == null; + return x == null && y == null; } - return left.Equals(right); + return x.Equals(y); } } diff --git a/Reactor/Utilities/SceneManagerUtilities.cs b/Reactor/Utilities/SceneManagerUtilities.cs index b0c51ce..a410b37 100644 --- a/Reactor/Utilities/SceneManagerUtilities.cs +++ b/Reactor/Utilities/SceneManagerUtilities.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using UnityEngine.Events; using UnityEngine.SceneManagement; @@ -9,6 +10,7 @@ public static class SceneManagerUtilities /// /// Adds a delegate to get one notification when a scene has loaded. /// + [SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "This supplements existing methods like add_sceneLoaded and remove_sceneLoaded")] public static void once_sceneLoaded(Action value) { UnityAction? unityAction = null; diff --git a/stylecop.json b/stylecop.json new file mode 100644 index 0000000..09546e5 --- /dev/null +++ b/stylecop.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "orderingRules": { + "usingDirectivesPlacement": "outsideNamespace" + }, + "layoutRules": { + "newlineAtEndOfFile": "require", + "allowDoWhileOnClosingBrace": true + }, + "documentationRules": { + "xmlHeader": false, + "documentInterfaces": false + } + } +} diff --git a/stylecop.ruleset b/stylecop.ruleset new file mode 100644 index 0000000..ac9ef64 --- /dev/null +++ b/stylecop.ruleset @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +