From 88851fa33c927aff85e2c2bd43e21bb4d16bfc34 Mon Sep 17 00:00:00 2001 From: AriusII Date: Wed, 23 Sep 2026 22:52:34 +0200 Subject: [PATCH 1/4] Close IDE/CA build-enforcement gaps in the C# 14 style contract Researched current C# 14 / .NET 10 style and analysis-rule guidance across seven angles (Microsoft Learn, the dotnet/roslyn option-default source, and 2026 analyzer-ecosystem status) to find rules this repo's TreatWarningsAsErrors + EnforceCodeStyleInBuild gate was not actually enforcing. The mechanism: EnforceCodeStyleInBuild only runs IDE-rule analyzers at build time, it does not promote their severity, and roughly two dozen relevant rules ship at Suggestion or Silent by default - a silent no-op in CI no matter how the project is configured, until each one gets an explicit severity here. Adds explicit severities/values for: pattern-matching preference (IDE0019, IDE0020, IDE0038, IDE0078, IDE0260), local-function-over-lambda and capture-free static local functions/lambdas (IDE0039, IDE0062, IDE0320), readonly struct/member (IDE0250, IDE0251), throw-expression and deconstruction simplification (IDE0016, IDE0042), redundant interpolation and compound assignment (IDE0071, IDE0054, IDE0074), dead-store elimination (IDE0059), parentheses-for-clarity (IDE0047, IDE0048), unbound-generic nameof for C# 14 (IDE0340), ArgumentNullException/ArgumentOutOfRangeException/ ObjectDisposedException throw-helper preference (CA1510-CA1513), and base/interface parameter-name parity kept at suggestion to match IDE1006's own rename-safety rationale (CA1725). Adds SYSLIB1054 as a build error to guard against a future hand-written [DllImport] - a BannedSymbols.txt/RS0030 entry for the same symbol was tried and reverted, because it also flags LibraryImportGenerator's own generated DllImport-based fallback stub for non-fully-blittable P/Invoke signatures, which RS0030 does not exempt the way the compiler's own SYSLIB1054 diagnostic does. Also flips csharp_style_prefer_primary_constructors to false to make the repo's existing explicit-constructor convention a documented choice rather than an unpinned SDK default, and enables dotnet_style_prefer_auto_properties and dotnet_style_prefer_conditional_expression_over_assignment/return at suggestion pending a manual pass. Adds three naming rules that previously matched nothing: non-private fields and enum members (the existing non_private_members rule only covers properties/methods/events), const and static readonly fields (previously fell through to the private-field _camelCase rule for the private subset), and an Async-suffix rule for async methods and local functions of any accessibility. Makes eng/Shipping.props's AOT/trim posture explicit (EnableTrimAnalyzer, EnableAotAnalyzer, EnableSingleFileAnalyzer, IsTrimmable - already implied by IsAotCompatible, restated so the guarantee survives a future SDK change to what that implies) and adds VerifyReferenceTrimCompatibility alongside the existing AOT reference check. dotnet format applied the ~24 resulting violations across the codebase. One of its rewrites (a lambda-to-local-function conversion in LiveProbeStateTests.cs, IDE0039) left a following continuation-line argument indented with a single space instead of the file's tab convention in two spots; fixed by hand after `dotnet format --verify-no-changes` and a full `dotnet build` both passed anyway, which is worth knowing about for any future large-scale dotnet format run on this codebase. Verified: clean build (0 warnings, 0 errors), dotnet format --verify-no-changes clean, and 4167/4168 tests pass. The one remaining failure (PackedConsumerBindingTests.Packaged_AOT_consumer_publishes_and_runs_only_as_a_standalone_executable) is a pre-existing environment gap (vswhere.exe not on PATH, breaking the native AOT link step) reproduced identically on main before this change. Every change here is low blast-radius by design (autofixable or additive, confirmed against a real build). Higher-blast-radius candidates from the same research pass - AnalysisMode escalations, CA1852/CA1063/CA1051, a Meziantou.Analyzer version bump, a VSTHRD analyzer addition, stricter expression-bodied-member and collection-expression severities, System.Threading.Lock migration, and CA1062 - are intentionally deferred pending their own trial builds and review. --- .editorconfig | 151 ++++++++++++++++++ eng/Shipping.props | 14 +- .../Errors/EngineMarshallingException.cs | 2 +- .../Values/IndexBase.cs | 2 +- .../Bootstrap/PluginHost.Lifecycle.cs | 2 +- .../Api/LuaApi.Constants.cs | 2 +- .../Marshalling/LuaIntegerReader.cs | 2 +- .../State/LuaState.Types.cs | 2 +- .../Parsing/SpecFileParser.cs | 2 +- .../Parsing/SpecIdentifiers.cs | 2 +- .../Parsing/LuaObjectMethodParser.cs | 4 +- .../Parsing/LuaObjectPropertyParser.cs | 6 +- .../ProtectedOperationCatalogParser.cs | 4 +- .../EquatableArray.cs | 2 +- .../HintNames.cs | 2 +- .../LuaEmit/LuaNames.cs | 2 +- .../Managed/ManagedExportedFunctionsTests.cs | 2 +- .../Native/ExportedFunctionsPrefixTests.cs | 2 +- .../Coexistence/NativeHostEmulatorTests.cs | 2 +- .../MemoryBindings.cs | 1 + .../LiveProbeStateTests.cs | 24 +-- .../Protected/LuaBridgeContractTests.cs | 6 +- .../Support/IlReader.cs | 2 +- .../PortableExecutableExportReader.cs | 2 +- .../Generator/NameEscapingTests.cs | 2 +- 25 files changed, 204 insertions(+), 40 deletions(-) diff --git a/.editorconfig b/.editorconfig index fe741e41..4216e54e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -95,6 +95,108 @@ dotnet_diagnostic.IDE0161.severity = warning # Naming fixes rename symbols, which dotnet format cannot apply safely; keep them as editor guidance. dotnet_diagnostic.IDE1006.severity = suggestion +################################################################################ +# Second hardening pass (2026-09): closes rules the .NET 10 SDK ships at +# Suggestion or Silent severity by default. EnforceCodeStyleInBuild only runs +# these analyzers at build time; it does NOT promote their severity. Only +# 'warning' (via TreatWarningsAsErrors) or 'error' fails the build, so every +# dotnet_diagnostic.IDEXXXX / csharp_style_* / dotnet_style_* line below +# carries an explicit severity for that reason - a bare option value with no +# ':severity' suffix silently keeps the SDK default, which is frequently +# Silent and therefore a no-op in CI no matter how the analyzer is configured. +################################################################################ + +# Pattern-matching preference: already 'true' by SDK default, only severity was missing. +# Roslyn only offers the fix when it is provably behavior-preserving. +dotnet_diagnostic.IDE0078.severity = warning +dotnet_diagnostic.IDE0260.severity = warning +dotnet_diagnostic.IDE0019.severity = warning +dotnet_diagnostic.IDE0020.severity = warning +dotnet_diagnostic.IDE0038.severity = warning + +# Local function over lambda when nothing is captured; avoids an implicit +# display-class/delegate allocation, which matters on the AOT src/libs surface. +dotnet_diagnostic.IDE0039.severity = warning +# Mark a capture-free local function/lambda 'static' to prevent the same allocation. +dotnet_diagnostic.IDE0062.severity = warning +dotnet_diagnostic.IDE0320.severity = warning + +# Mechanical, compiler-guaranteed-safe simplifications. +dotnet_diagnostic.IDE0042.severity = warning +dotnet_diagnostic.IDE0016.severity = warning +dotnet_diagnostic.IDE0071.severity = warning +dotnet_diagnostic.IDE0054.severity = warning +dotnet_diagnostic.IDE0074.severity = warning + +# Readonly struct / readonly member: Roslyn only offers the fix when no member +# mutates instance state. C#-level immutability only; it does not affect how +# native code writes through a pointer to the same memory, so it does not +# conflict with this SDK's blittable-struct/pointer-write interop model. +dotnet_diagnostic.IDE0250.severity = warning +dotnet_diagnostic.IDE0251.severity = warning + +# nameof(List<>) needs zero reflection metadata, unlike typeof(T).Name - the +# AOT-friendliest spelling, matching this SDK's no-reflection-type-discovery +# stance (eng/BannedSymbols.txt). C# 14+. +csharp_style_prefer_unbound_generic_type_in_nameof = true +dotnet_diagnostic.IDE0340.severity = warning + +# Prefer ArgumentNullException.ThrowIfNull / ArgumentOutOfRangeException throw +# helpers / ObjectDisposedException.ThrowIf over hand-written if-throw blocks. +# Already active at Suggestion under AnalysisLevel=10.0-recommended; Microsoft +# documents the fix as non-breaking. +dotnet_diagnostic.CA1510.severity = warning +dotnet_diagnostic.CA1511.severity = warning +dotnet_diagnostic.CA1512.severity = warning +dotnet_diagnostic.CA1513.severity = warning + +# Parameter-name consistency with the base/interface member it implements. +# The fix is a rename - the same class of fix dotnet/format#348 (open as of +# 2026-09-23) says 'dotnet format' cannot safely apply, so this stays at +# suggestion rather than joining IDE1006's exception list at a higher tier. +dotnet_diagnostic.CA1725.severity = suggestion + +# SYSLIB1054 ('use [LibraryImport], not [DllImport]') ships in-box since +# .NET 7 as part of the runtime's P/Invoke source generator; it lives outside +# AnalysisLevel/AnalysisMode entirely. No hand-written [DllImport] exists in +# this codebase today (verified), so this only guards against a future +# regression. Unlike a BannedSymbols.txt/RS0030 entry (tried, reverted), this +# compiler diagnostic correctly respects files, so it does +# not fire on LibraryImportGenerator's own generated DllImport-based fallback +# stub for non-fully-blittable signatures (libs/CheatEngine.SDK.Lua.Interop). +dotnet_diagnostic.SYSLIB1054.severity = error + +# Dead-store elimination: a value assigned to a local that is overwritten +# before being read. Safe, mechanical removal fix. +csharp_style_unused_value_assignment_preference = discard_variable:warning + +# Roslyn's fix only fires for a simple two-branch if/else; a forced ternary +# can still push past max_line_length=120 or read less explicitly than the +# block it replaces, so this stays advisory rather than build-breaking. +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion + +# Pure formatting, zero behavior change, covered by the same +# `dotnet format --verify-no-changes` CI gate as IDE0055. Removes +# operator-precedence ambiguity from mixed binary expressions. +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:warning + +# Flips the VALUE to match this file's own 'explicit types are the +# readability convention' stance (primary-constructor parameters become +# implicitly captured fields with different lifetime/visibility than an +# explicit field + assignment, and complicate per-parameter validation). +# Severity stays suggestion - a design judgment call, not build-breaking +# either way - mirroring IDE1006's philosophy. +csharp_style_prefer_primary_constructors = false:suggestion + +# Advisory only pending a manual pass over the Lua/ABI interop files, where a +# backing field is sometimes intentionally explicit for pointer/fixed/Unsafe +# access. +dotnet_style_prefer_auto_properties = true:suggestion + # Rider derives its own "var or explicit type" inspections from the shared # csharp_style_var_* values. Silence those copies so IDE0008 is the one # portable diagnostic developers see, rather than reporting each issue twice. @@ -108,6 +210,9 @@ resharper_suggest_var_or_type_deconstruction_declarations_highlighting = none resharper_possible_null_reference_exception_highlighting = warning # Naming rules keep public contracts recognisable before a reader opens a type. +# Evaluated top-to-bottom; the first matching rule wins, so every rule below +# that targets a modifier (async, const, static+readonly) is declared before +# the broader rule it would otherwise fall through to. dotnet_naming_rule.interfaces_must_be_prefixed_i.severity = suggestion dotnet_naming_rule.interfaces_must_be_prefixed_i.symbols = interfaces dotnet_naming_rule.interfaces_must_be_prefixed_i.style = i_pascal_case @@ -121,12 +226,55 @@ dotnet_naming_rule.types_must_be_pascal_case.style = pascal_case dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum, delegate dotnet_naming_style.pascal_case.capitalization = pascal_case +# Declared before non_private_members_must_be_pascal_case so an async method's +# suffix requirement is not shadowed by the broader rule. Any accessibility, +# so private async methods and local functions are covered too, not just +# public API. dotnet/roslyn#34833 (still open) means an interface-implementing +# or overriding async method is not always flagged - editor guidance, not a +# build gate, for that reason. +dotnet_naming_rule.async_methods_must_be_suffixed.severity = suggestion +dotnet_naming_rule.async_methods_must_be_suffixed.symbols = async_methods +dotnet_naming_rule.async_methods_must_be_suffixed.style = async_pascal_case +dotnet_naming_symbols.async_methods.applicable_kinds = method, local_function +dotnet_naming_symbols.async_methods.applicable_accessibilities = * +dotnet_naming_symbols.async_methods.required_modifiers = async +dotnet_naming_style.async_pascal_case.required_suffix = Async +dotnet_naming_style.async_pascal_case.capitalization = pascal_case + dotnet_naming_rule.non_private_members_must_be_pascal_case.severity = suggestion dotnet_naming_rule.non_private_members_must_be_pascal_case.symbols = non_private_members dotnet_naming_rule.non_private_members_must_be_pascal_case.style = pascal_case dotnet_naming_symbols.non_private_members.applicable_kinds = property, method, event dotnet_naming_symbols.non_private_members.applicable_accessibilities = public, internal, protected, protected_internal, private_protected +# Declared before private_fields_must_be_underscore_camel_case: a const or +# static-readonly field is PascalCase regardless of accessibility (BCL +# convention), which would otherwise be shadowed by the private-field rule +# below for the private subset. const and 'static, readonly' are reported as +# distinct modifier sets by the naming-rule engine, hence two rules. +dotnet_naming_rule.constants_must_be_pascal_case.severity = suggestion +dotnet_naming_rule.constants_must_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constants_must_be_pascal_case.style = pascal_case +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.applicable_accessibilities = * +dotnet_naming_symbols.constant_fields.required_modifiers = const + +dotnet_naming_rule.static_readonly_fields_must_be_pascal_case.severity = suggestion +dotnet_naming_rule.static_readonly_fields_must_be_pascal_case.symbols = static_readonly_fields +dotnet_naming_rule.static_readonly_fields_must_be_pascal_case.style = pascal_case +dotnet_naming_symbols.static_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.static_readonly_fields.applicable_accessibilities = * +dotnet_naming_symbols.static_readonly_fields.required_modifiers = static, readonly + +# non_private_members (above) covers properties/methods/events but not +# fields, and enum members are reported as fields too - both previously +# matched zero naming rule anywhere in this file. +dotnet_naming_rule.non_private_fields_must_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_fields_must_be_pascal_case.symbols = non_private_fields +dotnet_naming_rule.non_private_fields_must_be_pascal_case.style = pascal_case +dotnet_naming_symbols.non_private_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_fields.applicable_accessibilities = public, internal, protected, protected_internal, private_protected + dotnet_naming_rule.private_fields_must_be_underscore_camel_case.severity = suggestion dotnet_naming_rule.private_fields_must_be_underscore_camel_case.symbols = private_fields dotnet_naming_rule.private_fields_must_be_underscore_camel_case.style = underscore_camel_case @@ -145,6 +293,9 @@ dotnet_diagnostic.CS8762.severity = none [libs/**.cs] dotnet_diagnostic.IDE0005.severity = error +# IDE-visible companion to the already-enforced RS0048 (CESDK9003 MSBuild target +# plus PublicApiFileTests.cs): purely additive, same concern, fourth layer. +dotnet_public_api_analyzer.require_api_files = true [src/**.cs] dotnet_diagnostic.IDE0005.severity = error diff --git a/eng/Shipping.props b/eng/Shipping.props index d7ff060d..6e5277e8 100644 --- a/eng/Shipping.props +++ b/eng/Shipping.props @@ -3,10 +3,22 @@ net10.0 - + true + true + true + true + true true + + true All All diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs index 61a54231..41a9fb49 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs @@ -93,7 +93,7 @@ private static string CreateDefaultMessage(string operation, EngineMarshallingDi private static EngineMarshallingDirection ValidateDirection(EngineMarshallingDirection direction) { - if (direction != EngineMarshallingDirection.Argument && direction != EngineMarshallingDirection.Result) + if (direction is not EngineMarshallingDirection.Argument and not EngineMarshallingDirection.Result) { throw new ArgumentOutOfRangeException(nameof(direction), direction, "The marshalling direction is not defined."); diff --git a/libs/CheatEngine.SDK.Engine/Values/IndexBase.cs b/libs/CheatEngine.SDK.Engine/Values/IndexBase.cs index da7f5816..7f5b3ebe 100644 --- a/libs/CheatEngine.SDK.Engine/Values/IndexBase.cs +++ b/libs/CheatEngine.SDK.Engine/Values/IndexBase.cs @@ -69,7 +69,7 @@ public static int FromLuaKey(long luaKey) /// when the key is below one or the index would not fit an . public static bool TryFromLuaKey(long luaKey, out int zeroBasedIndex) { - if (luaKey < FirstLuaKey || luaKey > int.MaxValue + FirstLuaKey) + if (luaKey is < FirstLuaKey or > (int.MaxValue + FirstLuaKey)) { zeroBasedIndex = 0; return false; diff --git a/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs b/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs index 9b904e6c..ec7dada4 100644 --- a/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs +++ b/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs @@ -471,7 +471,7 @@ private static bool Disable() return true; } - bool cleanupSucceeded = false; + bool cleanupSucceeded; try { RunDisable(context!, plugin); diff --git a/libs/CheatEngine.SDK.Lua.Interop/Api/LuaApi.Constants.cs b/libs/CheatEngine.SDK.Lua.Interop/Api/LuaApi.Constants.cs index 49aac567..ff800ec7 100644 --- a/libs/CheatEngine.SDK.Lua.Interop/Api/LuaApi.Constants.cs +++ b/libs/CheatEngine.SDK.Lua.Interop/Api/LuaApi.Constants.cs @@ -17,7 +17,7 @@ public static unsafe partial class LuaApi /// LUAL_NUMSIZES: the size fingerprint luaL_checkversion compares, /// sizeof(lua_Integer) * 16 + sizeof(lua_Number). /// - public const int LUAL_NUMSIZES = sizeof(lua_Integer) * 16 + sizeof(lua_Number); + public const int LUAL_NUMSIZES = (sizeof(lua_Integer) * 16) + sizeof(lua_Number); // ---- limits and pseudo-indices (luaconf.h) ------------------------------------------------------------------- diff --git a/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs b/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs index 0e3440b3..9d4190d4 100644 --- a/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs +++ b/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs @@ -82,7 +82,7 @@ private static bool AcceptConverted(LuaState state, int index, bool acceptIntege bool accepted = state.TypeOf(index) switch { // lua_tointegerx already refused a non-integral, infinite or NaN float and one outside the long range. - LuaType.Number => value > -FloatExactLimit && value < FloatExactLimit, + LuaType.Number => value is > -FloatExactLimit and < FloatExactLimit, LuaType.String => acceptIntegerNumerals && state.TryReadUtf8(index, out ReadOnlySpan text) && IsIntegerNumeral(text), _ => false diff --git a/libs/CheatEngine.SDK.Lua/State/LuaState.Types.cs b/libs/CheatEngine.SDK.Lua/State/LuaState.Types.cs index 59e62d9a..800fc993 100644 --- a/libs/CheatEngine.SDK.Lua/State/LuaState.Types.cs +++ b/libs/CheatEngine.SDK.Lua/State/LuaState.Types.cs @@ -48,7 +48,7 @@ public ReadOnlySpan TypeName(int index) /// One C API call; never raises for a tag of . public ReadOnlySpan TypeName(LuaType type) { - Debug.Assert(type >= LuaType.None && type <= LuaType.Thread, "Not a Lua 5.3 type tag."); + Debug.Assert(type is >= LuaType.None and <= LuaType.Thread, "Not a Lua 5.3 type tag."); return MemoryMarshal.CreateReadOnlySpanFromNullTerminated(lua_typename(Pointer, (int) type)); } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs index ed0183a6..f0016a8c 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs @@ -527,7 +527,7 @@ private static bool IsFourPartVersion(string value) continue; } - if (character < '0' || character > '9') + if (character is < '0' or > '9') { return false; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs index ee692c81..d845190a 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs @@ -86,7 +86,7 @@ public static string Escape(string identifier) private static bool IsStart(char c) { - return c is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or '_'; + return c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '_'; } private static bool IsPart(char c) diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs index cc8147cd..e72de6bd 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs @@ -80,8 +80,8 @@ private static bool TryDescribe(IMethodSymbol method, MethodDeclarationSyntax? d valid &= DescribeParameters(method.Parameters, arguments, results); LuaCallForm form = results.Count == 0 ? LuaCallForm.Throwing : LuaCallForm.Try; - LuaValueKind? returnKind = null; - bool returnNullable = false; + LuaValueKind? returnKind; + bool returnNullable; valid &= TryDescribeReturn(method, form, out returnKind, out returnNullable); model = new LuaObjectMethodModel( diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs index 5e3513fa..4af51e2a 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs @@ -60,11 +60,11 @@ public static LuaObjectPropertyModel Parse(GeneratorAttributeSyntaxContext conte private static bool TryDescribe(IPropertySymbol property, PropertyDeclarationSyntax? declaration, out LuaObjectPropertyModel model) { - LuaValueKind kind = default; - bool isNullable = false; - string modifiers = string.Empty; + LuaValueKind kind; + bool isNullable; bool typeIsSupported = LuaValueKindMapper.TryMap(property.Type, out kind, out isNullable) && LuaValueKinds.CanBeResult(kind); + string modifiers; bool definitionIsSupported = IsSupportedDefinition(property, declaration, typeIsSupported, out modifiers); bool accessorsAreSupported = TryDescribeAccessors(declaration, out bool hasGetter, out string getterModifiers, diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs index 52ab476a..1a4f4cf0 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs @@ -446,7 +446,7 @@ private static bool IsPascalIdentifier(string value) for (int i = 1; i < value.Length; i++) { char character = value[i]; - if (character is not (>= 'A' and <= 'Z' or >= 'a' and <= 'z' or >= '0' and <= '9')) + if (character is not ((>= 'A' and <= 'Z') or (>= 'a' and <= 'z') or (>= '0' and <= '9'))) { return false; } @@ -932,7 +932,7 @@ private void SkipWhitespace() while (_position < _text.Length) { char character = _text[_position]; - if (character != ' ' && character != '\t' && character != '\r' && character != '\n') + if (character is not ' ' and not '\t' and not '\r' and not '\n') { return; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/EquatableArray.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/EquatableArray.cs index 0aedcf79..735067c5 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/EquatableArray.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/EquatableArray.cs @@ -129,7 +129,7 @@ public override int GetHashCode() for (int i = 0; i < items.Length; i++) { T? item = items[i]; - hash = unchecked(hash * 31 + (item is null ? 0 : comparer.GetHashCode(item))); + hash = unchecked((hash * 31) + (item is null ? 0 : comparer.GetHashCode(item))); } return hash; diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs index 78e634dd..a89502bd 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs @@ -129,7 +129,7 @@ private static string Build(string typeName, string suffix) bool replaced = false; foreach (char c in typeName) { - if (c is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or >= '0' and <= '9' or '.' or '_') + if (c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or (>= '0' and <= '9') or '.' or '_') { builder.Append(c); } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs index 23ce6c45..e8da28ef 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs @@ -61,7 +61,7 @@ public static bool IsReservedWord(string name) private static bool IsIdentifierStart(char c) { - return c is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or '_'; + return c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '_'; } private static bool IsIdentifierPart(char c) diff --git a/tests/CheatEngine.SDK.Abi.Tests/Managed/ManagedExportedFunctionsTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Managed/ManagedExportedFunctionsTests.cs index 7d299129..bb76a09b 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Managed/ManagedExportedFunctionsTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Managed/ManagedExportedFunctionsTests.cs @@ -50,7 +50,7 @@ public void Overlay_on_a_raw_host_record_on_64_bit_reads_every_slot() Unsafe.WriteUnaligned(raw, 48); for (int slot = 1; slot <= 5; slot++) { - Unsafe.WriteUnaligned(raw + slot * 8, (ulong) slot * 0x1000_0000_1000UL); + Unsafe.WriteUnaligned(raw + (slot * 8), (ulong) slot * 0x1000_0000_1000UL); } ManagedExportedFunctions copy = *(ManagedExportedFunctions*) raw; diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs index 6d800d08..4bda49d2 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs @@ -81,7 +81,7 @@ public void RegisterFunction_and_ChangeRegistersAtAddress_accept_the_declared_st [Fact] public void Prefix_stops_before_the_pointer_to_pointer_hook_suffix() { - FieldInfo[] fields = typeof(ExportedFunctionsPrefix).GetFields(BindingFlags.Instance | BindingFlags.Public); + _ = typeof(ExportedFunctionsPrefix).GetFields(BindingFlags.Instance | BindingFlags.Public); Assert.Null(typeof(ExportedFunctionsPrefix).GetField("ReadProcessMemory", BindingFlags.Instance | BindingFlags.Public)); diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorTests.cs b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorTests.cs index 7900b3b1..354ccd85 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorTests.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorTests.cs @@ -215,7 +215,7 @@ public void Emulator_facts_contain_no_absolute_path() return; } - NativeHostEmulatorResult result = RunSeparateComponentScenario(emulatorDirectory, out string factsPath); + NativeHostEmulatorResult result = RunSeparateComponentScenario(emulatorDirectory, out _); foreach (KeyValuePair fact in result.Facts) { diff --git a/tests/CheatEngine.SDK.LivePlugin/MemoryBindings.cs b/tests/CheatEngine.SDK.LivePlugin/MemoryBindings.cs index f84128d0..64b1475b 100644 --- a/tests/CheatEngine.SDK.LivePlugin/MemoryBindings.cs +++ b/tests/CheatEngine.SDK.LivePlugin/MemoryBindings.cs @@ -23,6 +23,7 @@ internal static partial class MemoryBindings /// internal static bool TryReadInt32(nuint address, out int value) { + value = 0; return TryReadInt32Raw(address, true, out value); } diff --git a/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStateTests.cs b/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStateTests.cs index 7a132ecc..ce265b8b 100644 --- a/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStateTests.cs +++ b/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStateTests.cs @@ -8,13 +8,13 @@ public sealed class LiveProbeStateTests public void CaptureHostProfile_when_authorization_expires_after_enable_returns_fresh_denial() { int evaluationCount = 0; - Func evaluateAuthorization = () => + AuthorizationDecision evaluateAuthorization() { evaluationCount++; return evaluationCount == 1 ? AllowedAuthorization() : AuthorizationDecision.Denied("The authorization manifest has expired."); - }; + } LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => 401); bool wasCaptured = false; @@ -36,13 +36,13 @@ public void CaptureHostProfile_when_authorization_expires_after_enable_returns_f public void CaptureHostProfile_when_target_image_changes_after_enable_returns_fresh_denial() { int evaluationCount = 0; - Func evaluateAuthorization = () => + AuthorizationDecision evaluateAuthorization() { evaluationCount++; return evaluationCount == 1 ? AllowedAuthorization() : AuthorizationDecision.Denied("The declared target SHA-256 differs from its live process image."); - }; + } LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => 401); bool wasCaptured = false; @@ -64,11 +64,11 @@ public void CaptureHostProfile_when_target_image_changes_after_enable_returns_fr public void CaptureHostProfile_when_ce_target_pid_changes_after_enable_returns_denial() { int evaluationCount = 0; - Func evaluateAuthorization = () => + AuthorizationDecision evaluateAuthorization() { evaluationCount++; return AllowedAuthorization(); - }; + } LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => 401); bool wasCaptured = false; @@ -90,13 +90,13 @@ public void CaptureHostProfile_when_ce_target_pid_changes_after_enable_returns_d public void CaptureHostProfile_when_fresh_authorization_and_pid_match_passes_fresh_decision_to_capture() { int evaluationCount = 0; - Func evaluateAuthorization = () => + AuthorizationDecision evaluateAuthorization() { evaluationCount++; return evaluationCount == 1 ? AuthorizationDecision.Denied("The manifest was not present during enable.") : AllowedAuthorization(); - }; + } LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => throw new InvalidOperationException("The denied enable state must not read CE's PID.")); @@ -113,13 +113,13 @@ public void CaptureHostProfile_when_fresh_authorization_and_pid_match_passes_fre public void TryRequireRuntimeAuthorization_when_manifest_expires_after_enable_rechecks_and_denies() { int evaluationCount = 0; - Func evaluateAuthorization = () => + AuthorizationDecision evaluateAuthorization() { evaluationCount++; return evaluationCount == 1 ? AllowedAuthorization() : AuthorizationDecision.Denied("The authorization manifest has expired."); - }; + } LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => 401); bool isAllowed = LiveProbeState.TryRequireRuntimeAuthorization(evaluateAuthorization, @@ -137,11 +137,11 @@ public void TryRequireRuntimeAuthorization_when_manifest_expires_after_enable_re public void TryRequireRuntimeAuthorization_when_ce_target_pid_changes_after_enable_rechecks_and_denies() { int evaluationCount = 0; - Func evaluateAuthorization = () => + AuthorizationDecision evaluateAuthorization() { evaluationCount++; return AllowedAuthorization(); - }; + } LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => 401); bool isAllowed = LiveProbeState.TryRequireRuntimeAuthorization(evaluateAuthorization, static () => 402, diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs index 80f3f828..bca49f83 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs @@ -94,7 +94,7 @@ private static bool HasDelayImports(string path) uint directories = ReadUInt32(image, optionalOffset + 108); Require(directories > 13, "The native bridge has no delay-import directory slot."); - int delayImportDirectoryOffset = optionalOffset + 112 + 13 * 8; + int delayImportDirectoryOffset = optionalOffset + 112 + (13 * 8); return ReadUInt32(image, delayImportDirectoryOffset) != 0 || ReadUInt32(image, delayImportDirectoryOffset + sizeof(uint)) != 0; } @@ -132,7 +132,7 @@ private static List ReadExportedNames(string path) for (uint i = 0u; i < namesCount; i++) { - uint nameRva = ReadUInt32(image, checked(namesOffset + (int) i * sizeof(uint))); + uint nameRva = ReadUInt32(image, checked(namesOffset + ((int) i * sizeof(uint)))); result.Add(ReadAsciiZ(image, RvaToFileOffset(image, nameRva, sizeOfHeaders, sectionOffset, sectionCount))); } @@ -193,7 +193,7 @@ private static int RvaToFileOffset(byte[] image, uint rva, uint sizeOfHeaders, i for (int i = 0; i < sectionCount; i++) { - int offset = checked(sectionOffset + i * 40); + int offset = checked(sectionOffset + (i * 40)); Require(offset <= image.Length - 40, "The native bridge has a truncated section header."); uint virtualSize = ReadUInt32(image, offset + 8); uint virtualAddress = ReadUInt32(image, offset + 12); diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs index d4aa61d4..3ec93411 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs @@ -61,7 +61,7 @@ private static int OperandSize(OperandType type, byte[] il, int offset) OperandType.ShortInlineBrTarget or OperandType.ShortInlineI or OperandType.ShortInlineVar => 1, OperandType.InlineVar => 2, OperandType.InlineI8 or OperandType.InlineR => 8, - OperandType.InlineSwitch => 4 + 4 * BitConverter.ToInt32(il, offset), + OperandType.InlineSwitch => 4 + (4 * BitConverter.ToInt32(il, offset)), _ => 4 }; } diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness/PortableExecutableExportReader.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness/PortableExecutableExportReader.cs index c87820ac..3976737c 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness/PortableExecutableExportReader.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness/PortableExecutableExportReader.cs @@ -77,7 +77,7 @@ private static int ResolveFileOffset(PEHeaders headers, int relativeVirtualAddre } long fileOffset = section.PointerToRawData + (relativeVirtualAddress - sectionStart); - if (fileOffset < 0 || fileOffset > int.MaxValue) + if (fileOffset is < 0 or > int.MaxValue) { throw new InvalidOperationException("The export directory resolves outside the file."); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs index 2803321c..e4cb4d9d 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs @@ -61,7 +61,7 @@ public void Generator_display_name_is_escaped_into_a_u8_literal(string caseKey) // Holds because the plugin type of these cases (Demo.DemoPlugin) is ASCII: whatever the display name is, the // literal adds no other character. Identifiers are written as declared (PluginLocationTests, non-ASCII case). Assert.All(generated, - static c => Assert.True(c is '\n' or >= ' ' and <= '~', + static c => Assert.True(c is '\n' or (>= ' ' and <= '~'), $"Non-ASCII character U+{(int) c:X4} in generated text.")); run.AssertCompilesClean(); } From 09df927bca790cde317f532220e2ae6d29b22da5 Mon Sep 17 00:00:00 2001 From: AriusII Date: Wed, 23 Sep 2026 23:06:40 +0200 Subject: [PATCH 2/4] reformatage update --- CheatEngine.SDK.slnx | 246 +++++++++--------- Directory.Packages.props | 2 +- README.md | 21 +- RELEASING.md | 44 ++-- SECURITY.md | 10 +- .../Plugin/PluginClassRewriter.cs | 8 +- .../Plugin/PluginClassShapeCodeFixProvider.cs | 20 +- .../Usage/ExceptionGuardRewriter.cs | 2 +- ...nmanagedCallersOnlyGuardCodeFixProvider.cs | 36 +-- .../Generation/LuaBindingAnalyzer.cs | 4 +- .../Generation/LuaFunctionDuplicateState.cs | 2 +- .../Generation/LuaGlobalProblemText.cs | 3 +- .../Generation/LuaObjectBindingAnalyzer.cs | 52 ++-- .../Plugin/CheatEnginePluginAnalyzer.cs | 40 +-- .../Plugin/ClassicNativeExportAnalyzer.cs | 6 +- .../Plugin/PluginCompilationState.cs | 2 +- .../Usage/ExceptionGuard.cs | 50 ++-- .../Usage/HostWidthPointerSizeAnalyzer.cs | 26 +- .../PluginLifecycleAndOwnershipAnalyzer.cs | 16 +- .../UnmanagedCallersOnlyGuardAnalyzer.cs | 2 +- .../WellKnown/SdkSymbolResolver.cs | 2 +- analyzers/docs/CESDK5010.md | 3 +- analyzers/docs/README.md | 68 ++--- exemples/05-aob-scans/README.md | 3 +- exemples/07-address-list/README.md | 3 +- .../Native/AddressListPluginInit.cs | 3 +- .../BoundedDebugEventObservationBuffer.cs | 2 +- .../Native/ClassicDebugEventDispatcher.cs | 6 +- .../ClassicExportedFunctionsPrefixReader.cs | 3 +- .../ClassicExportedFunctionsSlotReader.cs | 3 +- .../Native/ClassicSlotObservation.cs | 4 +- .../Native/ExportedFunctionsPrefix.cs | 3 +- .../Native/NativeExportNames.cs | 3 +- .../Native/PluginType0Record.cs | 3 +- libs/CheatEngine.SDK.Abi/README.md | 49 ++-- .../AddressList/AddressListCalls.cs | 2 +- .../AddressList/AddressListMutations.cs | 2 +- .../MemoryRecordActivationOutcome.cs | 3 +- .../Allocation/AllocatedRegion.cs | 4 +- .../Allocation/TargetMemoryAllocator.cs | 2 +- .../Assembly/AutoAssemblerOptions.cs | 6 +- .../Assembly/AutoAssemblerPatcher.cs | 18 +- .../Assembly/InstructionAssembly.cs | 4 +- .../Assembly/InstructionDisassembler.cs | 6 +- .../Assembly/InstructionProfiles.cs | 4 +- .../Enums/CEEnumNames.cs | 4 +- .../EngineGlobalUnavailableException.cs | 2 +- .../Errors/EngineLuaException.cs | 2 +- .../Errors/EngineMarshallingException.cs | 4 +- .../Errors/EngineResourceHandoffException.cs | 4 +- .../Errors/EngineTargetIdentityException.cs | 2 +- .../Inspection/EngineInspection.cs | 42 +-- .../SymbolListRegistrationHandoffException.cs | 5 +- .../Inspection/SymbolListRegistrationLease.cs | 6 +- .../SymbolListRegistrationReleaseOutcome.cs | 6 +- .../Inspection/SymbolLists.cs | 6 +- .../Inspection/SymbolRegistrationLease.cs | 3 +- .../SymbolRegistrationReleaseOutcome.cs | 6 +- .../Inspection/SymbolRegistry.cs | 8 +- .../Inspection/SymbolTableReader.cs | 2 +- .../Memory/HostMemory.cs | 24 +- .../Memory/MemoryLua.cs | 4 +- .../Memory/TargetMemory.cs | 32 +-- .../Objects/EngineResourceOrigin.cs | 2 +- libs/CheatEngine.SDK.Engine/Objects/Owned.cs | 18 +- .../Objects/StringLists.cs | 4 +- .../Processes/RuntimeHostOperations.cs | 7 +- .../Processes/RuntimeObservations.cs | 11 +- .../Processes/RuntimeProcessOperations.cs | 2 +- .../Processes/TargetArchitectureProbe.cs | 18 +- libs/CheatEngine.SDK.Engine/README.md | 148 ++++++----- .../Runtime/CheatEngineHostObservation.cs | 5 +- .../Runtime/CheatEngineOperatingSystem.cs | 3 +- .../Runtime/CheatEngineVersion.cs | 6 +- .../Runtime/RuntimeInfo.cs | 21 +- .../Runtime/TargetArchitectureObservation.cs | 20 +- .../Runtime/TargetBackend.cs | 21 +- .../Scanning/Aob/AobBoundedScan.cs | 13 +- .../Scanning/Aob/AobFirstFoundScan.cs | 7 +- .../Scanning/Aob/AobScanBounds.cs | 17 +- .../Scanning/Aob/AobScanOptions.cs | 4 +- .../Scanning/Aob/AobScanOutcomeKind.cs | 4 +- .../Scanning/Aob/AobScanner.cs | 11 +- .../Scanning/Values/FirstScanRequest.cs | 16 +- .../Scanning/Values/MemoryScanSession.cs | 65 ++--- .../Scanning/Values/MemoryScanSessions.cs | 4 +- .../Values/MemoryScanStateException.cs | 2 +- .../Values/MemoryScanTerminationStatus.cs | 3 +- .../Tables/CheatTableFiles.cs | 3 +- .../Targets/TargetSelection.cs | 6 +- .../Targets/TargetSelectionObservation.cs | 3 +- libs/CheatEngine.SDK.Engine/Values/Address.cs | 2 +- .../Values/IndexBase.cs | 2 +- .../Bootstrap/PluginHost.Lifecycle.cs | 14 +- .../Bootstrap/PluginHost.cs | 4 +- .../Diagnostics/LoadIdentification.cs | 16 +- .../Threading/MainThreadDispatcher.cs | 6 +- .../CheatEngine.SDK.Lua.Interop.csproj | 2 +- .../GlobalUsings.cs | 1 + .../Protected/LuaBridgeContract.cs | 20 +- .../Callbacks/LuaCallback.cs | 4 +- .../Callbacks/LuaHostSubscription.cs | 10 +- .../Callbacks/LuaHostSubscriptionRegistry.cs | 4 +- .../CompilerServices/LuaCallSupport.cs | 5 +- .../Marshalling/Int64Marshaller.cs | 3 +- .../Marshalling/LuaIntegerReader.cs | 6 +- .../Marshalling/LuaOptional.cs | 5 +- libs/CheatEngine.SDK.Lua/References/LuaRef.cs | 4 +- .../Registration/LuaRegistrationSet.cs | 2 +- .../Runtime/LuaAdmissionStatus.cs | 5 +- .../Runtime/LuaHostBinding.cs | 2 +- .../CheatEngine.SDK.Lua/Runtime/LuaRuntime.cs | 52 ++-- .../Runtime/LuaThreadAdmission.cs | 3 +- .../State/LuaState.Tables.cs | 2 +- .../cheatengine_sdk_lua_bridge.c | 2 +- .../AnalyzerReleases.Unshipped.md | 2 +- .../Emit/EngineApiFileEmitter.cs | 3 +- .../Model/SpecFiles.cs | 15 +- .../Parsing/SpecFileParser.cs | 101 +++---- .../Parsing/SpecIdentifiers.cs | 2 +- .../README.md | 88 +++---- .../Emit/BootstrapEmitter.cs | 4 +- .../Parsing/EntryPointContractSymbols.cs | 2 +- .../EntryPointDeclaredDiagnosticIds.cs | 22 +- .../Parsing/EntryPointGeneratedIdentity.cs | 4 +- .../Emit/LuaObjectMembersFileEmitter.cs | 2 +- .../Model/LuaFunctionModel.cs | 2 +- .../Model/LuaFunctionTables.cs | 5 +- .../Model/LuaGlobalModel.cs | 2 +- .../Model/LuaGlobalTables.cs | 5 +- .../Model/LuaObjectMembersTables.cs | 5 +- .../Parsing/ContainingTypeParser.cs | 2 +- .../LuaBindingsDeclaredDiagnosticIds.cs | 18 +- .../Parsing/LuaClassParser.cs | 18 +- .../Parsing/LuaFunctionParser.cs | 6 +- .../Parsing/LuaGlobalParser.cs | 2 +- .../Parsing/LuaObjectMethodParser.cs | 48 ++-- .../Parsing/LuaObjectPropertyParser.cs | 36 ++- .../README.md | 22 +- .../ProtectedOperationCatalogParser.cs | 10 +- .../GeneratedCodeText.cs | 8 +- .../HintNames.cs | 4 +- .../Parsing/ContainingTypeShape.cs | 2 +- .../LuaBindings/Parsing/Identifiers.cs | 2 +- .../Parsing/LuaClassGeneratedNames.cs | 14 +- .../LuaBindings/Parsing/LuaContractTypes.cs | 10 +- .../LuaBindings/Parsing/LuaFunctionShape.cs | 10 +- .../LuaBindings/Parsing/LuaGlobalShape.cs | 33 ++- .../Parsing/LuaMarshallerResolver.cs | 24 +- .../LuaBindings/Parsing/LuaValueKindMapper.cs | 22 +- .../LuaEmit/LuaArgumentModel.cs | 12 +- .../LuaEmit/LuaGlobalCallEmitter.cs | 4 +- .../LuaEmit/LuaGlobalCallModel.cs | 6 +- .../LuaEmit/LuaNames.cs | 2 +- .../LuaEmit/LuaResultModel.cs | 2 +- .../LuaEmit/LuaThunkEmitter.cs | 2 +- .../LuaEmit/LuaThunkModel.cs | 2 +- .../Shapes/PluginShape.cs | 10 +- .../CompatibilitySuppressions.xml | 134 +++++----- src/CheatEngine.SDK/README.md | 20 +- .../AbiBoundaryValueTests.cs | 6 +- .../AssemblyConformanceTests.cs | 6 +- .../FieldLayout/FieldLayoutContractTests.cs | 30 ++- .../Fixture/NativeAbiFixtureContractTests.cs | 4 +- .../NativeAbiFixtureManagedComparisonTests.cs | 2 +- .../Managed/PluginInitRecordTests.cs | 2 +- .../ClassicDebugEventDispatcherTests.cs | 6 +- ...assicExportedFunctionsPrefixReaderTests.cs | 6 +- ...ClassicExportedFunctionsSlotReaderTests.cs | 54 ++-- .../Native/ClassicSlotRegistryPrefixTests.cs | 15 +- .../Native/ExportedFunctionsPrefixTests.cs | 12 +- .../Native/PluginType0RecordTests.cs | 2 +- .../Native/SelectedRecordOracleTests.cs | 13 +- tests/CheatEngine.SDK.Abi.Tests/README.md | 27 +- .../Support/AbiStructures.cs | 3 +- .../Support/ClassicSlotRegistry.cs | 6 +- .../Support/FieldKind.cs | 5 +- .../Support/FieldLayoutExpectations.cs | 6 +- .../Support/FieldLayoutGate.cs | 6 +- .../Support/FieldLayoutRow.cs | 7 +- .../LuaDirectApiBoundaryGuardTests.cs | 60 ++--- .../Diagnostics/DiagnosticCatalogTests.cs | 6 +- .../Generation/LuaBindingAnalyzerTests.cs | 115 +++++--- .../LuaObjectBindingAnalyzerTests.cs | 22 +- .../Infrastructure/CodeFixVerifier.cs | 3 +- .../LocalFrameworkReferences.cs | 4 +- .../LocalFrameworkReferencesTests.cs | 2 +- .../Infrastructure/RepositoryLayout.cs | 4 +- .../ClassicNativeExportAnalyzerTests.cs | 37 +-- .../HostWidthPointerSizeAnalyzerTests.cs | 3 +- .../BenchFunctions.cs | 2 +- .../CallbackBenchmarks.cs | 2 +- .../EngineApiIncrementalBenchmarks.cs | 2 +- .../GlobalCallBenchmarks.cs | 2 +- .../MemoryScalarBenchmarks.cs | 10 +- .../Support/FakeHostRuntime.cs | 2 +- .../AddressList/AddressListExitTests.cs | 16 +- .../AddressList/AddressListTestHost.cs | 70 ++--- .../MemoryRecordActivationTests.cs | 8 +- .../Allocation/AllocatedRegionTests.cs | 40 +-- ...uaTargetMemoryAllocationOperationsTests.cs | 2 +- .../Allocation/TargetMemoryAllocatorTests.cs | 103 +++----- .../AutoAssemblerDisableInfoSnapshotTests.cs | 32 ++- .../Assembly/AutoAssemblerOutcomeTests.cs | 34 ++- .../Assembly/AutoAssemblerPatcherTests.cs | 3 +- .../Assembly/InstructionOperationsTests.cs | 10 +- .../Inspection/EngineInspectionTests.cs | 10 +- .../Inspection/SymbolLeaseReplacementTests.cs | 12 +- .../Inspection/SymbolListTests.cs | 28 +- .../Inspection/SymbolRegistryTests.cs | 36 +-- .../Memory/AddressTypeSeparationTests.cs | 2 +- .../Memory/MemoryScalarsFidelityTests.cs | 1 - .../Objects/OwnershipSurfaceTests.cs | 4 +- .../Processes/ProcessOperationStatusTests.cs | 3 +- .../RuntimeProcessOperationsTests.cs | 11 +- tests/CheatEngine.SDK.Engine.Tests/README.md | 4 +- .../Runtime/RuntimeCapabilityProbesTests.cs | 1 - .../Runtime/RuntimeContractsTests.cs | 10 +- .../Runtime/RuntimeObservationsTests.cs | 6 +- .../Scanning/Aob/AobBoundedScanTests.cs | 45 ++-- .../Scanning/Aob/AobFirstFoundScanTests.cs | 11 +- .../Aob/AobScannerPublicationTests.cs | 11 +- .../Scanning/MemScanTestHost.cs | 12 +- .../Scanning/MemoryScanSessionFactoryTests.cs | 10 +- .../Scanning/MemoryScanSessionTests.cs | 20 +- .../Scanning/ScanExperimentalApiTests.cs | 7 +- .../Values/MemoryScanSessionBatteryTests.cs | 10 +- .../Values/MemoryScanSessionDeadlineTests.cs | 24 +- .../Values/MemoryScanSessionReleaseTests.cs | 10 +- .../Support/FakeHost.Rt.cs | 2 +- .../Support/FakeHost.SRes.cs | 8 +- .../Support/FakeHost.Scanning.cs | 3 +- .../Support/FakeHost.cs | 16 +- .../Tables/CheatTableFilesTests.cs | 8 +- .../Targets/TargetSelectionTests.cs | 5 +- .../Coexistence/CoexistencePluginLayout.cs | 10 +- .../Coexistence/NativeHostEmulatorAlcRoute.cs | 2 +- .../Coexistence/NativeHostEmulatorRunner.cs | 15 +- .../Coexistence/NativeHostEmulatorTests.cs | 45 ++-- .../Diagnostics/HostLogContainmentTests.cs | 4 +- .../Diagnostics/LoadIdentificationTests.cs | 21 +- .../Lifecycle/DisablePluginTests.cs | 200 +++++++------- .../Support/RecordingPlugin.cs | 8 +- .../Threading/MainThreadTests.cs | 118 ++++----- .../PluginA/CoexistencePluginAFunctions.cs | 2 +- .../PluginB/CoexistencePluginBFunctions.cs | 2 +- .../LiveFunctions.cs | 2 +- tests/CheatEngine.SDK.LivePlugin/README.md | 8 +- .../LiveProbeStateTests.cs | 12 + .../LiveProbeStatusTests.cs | 6 +- .../ProbeHostGlobals.cs | 2 +- .../CheatEngine.SDK.LiveProbe.Tests/README.md | 12 +- .../CE77LiveProbeBootstrap.cs | 8 +- .../Ce77LiveProbePlugin.cs | 5 +- .../HostProfileObservation.cs | 6 +- .../LiveProbeAuthorization.cs | 28 +- .../LiveProbeFaultInjection.cs | 8 +- .../LiveProbeState.cs | 46 +--- .../LiveProbeStatusReport.cs | 3 +- .../CheatEngine.SDK.LiveProbe/ProbeConsole.cs | 2 +- tests/CheatEngine.SDK.LiveProbe/README.md | 68 ++--- .../Program.cs | 10 +- .../Initialization/LuaApiBoundTableTests.cs | 2 +- .../Protected/LuaBridgeContractTests.cs | 2 +- .../LuaInteropPrimitiveMatrixTests.cs | 46 ++-- .../README.md | 3 +- .../RoundTrips/CallTests.cs | 8 +- .../Support/IlReader.cs | 2 +- .../Allocation/ZeroAllocationTests.cs | 6 +- .../Callbacks/LuaCallbackTests.cs | 5 +- .../Callbacks/LuaHostSubscriptionTests.cs | 24 +- .../LuaCallSupportOptionalTests.cs | 19 +- .../Generated/MemoryBindings.cs | 2 +- .../Marshalling/LuaOptionalTests.cs | 3 +- .../Protected/NativeFailureProcessTests.cs | 11 +- .../Runtime/LuaExternalResetDetectionTests.cs | 8 +- .../LibraryProbeContractTests.cs | 9 +- ...NativeAotLibraryProbeExportSurfaceTests.cs | 6 +- .../PortableExecutableExportReaderTests.cs | 4 +- .../README.md | 3 +- .../Support/BridgeImage.cs | 3 +- .../LibraryProbeContract.cs | 4 +- .../Program.cs | 7 +- .../README.md | 7 +- .../ImageScanner.cs | 2 +- .../Program.cs | 4 +- .../README.md | 29 ++- .../ReadyRecord.cs | 3 +- .../TargetLayout.cs | 3 +- .../TargetMemory.cs | 6 +- .../Abi/AbiRouteSeparationTests.cs | 27 +- .../Abi/ClassicSlotRegistryContract.cs | 19 +- .../Abi/ClassicSlotRegistryDocumentTests.cs | 155 +++++++---- .../Abi/NativeAotProfileDocumentTests.cs | 23 +- .../Abi/RepositoryDocument.cs | 5 +- .../ApiGates/ApiGateDiagnosticTests.cs | 27 +- .../Diagnostics/ApiDiagnosticIdTests.cs | 36 +-- .../Generation/GeneratorInventoryTests.cs | 4 +- .../DependabotConfigurationTests.cs | 21 +- .../Governance/GovernanceDocumentTests.cs | 94 ++++--- .../Governance/GovernanceWorkflowTests.cs | 114 +++++--- .../Governance/PwshResult.cs | 3 +- .../Governance/PwshScript.cs | 12 +- .../Governance/TemporaryDirectory.cs | 14 +- .../Governance/YamlDocument.cs | 6 +- .../ConcurrencyContractDocumentationTests.cs | 27 +- .../NativeHostEmulatorScriptTests.cs | 23 +- .../Infrastructure/RepositoryRoot.cs | 4 +- .../LockFiles/LockFileTests.cs | 12 +- .../LuaBridge/LuaApiUseScanner.cs | 4 +- .../LuaBridge/LuaBridgeDocuments.cs | 5 +- .../LuaInteropPrimitiveMatrixDocumentTests.cs | 67 +++-- .../ProtectedOperationCatalogTests.cs | 50 ++-- .../Ownership/OwnershipPolicyTests.cs | 14 +- .../PublicApi/EnumContractTests.cs | 48 ++-- .../PublicApi/PublicApiDeclarations.cs | 9 +- .../PublicApi/PublicApiLibrary.cs | 2 +- .../README.md | 58 +++-- .../Release/ReleaseWorkflow.cs | 10 +- .../Release/ReleaseWorkflowContractTests.cs | 75 ++++-- .../Runtime/RuntimeCapabilitySpecTests.cs | 22 +- .../QualificationHarnessShapeTests.cs | 14 +- .../Toolchain/ToolchainPinTests.cs | 10 +- .../Workflows/WorkflowContract.cs | 7 +- .../WorkflowContractTests.BuildTest.cs | 86 +++--- .../Workflows/WorkflowContractTests.Gate.cs | 48 ++-- .../WorkflowContractTests.Hygiene.cs | 22 +- .../Workflows/WorkflowContractTests.Lint.cs | 9 +- .../WorkflowContractTests.Restore.cs | 22 +- .../Workflows/WorkflowContractTests.Supply.cs | 15 +- .../Workflows/WorkflowContractTests.cs | 2 +- .../Generator/DiagnosticsTests.cs | 38 +-- .../Generator/EmissionTests.cs | 25 +- .../EngineApiDiagnosticCatalogTests.cs | 13 +- .../Generator/IncrementalityTests.cs | 6 +- .../Infrastructure/GeneratedAssembly.cs | 4 +- .../LocalFrameworkReferences.cs | 4 +- .../Infrastructure/ModelGraph.cs | 2 +- .../Infrastructure/ProductionSpecs.cs | 2 +- .../Infrastructure/SpecSources.cs | 12 +- .../Parsing/ProductionSpecsTests.cs | 12 +- .../Parsing/SpecFileParserTests.cs | 57 ++-- .../Generator/ContractIdentityTests.cs | 6 +- .../Generator/NameEscapingTests.cs | 2 +- .../Generator/NominalOutputTests.cs | 7 +- .../Generator/RealAssemblyCompilationTests.cs | 6 +- .../Infrastructure/GeneratorRun.cs | 6 +- .../Infrastructure/LoadedBootstrap.cs | 2 +- .../LocalFrameworkReferences.cs | 4 +- .../Infrastructure/ModelGraph.cs | 2 +- .../Model/BootstrapModelTests.cs | 25 +- .../LuaGlobalOptionalArgumentEndToEndTests.cs | 7 +- .../LuaGlobalQ22MatrixEndToEndTests.cs | 3 +- .../LuaGlobalResultCountEndToEndTests.cs | 17 +- .../Generator/ContainingTypeTests.cs | 16 +- .../Generator/DefaultVerifierTests.cs | 3 +- .../Generator/IncrementalityTests.cs | 11 +- .../Generator/LuaFunctionOutputTests.cs | 8 +- .../Generator/LuaGlobalOutputTests.cs | 15 +- .../Generator/LuaObjectOutputTests.cs | 2 +- .../Generator/NoOutputTests.cs | 57 ++-- .../Generator/PartialMethodSignatureTests.cs | 24 +- .../Infrastructure/FidelityBindingSources.cs | 82 +++--- .../Infrastructure/GeneratorRun.cs | 6 +- .../LocalFrameworkReferences.cs | 4 +- .../Infrastructure/ModelGraph.cs | 2 +- .../Infrastructure/OptionalBindingSources.cs | 82 +++--- .../Model/LuaFunctionTablesTests.cs | 8 +- .../Model/LuaGlobalTablesTests.cs | 15 +- .../SharedCode/HintNamesTests.cs | 2 +- .../SharedCode/LuaApiNamesTests.cs | 4 +- .../SharedCode/LuaGlobalCallEmitterTests.cs | 12 +- .../SharedCode/LuaThunkEmitterTests.cs | 4 +- .../Generator/CatalogDiagnosticsTests.cs | 15 +- .../Generator/CatalogEmissionTests.cs | 14 +- .../NativeLua/NativeLuaProbe.cs | 2 +- .../NativeLua/PartialLuaModule.cs | 40 +-- .../ProjectDependencyDirectionTests.cs | 14 +- .../Build/NativeAotProfileTargetTests.cs | 38 +-- .../Infrastructure/CommittedFile.cs | 13 +- .../Infrastructure/EntryPointProbe.cs | 4 +- .../Infrastructure/PackagedUmbrellaFixture.cs | 39 +-- .../Infrastructure/ProcessRunner.cs | 5 +- .../Infrastructure/RepositoryLayout.cs | 4 +- .../Infrastructure/UmbrellaPackageSource.cs | 6 +- .../Packaging/BridgeAuditManifestTests.cs | 30 ++- .../Packaging/CleanConsumerIsolationTests.cs | 5 +- .../Packaging/ConsumerManifestRuleTests.cs | 8 +- .../Packaging/ConsumerManifestRules.cs | 19 +- .../Packaging/LivePluginClosureTests.cs | 39 ++- .../Packaging/PackageProvenanceTests.cs | 3 +- .../Packaging/PackagedUmbrellaTraitTests.cs | 23 +- .../Packaging/SupplyChainPackageTests.cs | 23 +- .../Packaging/UmbrellaPackageSourceTests.cs | 3 +- tests/CheatEngine.SDK.Tests/README.md | 18 +- 395 files changed, 3620 insertions(+), 2947 deletions(-) diff --git a/CheatEngine.SDK.slnx b/CheatEngine.SDK.slnx index ccca6943..316f2ab2 100644 --- a/CheatEngine.SDK.slnx +++ b/CheatEngine.SDK.slnx @@ -1,205 +1,217 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - + + + + - + - + - - - + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - + - - + + - - + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - + + - + - - + + - + - - - + + + - + - + - + - - + + - - + + - + - + - - - - - - - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/Directory.Packages.props b/Directory.Packages.props index 94f88314..4475bf56 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -40,7 +40,7 @@ - + diff --git a/README.md b/README.md index 04477705..a2bacb05 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,8 @@ configuration just to run a plugin. See the [live-plugin guide](tests/CheatEngine.SDK.LivePlugin/README.md#run-it-in-cheat-engine). A NativeAOT plugin DLL is not a supported profile: Cheat Engine unloads a plugin with `FreeLibrary`, which .NET does -not support for a NativeAOT library. See [load profiles and limits](src/CheatEngine.SDK/README.md#load-profiles-and-limits). +not support for a NativeAOT library. +See [load profiles and limits](src/CheatEngine.SDK/README.md#load-profiles-and-limits). ## Install @@ -120,15 +121,15 @@ C toolchain to rebuild it. ## Project layout -| Path | Purpose | -|------------------------------------------------|-----------------------------------------------------------------------------| -| [`libs/`](libs/) | Layered annotations, ABI, Lua, engine, and hosting libraries. | -| [`src/CheatEngine.SDK/`](src/CheatEngine.SDK/) | The `CheatEngine.SDK` NuGet package and consumer build properties. | -| [`source-generators/`](source-generators/) | Generated plugin entry-point and Lua-binding components. | -| [`analyzers/`](analyzers/) | Diagnostics, code fixes, and their documentation. | -| [`native/`](native/) | The Lua test fixture and bundled Windows x64 Lua protection bridge. | -| [`tests/`](tests/) | Unit tests, benchmarks, shared fixtures, and the live-plugin sample. | -| [`exemples/`](exemples/) | Guides, recipes, and API documentation. The directory name is intentional. | +| Path | Purpose | +|------------------------------------------------|---------------------------------------------------------------------------------| +| [`libs/`](libs/) | Layered annotations, ABI, Lua, engine, and hosting libraries. | +| [`src/CheatEngine.SDK/`](src/CheatEngine.SDK/) | The `CheatEngine.SDK` NuGet package and consumer build properties. | +| [`source-generators/`](source-generators/) | Generated plugin entry-point and Lua-binding components. | +| [`analyzers/`](analyzers/) | Diagnostics, code fixes, and their documentation. | +| [`native/`](native/) | The Lua test fixture and bundled Windows x64 Lua protection bridge. | +| [`tests/`](tests/) | Unit tests, benchmarks, shared fixtures, and the live-plugin sample. | +| [`exemples/`](exemples/) | Guides, recipes, and API documentation. The directory name is intentional. | | [`eng/`](eng/) | Shared MSBuild configuration (`Directory.Build.*`, central package management). | ## Documentation diff --git a/RELEASING.md b/RELEASING.md index 766d8522..89e14b14 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -22,15 +22,15 @@ verify ─► ci ─► attest ─► draft-release ─► publish ─► verify └ build and test the tag in Debug and Release, pack once, test that exact nupkg ``` -| Job | What it does | -|---|---| -| `verify` | Checks the SemVer tag, that it points to the first-parent history of `main`, that the version is not on nuget.org yet, and extracts the release notes from `CHANGELOG.md`. | -| `ci` | Runs `ci.yml` on the tag. The Release leg packs `CheatEngine.SDK..nupkg` (the file name must match the tag), runs the packaging tests on that exact file (`CESDK_PACKAGED_UMBRELLA_NUPKG`), and uploads it as `nuget-package`. | -| `attest` | Extracts the SPDX 2.2 SBOM embedded in the nupkg, creates the SLSA provenance attestation and the SBOM attestation of the nupkg (predicate `https://spdx.dev/Document/v2.2`), verifies both, and writes `SHA256SUMS`. | -| `draft-release` | Creates a **draft** release that already carries every asset, or completes an existing draft. It never uploads to a published release. | -| `publish` | Waits for approval of the `nuget` environment, checks the nupkg against `SHA256SUMS`, logs in through NuGet trusted publishing and pushes. | -| `verify-publication` | Waits until nuget.org lists the version, downloads the repository-signed copy and checks it: `dotnet nuget verify --all`, and every zip entry byte-identical to the attested package except the added `.signature.p7s`. | -| `finalize-release` | Publishes the release, then verifies what a consumer downloads (`SHA256SUMS`, `gh release verify`, `gh attestation verify`). | +| Job | What it does | +|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `verify` | Checks the SemVer tag, that it points to the first-parent history of `main`, that the version is not on nuget.org yet, and extracts the release notes from `CHANGELOG.md`. | +| `ci` | Runs `ci.yml` on the tag. The Release leg packs `CheatEngine.SDK..nupkg` (the file name must match the tag), runs the packaging tests on that exact file (`CESDK_PACKAGED_UMBRELLA_NUPKG`), and uploads it as `nuget-package`. | +| `attest` | Extracts the SPDX 2.2 SBOM embedded in the nupkg, creates the SLSA provenance attestation and the SBOM attestation of the nupkg (predicate `https://spdx.dev/Document/v2.2`), verifies both, and writes `SHA256SUMS`. | +| `draft-release` | Creates a **draft** release that already carries every asset, or completes an existing draft. It never uploads to a published release. | +| `publish` | Waits for approval of the `nuget` environment, checks the nupkg against `SHA256SUMS`, logs in through NuGet trusted publishing and pushes. | +| `verify-publication` | Waits until nuget.org lists the version, downloads the repository-signed copy and checks it: `dotnet nuget verify --all`, and every zip entry byte-identical to the attested package except the added `.signature.p7s`. | +| `finalize-release` | Publishes the release, then verifies what a consumer downloads (`SHA256SUMS`, `gh release verify`, `gh attestation verify`). | The `nuget-package` artifact is the release artifact: the file the packaging tests consumed is the file that is attested, attached to the release and pushed to nuget.org. Never upload a locally built package: nuget.org versions @@ -48,11 +48,11 @@ One release has three package identities: the attested asset, its NuGet content `verify-publication` checks all three exist and agree; none of them is written to a separate manifest. The published 1.0.0 is the worked example (verified on 2026-09-23): -| Identity | What it is | 1.0.0 | -|---|---|---| -| Attested asset SHA-256 | SHA-256 of the unsigned nupkg CI packed: the GitHub release asset and the subject of the attestations. | `99bf90101cd13e0183c94759e43badc6a1e719ffc3e2c9fd0b93490abdac0632` | -| NuGet content hash | SHA-512 (base64) of that same unsigned file. It is the `contentHash` consumer lock files store and validate on restore ([NU1403](https://learn.microsoft.com/nuget/reference/errors-and-warnings/nu1403)). | `n7nHqZ8vzo7Vf20jF0fkh/jUtR3yo1TwRGpXE7ERxZeJ4C5S/Nsft4lqOg7zGwfsD5Nh9tTVgdw4PrybJRF0gA==` | -| nuget.org signed file | nuget.org [repository-signs every package](https://learn.microsoft.com/nuget/reference/signed-packages-reference), so the file it serves has different bytes: the same entries plus `.signature.p7s`. | SHA-256 `3e8c98583ac71af25a5bd7053e7583fbafcd196139fae7c0b04bae9b40a7cd33`, SHA-512 `1a2B/E6reX5e636hfdb+Zdj3kT6817DuNES1RWvprhRyuyztE/56Zk2iHOMQIKpGH+O2Va8rYJxXXXTVq5aN9Q==` | +| Identity | What it is | 1.0.0 | +|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Attested asset SHA-256 | SHA-256 of the unsigned nupkg CI packed: the GitHub release asset and the subject of the attestations. | `99bf90101cd13e0183c94759e43badc6a1e719ffc3e2c9fd0b93490abdac0632` | +| NuGet content hash | SHA-512 (base64) of that same unsigned file. It is the `contentHash` consumer lock files store and validate on restore ([NU1403](https://learn.microsoft.com/nuget/reference/errors-and-warnings/nu1403)). | `n7nHqZ8vzo7Vf20jF0fkh/jUtR3yo1TwRGpXE7ERxZeJ4C5S/Nsft4lqOg7zGwfsD5Nh9tTVgdw4PrybJRF0gA==` | +| nuget.org signed file | nuget.org [repository-signs every package](https://learn.microsoft.com/nuget/reference/signed-packages-reference), so the file it serves has different bytes: the same entries plus `.signature.p7s`. | SHA-256 `3e8c98583ac71af25a5bd7053e7583fbafcd196139fae7c0b04bae9b40a7cd33`, SHA-512 `1a2B/E6reX5e636hfdb+Zdj3kT6817DuNES1RWvprhRyuyztE/56Zk2iHOMQIKpGH+O2Va8rYJxXXXTVq5aN9Q==` | The 1.0.0 signed copy has 28 entries and the asset 27; every common entry is byte-identical, and `dotnet nuget verify --all` on the signed copy reports the content hash above. The native bridge inside 1.0.0 @@ -107,11 +107,11 @@ releases were disabled. `CHANGELOG.md` and add its link reference. The body of that section becomes the GitHub release notes: a stable tag fails without it; a prerelease tag uses its own `## [X.Y.Z-rc.N]` section when present, otherwise `[Unreleased]`. Keep the four kinds of change the audit distinguishes apart, because each one breaks consumers differently: - - `### Added`: extensions (a new wrapper, option or API); - - `### Changed`: semantic corrections (the meaning of a result or boolean, a Lua arity or index convention, the - allowed thread, ownership conditions, an error category); - - `### Security`: refusal hardening (an operation that used to proceed and is now refused); - - `### Deployment`: package, native bridge, runtime policy or load-profile changes. + - `### Added`: extensions (a new wrapper, option or API); + - `### Changed`: semantic corrections (the meaning of a result or boolean, a Lua arity or index convention, the + allowed thread, ownership conditions, an error category); + - `### Security`: refusal hardening (an operation that used to proceed and is now refused); + - `### Deployment`: package, native bridge, runtime policy or load-profile changes. `### Removed` and `### Deprecated` are used as Keep a Changelog defines them. Add a `### Qualification waivers` section when the [qualification gate](#qualification-gate) needs one. @@ -208,8 +208,10 @@ Get-Content SHA256SUMS | ForEach-Object { - A consumer lock file holds the NuGet content hash: the `contentHash` of `CheatEngine.SDK` in `packages.lock.json` equals the base64 SHA-512 of the release asset (`[Convert]::ToBase64String([Security.Cryptography.SHA512]::HashData([IO.File]::ReadAllBytes("CheatEngine.SDK.$v.nupkg")))`). -- `dotnet nuget verify --all` on the file downloaded from nuget.org reports a nuget.org repository signature and the same - content hash ([`dotnet nuget verify`](https://learn.microsoft.com/dotnet/core/tools/dotnet-nuget-verify)). Never run it +- `dotnet nuget verify --all` on the file downloaded from nuget.org reports a nuget.org repository signature and the + same + content hash ([`dotnet nuget verify`](https://learn.microsoft.com/dotnet/core/tools/dotnet-nuget-verify)). Never run + it on the GitHub asset: that file is unsigned by design and fails with [NU3004](https://learn.microsoft.com/nuget/reference/errors-and-warnings/nu3004). - The `verify-publication` job automates these nuget.org checks directly in the workflow. diff --git a/SECURITY.md b/SECURITY.md index 287b0891..663a7057 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,11 +6,11 @@ fixes, how to report a vulnerability privately, and how to check that a package ## Supported versions -| Version | Package | Security fixes | -|---|---|---| -| 1.0.x, the latest published release line | `CheatEngine.SDK` on nuget.org | Yes, as a new 1.0.x patch release | -| 2.0.0 prereleases built from `main` | CI artifacts and prerelease packages | On `main` only; a prerelease is never patched in place | -| 0.1.0 to 0.2.1 | the former `CESDK` package ID | No; move to `CheatEngine.SDK` (see [CHANGELOG.md](CHANGELOG.md)) | +| Version | Package | Security fixes | +|------------------------------------------|--------------------------------------|------------------------------------------------------------------| +| 1.0.x, the latest published release line | `CheatEngine.SDK` on nuget.org | Yes, as a new 1.0.x patch release | +| 2.0.0 prereleases built from `main` | CI artifacts and prerelease packages | On `main` only; a prerelease is never patched in place | +| 0.1.0 to 0.2.1 | the former `CESDK` package ID | No; move to `CheatEngine.SDK` (see [CHANGELOG.md](CHANGELOG.md)) | When a new release line ships, the previous line stops receiving fixes; the table is updated in the same pull request. diff --git a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassRewriter.cs b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassRewriter.cs index e0e532e4..20d04ff8 100644 --- a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassRewriter.cs +++ b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassRewriter.cs @@ -57,8 +57,8 @@ public static ConstructorDeclarationSyntax MakePublic(ConstructorDeclarationSynt // 'private protected' and 'protected internal' are two keywords: drop the second one, but not what the // author wrote around it. Its comments move behind the modifier in front of it, which always exists. for (int next = IndexOfAccessibility(modifiers, first + 1); - next >= 0; - next = IndexOfAccessibility(modifiers, next)) + next >= 0; + next = IndexOfAccessibility(modifiers, next)) { SyntaxToken dropped = modifiers[next]; SyntaxToken previous = modifiers[next - 1]; @@ -79,7 +79,7 @@ private static SyntaxTriviaList FromFirstComment(SyntaxTriviaList trivia) foreach (SyntaxTrivia item in trivia) { if (kept.Count > 0 || - !(item.IsKind(SyntaxKind.WhitespaceTrivia) || item.IsKind(SyntaxKind.EndOfLineTrivia))) + !(item.IsKind(SyntaxKind.WhitespaceTrivia) || item.IsKind(SyntaxKind.EndOfLineTrivia))) { kept = kept.Add(item); } @@ -111,7 +111,7 @@ private static int IndexOfAccessibility(SyntaxTokenList modifiers, int start) for (int index = start; index < modifiers.Count; index++) { if (modifiers[index].Kind() is SyntaxKind.PublicKeyword or SyntaxKind.InternalKeyword - or SyntaxKind.ProtectedKeyword or SyntaxKind.PrivateKeyword) + or SyntaxKind.ProtectedKeyword or SyntaxKind.PrivateKeyword) { return index; } diff --git a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassShapeCodeFixProvider.cs b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassShapeCodeFixProvider.cs index 589468a5..4926f9a2 100644 --- a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassShapeCodeFixProvider.cs +++ b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassShapeCodeFixProvider.cs @@ -80,10 +80,10 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) foreach (Diagnostic diagnostic in context.Diagnostics) { if (!diagnostic.Properties.TryGetValue(DiagnosticProperties.PluginClassProblem, out string? problemName) - || !Enum.TryParse(problemName, out PluginShapeIssues problem) - || root.FindToken(diagnostic.Location.SourceSpan.Start).Parent - ?.FirstAncestorOrSelf() is not { } declaration - || semanticModel.GetDeclaredSymbol(declaration, cancellationToken) is not { } type) + || !Enum.TryParse(problemName, out PluginShapeIssues problem) + || root.FindToken(diagnostic.Location.SourceSpan.Start).Parent + ?.FirstAncestorOrSelf() is not { } declaration + || semanticModel.GetDeclaredSymbol(declaration, cancellationToken) is not { } type) { continue; } @@ -117,7 +117,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) foreach (SyntaxReference reference in type.DeclaringSyntaxReferences) { if (reference.GetSyntax(cancellationToken) is not TypeDeclarationSyntax part - || solution.GetDocument(reference.SyntaxTree) is not { } document) + || solution.GetDocument(reference.SyntaxTree) is not { } document) { continue; } @@ -243,11 +243,11 @@ private static bool CanOmitEveryArgument(IMethodSymbol constructor) foreach (IMethodSymbol constructor in type.InstanceConstructors) { if (!constructor.Parameters.IsEmpty - || constructor.IsImplicitlyDeclared - || constructor.DeclaringSyntaxReferences.IsEmpty - || constructor.DeclaringSyntaxReferences[0] is not { } reference - || reference.GetSyntax(cancellationToken) is not ConstructorDeclarationSyntax syntax - || solution.GetDocument(reference.SyntaxTree) is not { } document) + || constructor.IsImplicitlyDeclared + || constructor.DeclaringSyntaxReferences.IsEmpty + || constructor.DeclaringSyntaxReferences[0] is not { } reference + || reference.GetSyntax(cancellationToken) is not ConstructorDeclarationSyntax syntax + || solution.GetDocument(reference.SyntaxTree) is not { } document) { continue; } diff --git a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/ExceptionGuardRewriter.cs b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/ExceptionGuardRewriter.cs index b71d2474..345a5f11 100644 --- a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/ExceptionGuardRewriter.cs +++ b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/ExceptionGuardRewriter.cs @@ -57,7 +57,7 @@ public static BlockSyntax Guard(ArrowExpressionClauseSyntax expressionBody, Synt int statementPart = IndexAfterLastComment(afterSemicolon); SyntaxTriviaList withStatement = Slice(afterSemicolon, 0, statementPart); if (statementPart > 0 && afterSemicolon[statementPart - 1].IsKind(SyntaxKind.SingleLineCommentTrivia)) - // The closing brace of the try block follows: it must not end up inside the comment. + // The closing brace of the try block follows: it must not end up inside the comment. { withStatement = withStatement.Add(endOfLine); } diff --git a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/UnmanagedCallersOnlyGuardCodeFixProvider.cs b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/UnmanagedCallersOnlyGuardCodeFixProvider.cs index 46d12ee0..b95c46bb 100644 --- a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/UnmanagedCallersOnlyGuardCodeFixProvider.cs +++ b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/UnmanagedCallersOnlyGuardCodeFixProvider.cs @@ -64,8 +64,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) { MethodDeclarationSyntax? declaration = FindDeclaration(root, diagnostic.Location.SourceSpan); if (declaration is null - || semanticModel.GetDeclaredSymbol(declaration, context.CancellationToken) is not IMethodSymbol method - || !HasKnownFailureConvention(method)) + || semanticModel.GetDeclaredSymbol(declaration, context.CancellationToken) is not IMethodSymbol method + || !HasKnownFailureConvention(method)) { continue; } @@ -107,8 +107,8 @@ private static async Task WrapAsync(Document document, MethodDeclarati SyntaxNode? root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SemanticModel? semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (root is null || - semanticModel?.GetDeclaredSymbol(declaration, cancellationToken) is not IMethodSymbol method - || !HasKnownFailureConvention(method)) + semanticModel?.GetDeclaredSymbol(declaration, cancellationToken) is not IMethodSymbol method + || !HasKnownFailureConvention(method)) { return document; } @@ -136,25 +136,25 @@ private static async Task WrapAsync(Document document, MethodDeclarati private static bool HasKnownFailureConvention(IMethodSymbol method) { if (!method.IsStatic - || method.IsGenericMethod - || method.DeclaredAccessibility != Accessibility.Public - || !string.Equals(method.Name, "CEPluginInitialize", StringComparison.Ordinal) - || method.ReturnsByRef - || method.ReturnsByRefReadonly - || method.ReturnType.SpecialType != SpecialType.System_Int32 - || method.Parameters.Length != 2 - || method.Parameters[0].RefKind != RefKind.None - || method.Parameters[0].Type.SpecialType != SpecialType.System_IntPtr - || method.Parameters[1].RefKind != RefKind.None - || method.Parameters[1].Type.SpecialType != SpecialType.System_Int32) + || method.IsGenericMethod + || method.DeclaredAccessibility != Accessibility.Public + || !string.Equals(method.Name, "CEPluginInitialize", StringComparison.Ordinal) + || method.ReturnsByRef + || method.ReturnsByRefReadonly + || method.ReturnType.SpecialType != SpecialType.System_Int32 + || method.Parameters.Length != 2 + || method.Parameters[0].RefKind != RefKind.None + || method.Parameters[0].Type.SpecialType != SpecialType.System_IntPtr + || method.Parameters[1].RefKind != RefKind.None + || method.Parameters[1].Type.SpecialType != SpecialType.System_Int32) { return false; } INamedTypeSymbol containingType = method.ContainingType; return string.Equals(containingType.Name, "CESDK", StringComparison.Ordinal) - && containingType.ContainingType is null - && string.Equals(containingType.ContainingNamespace.ToDisplayString(), "CESDK", - StringComparison.Ordinal); + && containingType.ContainingType is null + && string.Equals(containingType.ContainingNamespace.ToDisplayString(), "CESDK", + StringComparison.Ordinal); } } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaBindingAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaBindingAnalyzer.cs index 66d90b45..a4e0e6bb 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaBindingAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaBindingAnalyzer.cs @@ -123,7 +123,7 @@ private static void AnalyzeObjectMember(SymbolAnalysisContext context, LuaBindin switch (context.Symbol) { case IMethodSymbol method when symbols.LuaMethodAttribute is not null - && FindAttribute(method, symbols.LuaMethodAttribute) is not null: + && FindAttribute(method, symbols.LuaMethodAttribute) is not null: usesOptional = LuaContractTypes.Is(method.ReturnType, symbols.LuaOptional); foreach (IParameterSymbol parameter in method.Parameters) { @@ -132,7 +132,7 @@ private static void AnalyzeObjectMember(SymbolAnalysisContext context, LuaBindin break; case IPropertySymbol property when symbols.LuaPropertyAttribute is not null - && FindAttribute(property, symbols.LuaPropertyAttribute) is not null: + && FindAttribute(property, symbols.LuaPropertyAttribute) is not null: usesOptional = LuaContractTypes.Is(property.Type, symbols.LuaOptional); break; default: diff --git a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaFunctionDuplicateState.cs b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaFunctionDuplicateState.cs index 09327583..5b73fe87 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaFunctionDuplicateState.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaFunctionDuplicateState.cs @@ -65,7 +65,7 @@ public void Report(CompilationAnalysisContext context) private string LuaNameFor(ConcurrentQueue<(string MethodName, Location Location)> members) { foreach (KeyValuePair<(string ContainingType, string LuaName), - ConcurrentQueue<(string MethodName, Location Location)>> pair in _candidates) + ConcurrentQueue<(string MethodName, Location Location)>> pair in _candidates) { if (ReferenceEquals(pair.Value, members)) { diff --git a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaGlobalProblemText.cs b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaGlobalProblemText.cs index e8ddd956..e3ddf2b4 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaGlobalProblemText.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaGlobalProblemText.cs @@ -55,7 +55,8 @@ public static DiagnosticDescriptor DescriptorFor(LuaGlobalShapeIssues problem) LuaGlobalShapeIssues.OptionalArgumentNotTrailing => DiagnosticDescriptors.NonTrailingOptionalLuaArgument, LuaGlobalShapeIssues.OptionalResultNotTrailing or LuaGlobalShapeIssues.VariadicResultNotLast or LuaGlobalShapeIssues.VariadicResultOutsideOutcome or LuaGlobalShapeIssues.UnsupportedVariadicElement - or LuaGlobalShapeIssues.MultipleVariadicResults => DiagnosticDescriptors.InvalidOptionalOrVariadicLuaResult, + or LuaGlobalShapeIssues.MultipleVariadicResults => DiagnosticDescriptors + .InvalidOptionalOrVariadicLuaResult, LuaGlobalShapeIssues.LookAlikeContractType => DiagnosticDescriptors.LookAlikeLuaContractType, LuaGlobalShapeIssues.OptionalNotSupportedHere => DiagnosticDescriptors.UnsupportedLuaOptionalPosition, _ => DiagnosticDescriptors.InvalidLuaGlobal diff --git a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaObjectBindingAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaObjectBindingAnalyzer.cs index 219c9730..5c94e14c 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaObjectBindingAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaObjectBindingAnalyzer.cs @@ -77,7 +77,7 @@ private static void AnalyzeType(SymbolAnalysisContext context, LuaObjectContract { INamedTypeSymbol type = (INamedTypeSymbol) context.Symbol; if (symbols.LuaClassAttribute is not null - && FindAttribute(type, symbols.LuaClassAttribute) is { } luaClassAttribute) + && FindAttribute(type, symbols.LuaClassAttribute) is { } luaClassAttribute) { string problem = LuaClassProblem(type, luaClassAttribute, context.CancellationToken); if (problem.Length > 0) @@ -100,7 +100,7 @@ private static void AnalyzeMethod(SymbolAnalysisContext context, LuaObjectContra { IMethodSymbol method = (IMethodSymbol) context.Symbol; if (symbols.LuaMethodAttribute is not null - && FindAttribute(method, symbols.LuaMethodAttribute) is { } luaMethodAttribute) + && FindAttribute(method, symbols.LuaMethodAttribute) is { } luaMethodAttribute) { string problem = LuaMethodProblem(method, luaMethodAttribute, symbols, context.CancellationToken); if (problem.Length > 0) @@ -114,7 +114,7 @@ private static void AnalyzeProperty(SymbolAnalysisContext context, LuaObjectCont { IPropertySymbol property = (IPropertySymbol) context.Symbol; if (symbols.LuaPropertyAttribute is null - || FindAttribute(property, symbols.LuaPropertyAttribute) is not { } luaPropertyAttribute) + || FindAttribute(property, symbols.LuaPropertyAttribute) is not { } luaPropertyAttribute) { return; } @@ -150,12 +150,12 @@ private static void ReportLuaClassIdentityCollisions(SymbolAnalysisContext conte foreach (ISymbol member in type.GetMembers()) { if (member is IMethodSymbol { MethodKind: MethodKind.UserDefinedOperator } method - && method.Name is "op_Equality" or "op_Inequality") + && method.Name is "op_Equality" or "op_Inequality") { ReportCollision(context, member, "operator " + - (string.Equals(method.Name, "op_Equality", StringComparison.Ordinal) - ? "==" - : "!=")); + (string.Equals(method.Name, "op_Equality", StringComparison.Ordinal) + ? "==" + : "!=")); } } @@ -167,8 +167,8 @@ private static void ReportLuaClassIdentityCollisions(SymbolAnalysisContext conte foreach (IMethodSymbol constructor in type.InstanceConstructors) { if (constructor.Parameters.Length == 1 - && constructor.Parameters[0].RefKind == RefKind.None - && SymbolEqualityComparer.Default.Equals(constructor.Parameters[0].Type, ceObject)) + && constructor.Parameters[0].RefKind == RefKind.None + && SymbolEqualityComparer.Default.Equals(constructor.Parameters[0].Type, ceObject)) { ReportCollision(context, constructor, type.Name + "(CEObject)"); } @@ -203,7 +203,7 @@ private static void ReportLuaFunctionIdentityCollisions(SymbolAnalysisContext co foreach (ISymbol member in type.GetMembers()) { if (member is not IMethodSymbol method - || FindAttribute(method, symbols.LuaFunctionAttribute) is not { } attribute) + || FindAttribute(method, symbols.LuaFunctionAttribute) is not { } attribute) { continue; } @@ -252,7 +252,7 @@ private static void ReportLuaGlobalIdentityCollisions(SymbolAnalysisContext cont foreach (ISymbol member in type.GetMembers()) { if (member is not IMethodSymbol method - || FindAttribute(method, symbols.LuaGlobalAttribute) is not { } attribute) + || FindAttribute(method, symbols.LuaGlobalAttribute) is not { } attribute) { continue; } @@ -434,7 +434,7 @@ private static string LuaMethodParameterProblem(IMethodSymbol method, LuaObjectC { hasOutResult = true; if (!LuaContractTypes.Is(parameter.Type, symbols.LuaOptional) - && !IsScalar(parameter.Type, false, symbols.ReadOnlySpan)) + && !IsScalar(parameter.Type, false, symbols.ReadOnlySpan)) { return "out results must be supported scalar values"; } @@ -464,7 +464,7 @@ private static string LuaMethodParameterProblem(IMethodSymbol method, LuaObjectC // LuaOptional on an object member is CESDK2013 (LuaBindingAnalyzer), not a generic unsupported type. if (!LuaContractTypes.Is(parameter.Type, symbols.LuaOptional) - && !IsScalar(parameter.Type, true, symbols.ReadOnlySpan)) + && !IsScalar(parameter.Type, true, symbols.ReadOnlySpan)) { return "parameters must be supported scalar values"; } @@ -514,7 +514,7 @@ private static string LuaPropertyProblem(IPropertySymbol property, AttributeData } if (!LuaContractTypes.Is(property.Type, symbols.LuaOptional) - && !IsScalar(property.Type, false, symbols.ReadOnlySpan)) + && !IsScalar(property.Type, false, symbols.ReadOnlySpan)) { return "the property type must be a supported scalar value"; } @@ -531,7 +531,7 @@ private static string LuaClassProblemForMember(INamedTypeSymbol containingType, CancellationToken cancellationToken) { if (symbols.LuaClassAttribute is null - || FindAttribute(containingType, symbols.LuaClassAttribute) is not { } luaClassAttribute) + || FindAttribute(containingType, symbols.LuaClassAttribute) is not { } luaClassAttribute) { return "the containing type must carry [LuaClass]"; } @@ -593,7 +593,7 @@ private static bool IsBodylessPartialProperty(IPropertySymbol property, Cancella } if (!hasPartialModifier || declaration.AccessorList is null || - declaration.AccessorList.Accessors.Count == 0) + declaration.AccessorList.Accessors.Count == 0) { return false; } @@ -606,8 +606,8 @@ private static bool IsBodylessPartialProperty(IPropertySymbol property, Cancella foreach (AccessorDeclarationSyntax accessor in declaration.AccessorList.Accessors) { if (accessor.Kind() is not SyntaxKind.GetAccessorDeclaration and not SyntaxKind.SetAccessorDeclaration - || accessor.Body is not null || accessor.ExpressionBody is not null - || !HasSupportedAccessorModifiers(accessor)) + || accessor.Body is not null || accessor.ExpressionBody is not null + || !HasSupportedAccessorModifiers(accessor)) { return false; } @@ -622,7 +622,7 @@ private static bool HasSupportedAccessorModifiers(AccessorDeclarationSyntax acce foreach (SyntaxToken modifier in accessor.Modifiers) { if (modifier.Kind() is not (SyntaxKind.PublicKeyword or SyntaxKind.PrivateKeyword - or SyntaxKind.ProtectedKeyword or SyntaxKind.InternalKeyword)) + or SyntaxKind.ProtectedKeyword or SyntaxKind.InternalKeyword)) { return false; } @@ -634,15 +634,15 @@ private static bool HasSupportedAccessorModifiers(AccessorDeclarationSyntax acce private static bool IsScalar(ITypeSymbol type, bool allowReadOnlySpan, INamedTypeSymbol? readOnlySpan) { if (type.SpecialType is SpecialType.System_Int32 or SpecialType.System_Int64 or SpecialType.System_Single - or SpecialType.System_Double or SpecialType.System_Boolean or SpecialType.System_UIntPtr - or SpecialType.System_String) + or SpecialType.System_Double or SpecialType.System_Boolean or SpecialType.System_UIntPtr + or SpecialType.System_String) { return true; } if (!allowReadOnlySpan || readOnlySpan is null || type is not INamedTypeSymbol { IsGenericType: true } named - || !SymbolEqualityComparer.Default.Equals(named.OriginalDefinition, readOnlySpan) - || named.TypeArguments.Length != 1) + || !SymbolEqualityComparer.Default.Equals(named.OriginalDefinition, readOnlySpan) + || named.TypeArguments.Length != 1) { return false; } @@ -761,8 +761,8 @@ public INamedTypeSymbol? CEObject } = ceObject; public bool HasAnyLuaObjectAnnotation => LuaClassAttribute is not null || LuaMethodAttribute is not null - || LuaPropertyAttribute is not null || - LuaFunctionAttribute is not null - || LuaGlobalAttribute is not null; + || LuaPropertyAttribute is not null || + LuaFunctionAttribute is not null + || LuaGlobalAttribute is not null; } } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Plugin/CheatEnginePluginAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Plugin/CheatEnginePluginAnalyzer.cs index 65242eab..f7e998f0 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Plugin/CheatEnginePluginAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Plugin/CheatEnginePluginAnalyzer.cs @@ -86,8 +86,8 @@ private static void OnCompilationStart(CompilationStartAnalysisContext context) // CESDK.CESDK to the author, which CESDK0003 validates at compilation end. bool? entryPointIsGenerated = null; if (context.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue(GenerateEntryPointKey, - out string? raw) - && bool.TryParse(raw, out bool generate)) + out string? raw) + && bool.TryParse(raw, out bool generate)) { entryPointIsGenerated = generate; } @@ -128,7 +128,7 @@ private static void AnalyzeNamedType( // The attribute targets classes only: on anything else the compiler already reports CS0592. if (type.TypeKind != TypeKind.Class || - FindAttribute(type, symbols.PluginAttribute) is not { } attribute) + FindAttribute(type, symbols.PluginAttribute) is not { } attribute) { return; } @@ -215,20 +215,20 @@ private static bool IsManualBootstrap(INamedTypeSymbol type) foreach (ISymbol member in type.GetMembers("CEPluginInitialize")) { if (member is not IMethodSymbol - { - MethodKind: MethodKind.Ordinary, - IsStatic: true, - IsGenericMethod: false, - DeclaredAccessibility: Accessibility.Public, - ReturnsByRef: false, - ReturnsByRefReadonly: false, - ReturnType.SpecialType: SpecialType.System_Int32, - Parameters: - [ - { RefKind: RefKind.None, Type.SpecialType: SpecialType.System_IntPtr }, - { RefKind: RefKind.None, Type.SpecialType: SpecialType.System_Int32 } - ] - }) + { + MethodKind: MethodKind.Ordinary, + IsStatic: true, + IsGenericMethod: false, + DeclaredAccessibility: Accessibility.Public, + ReturnsByRef: false, + ReturnsByRefReadonly: false, + ReturnType.SpecialType: SpecialType.System_Int32, + Parameters: + [ + { RefKind: RefKind.None, Type.SpecialType: SpecialType.System_IntPtr }, + { RefKind: RefKind.None, Type.SpecialType: SpecialType.System_Int32 } + ] + }) { continue; } @@ -265,9 +265,9 @@ private static void AnalyzeNamespaceDeclaration(SyntaxNodeAnalysisContext contex // A nested declaration is under 'CESDK' exactly when its outermost declaration is: one report per outermost one. if (declaration.Parent is not CompilationUnitSyntax - || context.SemanticModel.GetDeclaredSymbol(declaration, context.CancellationToken) is not INamespaceSymbol - declared - || !IsUnderReservedRoot(declared, context.CancellationToken)) + || context.SemanticModel.GetDeclaredSymbol(declaration, context.CancellationToken) is not INamespaceSymbol + declared + || !IsUnderReservedRoot(declared, context.CancellationToken)) { return; } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Plugin/ClassicNativeExportAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Plugin/ClassicNativeExportAnalyzer.cs index ca0723b6..bcc69a49 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Plugin/ClassicNativeExportAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Plugin/ClassicNativeExportAnalyzer.cs @@ -95,14 +95,14 @@ private static void Analyze(Action report, IMethodSymbol method, INa foreach (KeyValuePair argument in attribute.NamedArguments) { if (!string.Equals(argument.Key, EntryPointArgument, StringComparison.Ordinal) || - argument.Value.Value is not string entryPoint || - !entryPoint.StartsWith(ClassicExportPrefix, StringComparison.Ordinal)) + argument.Value.Value is not string entryPoint || + !entryPoint.StartsWith(ClassicExportPrefix, StringComparison.Ordinal)) { continue; } Location location = attribute.ApplicationSyntaxReference?.GetSyntax(cancellationToken).GetLocation() - ?? (method.Locations.IsEmpty ? Location.None : method.Locations[0]); + ?? (method.Locations.IsEmpty ? Location.None : method.Locations[0]); report(Diagnostic.Create(DiagnosticDescriptors.ClassicNativePluginExport, location, method.Name, entryPoint)); } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Plugin/PluginCompilationState.cs b/analyzers/CheatEngine.SDK.Analyzers/Plugin/PluginCompilationState.cs index 13260a17..146e92da 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Plugin/PluginCompilationState.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Plugin/PluginCompilationState.cs @@ -57,7 +57,7 @@ public void Report(CompilationAnalysisContext context) { int pluginClassCount = _pluginClasses.Count; if (pluginClassCount == 0) - // Not a plugin assembly (the SDK's own libraries, a helper library): both rules are about plugins. + // Not a plugin assembly (the SDK's own libraries, a helper library): both rules are about plugins. { return; } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Usage/ExceptionGuard.cs b/analyzers/CheatEngine.SDK.Analyzers/Usage/ExceptionGuard.cs index b9db1a10..97f80cd3 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Usage/ExceptionGuard.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Usage/ExceptionGuard.cs @@ -113,16 +113,16 @@ private static bool IsGuardTry(ITryOperation tryOperation, INamedTypeSymbol exce } return hasCatchAll - && (tryOperation.Finally is null - || !ContainsThrow(tryOperation.Finally, doesNotReturnAttribute, environmentType)); + && (tryOperation.Finally is null + || !ContainsThrow(tryOperation.Finally, doesNotReturnAttribute, environmentType)); } // 'catch { }' has the exception type System.Object; 'catch (Exception)' names the root of the hierarchy. private static bool IsCatchAll(ICatchClauseOperation catchClause, INamedTypeSymbol exceptionType) { return catchClause.Filter is null - && (catchClause.ExceptionType.SpecialType == SpecialType.System_Object - || SymbolEqualityComparer.Default.Equals(catchClause.ExceptionType, exceptionType)); + && (catchClause.ExceptionType.SpecialType == SpecialType.System_Object + || SymbolEqualityComparer.Default.Equals(catchClause.ExceptionType, exceptionType)); } private static bool ContainsThrow(IOperation block, INamedTypeSymbol? doesNotReturnAttribute, @@ -131,8 +131,8 @@ private static bool ContainsThrow(IOperation block, INamedTypeSymbol? doesNotRet foreach (IOperation descendant in block.Descendants()) { if (descendant.Kind == OperationKind.Throw - || (descendant is IInvocationOperation invocation - && NeverReturnsByThrowing(invocation.TargetMethod, doesNotReturnAttribute, environmentType))) + || (descendant is IInvocationOperation invocation + && NeverReturnsByThrowing(invocation.TargetMethod, doesNotReturnAttribute, environmentType))) { return true; } @@ -148,7 +148,7 @@ private static bool NeverReturnsByThrowing(IMethodSymbol method, INamedTypeSymbo INamedTypeSymbol? environmentType) { if (doesNotReturnAttribute is null - || SymbolEqualityComparer.Default.Equals(method.ContainingType, environmentType)) + || SymbolEqualityComparer.Default.Equals(method.ContainingType, environmentType)) { return false; } @@ -199,7 +199,7 @@ private static bool IsTriviallyNonThrowing(IOperation value) } => true, IConversionOperation conversion => IsNonThrowingConversion(conversion) && - IsTriviallyNonThrowing(conversion.Operand), + IsTriviallyNonThrowing(conversion.Operand), // '-x', '+x', '~x', '!x' outside a checked context. 'dynamic' and 'decimal' operands run code, and so does // the fifth built-in unary operator: '^x' constructs a System.Index, which rejects negative values. @@ -229,7 +229,7 @@ private static bool IsNonThrowingConversion(IConversionOperation operation) { Conversion conversion = operation.GetConversion(); if (!conversion.Exists || conversion.IsUserDefined || conversion.MethodSymbol is not null || - conversion.IsDynamic) + conversion.IsDynamic) { return false; } @@ -246,15 +246,15 @@ private static bool IsNonThrowingConversion(IConversionOperation operation) if (conversion.IsImplicit) { return conversion.IsNumeric - || conversion.IsReference - || conversion.IsPointer - || (conversion.IsNullable && IsNullableWrapping(source, target)); + || conversion.IsReference + || conversion.IsPointer + || (conversion.IsNullable && IsNullableWrapping(source, target)); } return !operation.IsChecked - && (conversion.IsNumeric || conversion.IsEnumeration || conversion.IsPointer) - && IsPrimitiveEnumOrPointer(source) - && IsPrimitiveEnumOrPointer(target); + && (conversion.IsNumeric || conversion.IsEnumeration || conversion.IsPointer) + && IsPrimitiveEnumOrPointer(source) + && IsPrimitiveEnumOrPointer(target); } // 'int -> int?', 'int -> long?', 'int? -> long?', 'Guid -> Guid?'. An implicit nullable conversion can also @@ -265,9 +265,9 @@ private static bool IsNullableWrapping(ITypeSymbol? source, ITypeSymbol? target) ITypeSymbol? from = UnwrapNullable(source); ITypeSymbol? to = UnwrapNullable(target); return from is not null - && to is not null - && (SymbolEqualityComparer.Default.Equals(from, to) || - (IsPrimitiveOrEnum(from) && IsPrimitiveOrEnum(to))); + && to is not null + && (SymbolEqualityComparer.Default.Equals(from, to) || + (IsPrimitiveOrEnum(from) && IsPrimitiveOrEnum(to))); } private static ITypeSymbol? UnwrapNullable(ITypeSymbol? type) @@ -287,12 +287,12 @@ private static bool IsPrimitiveEnumOrPointer(ITypeSymbol? type) private static bool IsPrimitiveOrEnum(ITypeSymbol? type) { return type is { TypeKind: TypeKind.Enum } - || type?.SpecialType is SpecialType.System_Boolean or SpecialType.System_Char - or SpecialType.System_SByte or SpecialType.System_Byte - or SpecialType.System_Int16 or SpecialType.System_UInt16 - or SpecialType.System_Int32 or SpecialType.System_UInt32 - or SpecialType.System_Int64 or SpecialType.System_UInt64 - or SpecialType.System_IntPtr or SpecialType.System_UIntPtr - or SpecialType.System_Single or SpecialType.System_Double; + || type?.SpecialType is SpecialType.System_Boolean or SpecialType.System_Char + or SpecialType.System_SByte or SpecialType.System_Byte + or SpecialType.System_Int16 or SpecialType.System_UInt16 + or SpecialType.System_Int32 or SpecialType.System_UInt32 + or SpecialType.System_Int64 or SpecialType.System_UInt64 + or SpecialType.System_IntPtr or SpecialType.System_UIntPtr + or SpecialType.System_Single or SpecialType.System_Double; } } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Usage/HostWidthPointerSizeAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Usage/HostWidthPointerSizeAnalyzer.cs index 7a6f9a61..11267a33 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Usage/HostWidthPointerSizeAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Usage/HostWidthPointerSizeAnalyzer.cs @@ -73,7 +73,7 @@ private static void OnCompilationStart(CompilationStartAnalysisContext context) foreach (MetadataReference reference in compilation.References) { if (compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly - && string.Equals(assembly.Identity.Name, EngineAssemblyName, StringComparison.Ordinal)) + && string.Equals(assembly.Identity.Name, EngineAssemblyName, StringComparison.Ordinal)) { return assembly.GetTypeByMetadataName(PointerSizeMetadataName); } @@ -86,8 +86,8 @@ private static void AnalyzeObjectCreation(OperationAnalysisContext context, Host { IObjectCreationOperation creation = (IObjectCreationOperation) context.Operation; if (creation.Constructor is null - || !SymbolEqualityComparer.Default.Equals(creation.Constructor.ContainingType, symbols.PointerSize) - || creation.Arguments.Length != 1) + || !SymbolEqualityComparer.Default.Equals(creation.Constructor.ContainingType, symbols.PointerSize) + || creation.Arguments.Length != 1) { return; } @@ -106,9 +106,9 @@ private static void AnalyzeConditional(OperationAnalysisContext context, HostWid { IConditionalOperation conditional = (IConditionalOperation) context.Operation; if (conditional.WhenFalse is null - || !SymbolEqualityComparer.Default.Equals(conditional.Type, symbols.PointerSize) - || !IsWidthConstant(conditional.WhenTrue, symbols) - || !IsWidthConstant(conditional.WhenFalse, symbols)) + || !SymbolEqualityComparer.Default.Equals(conditional.Type, symbols.PointerSize) + || !IsWidthConstant(conditional.WhenTrue, symbols) + || !IsWidthConstant(conditional.WhenFalse, symbols)) { return; } @@ -127,8 +127,8 @@ private static void AnalyzeConditional(OperationAnalysisContext context, HostWid private static bool IsWidthConstant(IOperation operation, HostWidthSymbols symbols) { return SkipConversions(operation) is IPropertyReferenceOperation { Instance: null } property - && SymbolEqualityComparer.Default.Equals(property.Property.ContainingType, symbols.PointerSize) - && property.Property.Name is "Bit32" or "Bit64"; + && SymbolEqualityComparer.Default.Equals(property.Property.ContainingType, symbols.PointerSize) + && property.Property.Name is "Bit32" or "Bit64"; } private static IOperation? FindHostWidthSource(IOperation condition, HostWidthSymbols symbols) @@ -156,7 +156,7 @@ private static bool IsHostWidthSource(IOperation operation, HostWidthSymbols sym case IPropertyReferenceOperation { Instance: null } property: // IntPtr.Size and UIntPtr.Size; nint.Size and nuint.Size bind to the same properties. return string.Equals(property.Property.Name, "Size", StringComparison.Ordinal) - && IsNativeWidthType(property.Property.ContainingType); + && IsNativeWidthType(property.Property.ContainingType); case ISizeOfOperation sizeOf: return IsNativeWidthType(sizeOf.TypeOperand) || sizeOf.TypeOperand is IPointerTypeSymbol; case IInvocationOperation invocation: @@ -171,14 +171,14 @@ private static bool IsGenericSizeOf(IInvocationOperation invocation, HostWidthSy { IMethodSymbol method = invocation.TargetMethod; if (!string.Equals(method.Name, "SizeOf", StringComparison.Ordinal) || method.TypeArguments.Length != 1 - || invocation.Arguments.Length != 0) + || invocation.Arguments.Length != 0) { return false; } INamedTypeSymbol declaring = method.ContainingType; bool knownHelper = SymbolEqualityComparer.Default.Equals(declaring, symbols.Unsafe) - || SymbolEqualityComparer.Default.Equals(declaring, symbols.Marshal); + || SymbolEqualityComparer.Default.Equals(declaring, symbols.Marshal); ITypeSymbol argument = method.TypeArguments[0]; return knownHelper && (IsNativeWidthType(argument) || argument is IPointerTypeSymbol); } @@ -186,8 +186,8 @@ private static bool IsGenericSizeOf(IInvocationOperation invocation, HostWidthSy private static bool IsIs64BitProcess(IOperation operation, HostWidthSymbols symbols) { return operation is IPropertyReferenceOperation { Instance: null } property - && string.Equals(property.Property.Name, "Is64BitProcess", StringComparison.Ordinal) - && SymbolEqualityComparer.Default.Equals(property.Property.ContainingType, symbols.Environment); + && string.Equals(property.Property.Name, "Is64BitProcess", StringComparison.Ordinal) + && SymbolEqualityComparer.Default.Equals(property.Property.ContainingType, symbols.Environment); } // System.IntPtr and System.UIntPtr, including their nint and nuint spellings. diff --git a/analyzers/CheatEngine.SDK.Analyzers/Usage/PluginLifecycleAndOwnershipAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Usage/PluginLifecycleAndOwnershipAnalyzer.cs index 6d60546a..2d1dc3d5 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Usage/PluginLifecycleAndOwnershipAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Usage/PluginLifecycleAndOwnershipAnalyzer.cs @@ -77,8 +77,8 @@ private static void AnalyzeInvocation(OperationAnalysisContext context, PluginLi { IInvocationOperation invocation = (IInvocationOperation) context.Operation; if (symbols.RequiresPluginEnabled is not null && IsTooEarly(context.ContainingSymbol, symbols.PluginAttribute) - && RequiresEnabled(invocation.TargetMethod, - symbols.RequiresPluginEnabled)) + && RequiresEnabled(invocation.TargetMethod, + symbols.RequiresPluginEnabled)) { context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.RequiresPluginEnabledTooEarly, invocation.Syntax.GetLocation(), DisplayName(invocation.TargetMethod))); @@ -102,7 +102,7 @@ private static void AnalyzePropertyReference(OperationAnalysisContext context, PluginLifecycleContractSymbols symbols) { if (symbols.RequiresPluginEnabled is null || - !IsTooEarly(context.ContainingSymbol, symbols.PluginAttribute)) + !IsTooEarly(context.ContainingSymbol, symbols.PluginAttribute)) { return; } @@ -120,14 +120,14 @@ private static void AnalyzePropertyReference(OperationAnalysisContext context, private static void AnalyzeObjectCreation(OperationAnalysisContext context, PluginLifecycleContractSymbols symbols) { if (symbols.RequiresPluginEnabled is null || - !IsTooEarly(context.ContainingSymbol, symbols.PluginAttribute)) + !IsTooEarly(context.ContainingSymbol, symbols.PluginAttribute)) { return; } IObjectCreationOperation creation = (IObjectCreationOperation) context.Operation; if (creation.Constructor is null || - !RequiresEnabled(creation.Constructor, symbols.RequiresPluginEnabled)) + !RequiresEnabled(creation.Constructor, symbols.RequiresPluginEnabled)) { return; } @@ -140,7 +140,7 @@ private static void AnalyzeMethod(SymbolAnalysisContext context, PluginLifecycle { IMethodSymbol method = (IMethodSymbol) context.Symbol; if (!method.IsAsync || !method.ReturnsVoid || - !IsPluginClass(method.ContainingType, symbols.PluginAttribute)) + !IsPluginClass(method.ContainingType, symbols.PluginAttribute)) { return; } @@ -183,8 +183,8 @@ private static bool IsLifecycleOverride(IMethodSymbol method, INamedTypeSymbol p } for (IMethodSymbol? overridden = method.OverriddenMethod; - overridden is not null; - overridden = overridden.OverriddenMethod) + overridden is not null; + overridden = overridden.OverriddenMethod) { if (SymbolEqualityComparer.Default.Equals(overridden.ContainingType, pluginBase)) { diff --git a/analyzers/CheatEngine.SDK.Analyzers/Usage/UnmanagedCallersOnlyGuardAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Usage/UnmanagedCallersOnlyGuardAnalyzer.cs index f7e1589f..1f037769 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Usage/UnmanagedCallersOnlyGuardAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Usage/UnmanagedCallersOnlyGuardAnalyzer.cs @@ -82,7 +82,7 @@ private static void AnalyzeMethodBody(OperationAnalysisContext context, INamedTy { IMethodBodyOperation body = (IMethodBodyOperation) context.Operation; if (context.ContainingSymbol is not IMethodSymbol method || - !IsUnmanagedCallersOnly(method, unmanagedCallersOnly)) + !IsUnmanagedCallersOnly(method, unmanagedCallersOnly)) { return; } diff --git a/analyzers/CheatEngine.SDK.Analyzers/WellKnown/SdkSymbolResolver.cs b/analyzers/CheatEngine.SDK.Analyzers/WellKnown/SdkSymbolResolver.cs index 6c21f93d..83b760c2 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/WellKnown/SdkSymbolResolver.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/WellKnown/SdkSymbolResolver.cs @@ -38,7 +38,7 @@ internal static class SdkSymbolResolver foreach (MetadataReference reference in compilation.References) { if (compilation.GetAssemblyOrModuleSymbol(reference) is not IAssemblySymbol assembly - || !string.Equals(assembly.Identity.Name, assemblyName, StringComparison.Ordinal)) + || !string.Equals(assembly.Identity.Name, assemblyName, StringComparison.Ordinal)) { continue; } diff --git a/analyzers/docs/CESDK5010.md b/analyzers/docs/CESDK5010.md index 1aa1fc81..26b078c5 100644 --- a/analyzers/docs/CESDK5010.md +++ b/analyzers/docs/CESDK5010.md @@ -26,7 +26,8 @@ Your code calls one of these `CheatEngine.SDK.Engine` members, which carry Cheat Engine 7.7.0.10621 documents an optional timeout for `MemScan.waitTillDone` that returns a boolean (`celua.txt` line 2649) and a cooperative `MemScan.terminateScan` (line 2566). The C3 spike of 2026-09-22 (Lua-only, on the pinned -`ce-7.7.0.10621-x64-managed-hostfxr` profile, decision D4.7) observed `waitTillDone(timeout)` returning `true`, but could +`ce-7.7.0.10621-x64-managed-hostfxr` profile, decision D4.7) observed `waitTillDone(timeout)` returning `true`, but +could not produce the `false` path: a whole-address-space scan finished before a one-millisecond deadline expired. It did not exercise `terminateScan` at all. Everything these members do after a deadline expires is therefore covered by fixture tests (C1) only, not by the host. diff --git a/analyzers/docs/README.md b/analyzers/docs/README.md index e3c92b6f..801e7fb4 100644 --- a/analyzers/docs/README.md +++ b/analyzers/docs/README.md @@ -12,40 +12,40 @@ separate EngineApi generator owns `[Experimental]` API gates, held unqualified until their audit criteria pass. `CESDK7xxx` marks members obsoleted after 1.0.0 (`[Obsolete(DiagnosticId = …)]`). Identifiers are never renumbered or reused. -| Id | Title | Severity | Code fix | -|---------------------------|------------------------------------------------------------------|----------|----------------------------------------------------------------------------------------------| -| [CESDK0001](CESDK0001.md) | Plugin class cannot be constructed by the generated entry point | Error | Replace `abstract` or `static` with `sealed`, add a constructor, make the constructor public | -| [CESDK0002](CESDK0002.md) | More than one plugin class in the assembly | Error | None | -| [CESDK0003](CESDK0003.md) | Manual Cheat Engine bootstrap is missing or malformed | Error | Add the exact `CESDK.CESDK.CEPluginInitialize(IntPtr, int)` contract | -| [CESDK0004](CESDK0004.md) | Plugin assembly declares a namespace under 'CESDK' | Warning | None | -| [CESDK0005](CESDK0005.md) | Source type collides with the generated Cheat Engine entry point | Error | Rename it, or explicitly own the complete manual bootstrap | -| [CESDK0006](CESDK0006.md) | Method exports a classic Cheat Engine native plugin entry point | Warning | None | -| [CESDK1001](CESDK1001.md) | Plugin startup code calls an enabled-only API | Error | Move the call to `OnEnable` | -| [CESDK1003](CESDK1003.md) | A Cheat Engine-owned value is being destroyed | Error | Keep it borrowed or use an explicit `Owned` transfer | -| [CESDK1004](CESDK1004.md) | Exception can escape an [UnmanagedCallersOnly] method | Warning | Wrap the body in try/catch | -| [CESDK1005](CESDK1005.md) | Plugin lifecycle callback must not be `async void` | Error | Keep `OnEnable`/`OnDisable` synchronous | -| [CESDK1020](CESDK1020.md) | PointerSize built from the plugin process width | Warning | None; read the target bitness or configured pointer size from Cheat Engine | -| [CESDK2001](CESDK2001.md) | Lua binding needs AllowUnsafeBlocks | Error | None | -| [CESDK2002](CESDK2002.md) | Type cannot receive a generated Lua binding part | Error | None | -| [CESDK2003](CESDK2003.md) | [LuaFunction] method cannot be exported by a generated thunk | Error | None | -| [CESDK2004](CESDK2004.md) | [LuaGlobal] method cannot receive a generated body | Error | None | -| [CESDK2005](CESDK2005.md) | Lua function name is duplicated | Error | Give one valid export a distinct Lua name | -| [CESDK2006](CESDK2006.md) | Lua annotation target cannot receive generated code | Error | Declare the supported borrowed-handle/member shape | -| [CESDK2007](CESDK2007.md) | User member collides with a generated Lua binding identity | Error | Rename the member or change the binding declaration | -| [CESDK2010](CESDK2010.md) | Optional Lua argument is not in a trailing run | Error | Declare optional arguments after the required ones | -| [CESDK2011](CESDK2011.md) | Optional or variadic Lua result shape is invalid | Error | Required, then optional results; one variadic pair last | -| [CESDK2012](CESDK2012.md) | Type impersonates an SDK Lua contract type | Error | Use the CheatEngine.SDK.Lua type | -| [CESDK2013](CESDK2013.md) | LuaOptional is not supported in this position | Error | Use an argument or an `out` result of a supported kind | -| [CESDK3001](CESDK3001.md) | Engine API specification is invalid | Error | Correct the reported spec line | -| [CESDK3002](CESDK3002.md) | Engine API specification has a generated-identity conflict | Error | Keep one spec file per generated type | -| [CESDK3003](CESDK3003.md) | Engine API specification does not declare the ce77 contract | Error | Add the `contract: ce77` header | -| [CESDK3004](CESDK3004.md) | Engine API optional argument is invalid | Error | Declare `opt:` arguments last | -| [CESDK3005](CESDK3005.md) | Engine API optional or variadic result is invalid | Error | `result:`, then `opt-result:`, then one `rest:` | -| [CESDK5001](CESDK5001.md) | Worker-thread Lua admission is experimental | Error (compiler) | None | -| [CESDK5010](CESDK5010.md) | Scan deadline and cooperative termination are experimental | Error (compiler) | None | -| [CESDK5011](CESDK5011.md) | First-found AOB scan is experimental | Error (compiler) | None | -| [CESDK7001](CESDK7001.md) | PointerSize.FromArchitecture is obsolete | Warning | None; use `TargetArchitectureObservation.ConfiguredPointerSize` or `Bitness` | -| [CESDK9102](CESDK9102.md) | A CheatEngine.SDK plugin library sets PublishAot (MSBuild, packaged build target) | Warning | None | +| Id | Title | Severity | Code fix | +|---------------------------|-----------------------------------------------------------------------------------|------------------|----------------------------------------------------------------------------------------------| +| [CESDK0001](CESDK0001.md) | Plugin class cannot be constructed by the generated entry point | Error | Replace `abstract` or `static` with `sealed`, add a constructor, make the constructor public | +| [CESDK0002](CESDK0002.md) | More than one plugin class in the assembly | Error | None | +| [CESDK0003](CESDK0003.md) | Manual Cheat Engine bootstrap is missing or malformed | Error | Add the exact `CESDK.CESDK.CEPluginInitialize(IntPtr, int)` contract | +| [CESDK0004](CESDK0004.md) | Plugin assembly declares a namespace under 'CESDK' | Warning | None | +| [CESDK0005](CESDK0005.md) | Source type collides with the generated Cheat Engine entry point | Error | Rename it, or explicitly own the complete manual bootstrap | +| [CESDK0006](CESDK0006.md) | Method exports a classic Cheat Engine native plugin entry point | Warning | None | +| [CESDK1001](CESDK1001.md) | Plugin startup code calls an enabled-only API | Error | Move the call to `OnEnable` | +| [CESDK1003](CESDK1003.md) | A Cheat Engine-owned value is being destroyed | Error | Keep it borrowed or use an explicit `Owned` transfer | +| [CESDK1004](CESDK1004.md) | Exception can escape an [UnmanagedCallersOnly] method | Warning | Wrap the body in try/catch | +| [CESDK1005](CESDK1005.md) | Plugin lifecycle callback must not be `async void` | Error | Keep `OnEnable`/`OnDisable` synchronous | +| [CESDK1020](CESDK1020.md) | PointerSize built from the plugin process width | Warning | None; read the target bitness or configured pointer size from Cheat Engine | +| [CESDK2001](CESDK2001.md) | Lua binding needs AllowUnsafeBlocks | Error | None | +| [CESDK2002](CESDK2002.md) | Type cannot receive a generated Lua binding part | Error | None | +| [CESDK2003](CESDK2003.md) | [LuaFunction] method cannot be exported by a generated thunk | Error | None | +| [CESDK2004](CESDK2004.md) | [LuaGlobal] method cannot receive a generated body | Error | None | +| [CESDK2005](CESDK2005.md) | Lua function name is duplicated | Error | Give one valid export a distinct Lua name | +| [CESDK2006](CESDK2006.md) | Lua annotation target cannot receive generated code | Error | Declare the supported borrowed-handle/member shape | +| [CESDK2007](CESDK2007.md) | User member collides with a generated Lua binding identity | Error | Rename the member or change the binding declaration | +| [CESDK2010](CESDK2010.md) | Optional Lua argument is not in a trailing run | Error | Declare optional arguments after the required ones | +| [CESDK2011](CESDK2011.md) | Optional or variadic Lua result shape is invalid | Error | Required, then optional results; one variadic pair last | +| [CESDK2012](CESDK2012.md) | Type impersonates an SDK Lua contract type | Error | Use the CheatEngine.SDK.Lua type | +| [CESDK2013](CESDK2013.md) | LuaOptional is not supported in this position | Error | Use an argument or an `out` result of a supported kind | +| [CESDK3001](CESDK3001.md) | Engine API specification is invalid | Error | Correct the reported spec line | +| [CESDK3002](CESDK3002.md) | Engine API specification has a generated-identity conflict | Error | Keep one spec file per generated type | +| [CESDK3003](CESDK3003.md) | Engine API specification does not declare the ce77 contract | Error | Add the `contract: ce77` header | +| [CESDK3004](CESDK3004.md) | Engine API optional argument is invalid | Error | Declare `opt:` arguments last | +| [CESDK3005](CESDK3005.md) | Engine API optional or variadic result is invalid | Error | `result:`, then `opt-result:`, then one `rest:` | +| [CESDK5001](CESDK5001.md) | Worker-thread Lua admission is experimental | Error (compiler) | None | +| [CESDK5010](CESDK5010.md) | Scan deadline and cooperative termination are experimental | Error (compiler) | None | +| [CESDK5011](CESDK5011.md) | First-found AOB scan is experimental | Error (compiler) | None | +| [CESDK7001](CESDK7001.md) | PointerSize.FromArchitecture is obsolete | Warning | None; use `TargetArchitectureObservation.ConfiguredPointerSize` or `Bitness` | +| [CESDK9102](CESDK9102.md) | A CheatEngine.SDK plugin library sets PublishAot (MSBuild, packaged build target) | Warning | None | Configure a rule like any other analyzer diagnostic: diff --git a/exemples/05-aob-scans/README.md b/exemples/05-aob-scans/README.md index b1c76334..08c9de1f 100644 --- a/exemples/05-aob-scans/README.md +++ b/exemples/05-aob-scans/README.md @@ -176,7 +176,8 @@ internal static class ModuleSignatures ``` `result.IsMaterializationLimitReached` tells you the destination filled up before every row was read, and -`result.InBoundsCountIsExact` that `Written` is the full in-bounds count; a single match is proven only by that, never by +`result.InBoundsCountIsExact` that `Written` is the full in-bounds count; a single match is proven only by that, never +by a first-found scan. ```mermaid diff --git a/exemples/07-address-list/README.md b/exemples/07-address-list/README.md index 05d1f740..6070008a 100644 --- a/exemples/07-address-list/README.md +++ b/exemples/07-address-list/README.md @@ -150,7 +150,8 @@ boundary, not as an opportunity to retain a borrowed record. ## Evidence and scope -This slice is sourced from the exact CE `7.7.0.10621` x64 `celua.txt` fixture: `getAddressList`, the `Addresslist` class, and the +This slice is sourced from the exact CE `7.7.0.10621` x64 `celua.txt` fixture: `getAddressList`, the `Addresslist` +class, and the `MemoryRecord` members used above. Its protected-call tests exercise the managed boundary; they do not prove a live CE GUI thread contract. The classic plugin callback type 0 record is a separate ABI concern and is not this object API. diff --git a/libs/CheatEngine.SDK.Abi/Native/AddressListPluginInit.cs b/libs/CheatEngine.SDK.Abi/Native/AddressListPluginInit.cs index eaa9526d..da336034 100644 --- a/libs/CheatEngine.SDK.Abi/Native/AddressListPluginInit.cs +++ b/libs/CheatEngine.SDK.Abi/Native/AddressListPluginInit.cs @@ -18,7 +18,8 @@ namespace CheatEngine.SDK.Abi.Native; /// TPlugin0_SelectedRecord of the pinned plugin.pas (lines 726-735, address: ptrUint, /// ispointer: BOOL), which agrees with the C header and is mirrored by the internal /// PluginType0Record. The Pascal kit unit's two variants (address: dword, and a one-byte -/// ispointer: boolean) are known-wrong for x64 (see libs/CheatEngine.SDK.Abi/README.md). What the CE 7.7.0.10621 +/// ispointer: boolean) are known-wrong for x64 (see libs/CheatEngine.SDK.Abi/README.md). What the CE +/// 7.7.0.10621 /// binary passes is still not observed (no managed-hostfxr route registers a type-0 function), so the /// callback stays void*: no callable signature is published. /// diff --git a/libs/CheatEngine.SDK.Abi/Native/BoundedDebugEventObservationBuffer.cs b/libs/CheatEngine.SDK.Abi/Native/BoundedDebugEventObservationBuffer.cs index 8f738885..73db789e 100644 --- a/libs/CheatEngine.SDK.Abi/Native/BoundedDebugEventObservationBuffer.cs +++ b/libs/CheatEngine.SDK.Abi/Native/BoundedDebugEventObservationBuffer.cs @@ -30,7 +30,7 @@ public BoundedDebugEventObservationBuffer(int capacity, DebugEventObservationOve { ArgumentOutOfRangeException.ThrowIfNegativeOrZero(capacity); if (overflowPolicy is not DebugEventObservationOverflowPolicy.DropNewest - and not DebugEventObservationOverflowPolicy.DropOldest) + and not DebugEventObservationOverflowPolicy.DropOldest) { throw new ArgumentOutOfRangeException(nameof(overflowPolicy)); } diff --git a/libs/CheatEngine.SDK.Abi/Native/ClassicDebugEventDispatcher.cs b/libs/CheatEngine.SDK.Abi/Native/ClassicDebugEventDispatcher.cs index 2cb6520d..58b0e44d 100644 --- a/libs/CheatEngine.SDK.Abi/Native/ClassicDebugEventDispatcher.cs +++ b/libs/CheatEngine.SDK.Abi/Native/ClassicDebugEventDispatcher.cs @@ -207,9 +207,9 @@ private static int Dispatch(void* nativeEvent) } if (!TryEnterActiveCallback( - out ClassicDebugEventDispatcher? dispatcher, - out DebugEventDecisionHandler handler, - out BoundedDebugEventObservationBuffer? observations)) + out ClassicDebugEventDispatcher? dispatcher, + out DebugEventDecisionHandler handler, + out BoundedDebugEventObservationBuffer? observations)) { return 0; } diff --git a/libs/CheatEngine.SDK.Abi/Native/ClassicExportedFunctionsPrefixReader.cs b/libs/CheatEngine.SDK.Abi/Native/ClassicExportedFunctionsPrefixReader.cs index 1234f740..83a23315 100644 --- a/libs/CheatEngine.SDK.Abi/Native/ClassicExportedFunctionsPrefixReader.cs +++ b/libs/CheatEngine.SDK.Abi/Native/ClassicExportedFunctionsPrefixReader.cs @@ -15,7 +15,8 @@ namespace CheatEngine.SDK.Abi.Native; /// /// All or nothing. The copy succeeds only when both the declared size and the physical buffer cover the /// whole prefix, = 144 bytes, the minDeclaredSize of slot 17 in -/// tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json. A table that declares, say, 64 bytes yields no prefix at all, +/// tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json. A table that declares, +/// say, 64 bytes yields no prefix at all, /// not the first seven slots; ClassicExportedFunctionsSlotReader is the per-slot observation path. /// /// diff --git a/libs/CheatEngine.SDK.Abi/Native/ClassicExportedFunctionsSlotReader.cs b/libs/CheatEngine.SDK.Abi/Native/ClassicExportedFunctionsSlotReader.cs index 95c88236..84127594 100644 --- a/libs/CheatEngine.SDK.Abi/Native/ClassicExportedFunctionsSlotReader.cs +++ b/libs/CheatEngine.SDK.Abi/Native/ClassicExportedFunctionsSlotReader.cs @@ -17,7 +17,8 @@ namespace CheatEngine.SDK.Abi.Native; /// /// /// Scope. Slots 1 to 158 of TExportedFunctions5 (plugin contract 6, 159 fields, 1272 bytes on x64, -/// tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json); slot 0 is the declared size itself. No managed-hostfxr plugin +/// tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json); slot 0 is the declared +/// size itself. No managed-hostfxr plugin /// receives this table, so there is no production caller: the classic facade is deferred and every slot stays /// NotObserved on the qualifiable profile. x64 only, like the rest of the assembly. /// diff --git a/libs/CheatEngine.SDK.Abi/Native/ClassicSlotObservation.cs b/libs/CheatEngine.SDK.Abi/Native/ClassicSlotObservation.cs index 3c56e562..676e6301 100644 --- a/libs/CheatEngine.SDK.Abi/Native/ClassicSlotObservation.cs +++ b/libs/CheatEngine.SDK.Abi/Native/ClassicSlotObservation.cs @@ -10,7 +10,9 @@ namespace CheatEngine.SDK.Abi.Native; /// /// /// An observation, not a capability: is the pointer-sized value the table held when it -/// was read. Depending on the slot (see tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json) it is a function address, +/// was read. Depending on the slot (see +/// tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json) it is a function +/// address, /// the address of a host cell that holds a function pointer, the address of a host variable, or nil. Nothing /// here dereferences, invokes or caches it; two reads of the same slot are two independent observations. /// diff --git a/libs/CheatEngine.SDK.Abi/Native/ExportedFunctionsPrefix.cs b/libs/CheatEngine.SDK.Abi/Native/ExportedFunctionsPrefix.cs index 2b213159..182d72b0 100644 --- a/libs/CheatEngine.SDK.Abi/Native/ExportedFunctionsPrefix.cs +++ b/libs/CheatEngine.SDK.Abi/Native/ExportedFunctionsPrefix.cs @@ -13,7 +13,8 @@ namespace CheatEngine.SDK.Abi.Native; /// validate , and impose its own lifetime, main-thread, and failure policy. /// /// -/// Evidence: slots 0-17 of the classic slot registry (tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json). Its +/// Evidence: slots 0-17 of the classic slot registry ( +/// tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json). Its /// authority is the host type TExportedFunctions5 of the pinned plugin.pas (fields lines 47-226, /// assignments of TPluginHandler.create lines 1856-2045); cepluginsdk.h and /// cepluginsdk.pas are mirror columns only. Offsets are Deduced from the declarations (x64 natural diff --git a/libs/CheatEngine.SDK.Abi/Native/NativeExportNames.cs b/libs/CheatEngine.SDK.Abi/Native/NativeExportNames.cs index aba09c29..edceb432 100644 --- a/libs/CheatEngine.SDK.Abi/Native/NativeExportNames.cs +++ b/libs/CheatEngine.SDK.Abi/Native/NativeExportNames.cs @@ -3,7 +3,8 @@ namespace CheatEngine.SDK.Abi.Native; /// /// The names of the three functions a classic native plugin DLL exports. Classic native load path only: a /// NativeAOT DLL exposing them is not a supported CheatEngine.SDK profile, because Cheat Engine unloads plugins with -/// FreeLibrary, which .NET does not support for NativeAOT libraries; see libs/CheatEngine.SDK.Abi/README.md. +/// FreeLibrary, which .NET does not support for NativeAOT libraries; see +/// libs/CheatEngine.SDK.Abi/README.md. /// /// /// diff --git a/libs/CheatEngine.SDK.Abi/Native/PluginType0Record.cs b/libs/CheatEngine.SDK.Abi/Native/PluginType0Record.cs index 9bd68569..28732c81 100644 --- a/libs/CheatEngine.SDK.Abi/Native/PluginType0Record.cs +++ b/libs/CheatEngine.SDK.Abi/Native/PluginType0Record.cs @@ -25,7 +25,8 @@ namespace CheatEngine.SDK.Abi.Native; /// of the same name with address: dword, which moves ispointer to 12 and countoffsets to /// 16 while keeping 48 bytes, and a TSelectedRecord (lines 147-156) with a one-byte /// ispointer: boolean at the host offsets. Neither is x64 authority; a size check alone cannot tell them -/// apart (per-field table in libs/CheatEngine.SDK.Abi/README.md, tests SelectedRecordOracleTests and the +/// apart (per-field table in libs/CheatEngine.SDK.Abi/README.md, tests SelectedRecordOracleTests and +/// the /// compiled fixture facts host_plugin0_selected_record, pascal_dword_mirror_selected_record, /// pascal_boolean_mirror_selected_record). /// diff --git a/libs/CheatEngine.SDK.Abi/README.md b/libs/CheatEngine.SDK.Abi/README.md index ba45a5e8..b25c5b3a 100644 --- a/libs/CheatEngine.SDK.Abi/README.md +++ b/libs/CheatEngine.SDK.Abi/README.md @@ -68,7 +68,8 @@ These installed-file hashes were recorded in a source index that was retired on remain declarations (`DeclaredRepo`) until an exact-host measurement re-measures them. The independently compiled fixture is deliberately more limited: it compiles a checked-in transcription of the pinned upstream C-header subset under MSVC x64, validates 104 facts, and compares its `sizeof`, `offsetof`, alignment, export, and topology facts -with a versioned expectation. The Debug CI test run also passes that facts file into a compiled managed test, which measures +with a versioned expectation. The Debug CI test run also passes that facts file into a compiled managed test, which +measures the matching managed record sizes, offsets, and alignments directly. It is therefore a `compiled-transcription-fixture` proof, not proof that a live CE host loads a slot, uses a given Pascal boolean width, or provides a non-null table entry. The records stay internal until a @@ -86,8 +87,8 @@ its own. Cheat Engine hands a plugin one of two exported-function tables, depending on how the plugin was loaded: -| Route | Entry point | Table the plugin receives | -|-------------------|-----------------------------------------------------|--------------------------------------------------------------------------------------------| +| Route | Entry point | Table the plugin receives | +|-------------------|----------------------------------------------------|-------------------------------------------------------------------------------------------| | Managed (hostfxr) | `CESDK.CESDK.CEPluginInitialize(IntPtr, int)` | `ManagedExportedFunctions`: 48 bytes, six fields, filled by Cheat Engine's managed loader | | Classic native | `CEPlugin_GetVersion`, `CEPlugin_InitializePlugin` | `TExportedFunctions5` of `plugin.pas`: 159 slots, 1272 bytes on x64 | @@ -109,16 +110,16 @@ The oracle for `PluginType0Record` is the host type actually passed: `TPlugin0_S with. The Pascal kit unit `cepluginsdk.pas` has two known-wrong mirrors. All three are 48 bytes, so only a per-field check separates them (`SelectedRecordOracleTests`, registry divergence D09): -| Field | Host type (oracle) | `cepluginsdk.pas` dword mirror (lines 161-170) | `cepluginsdk.pas` `TSelectedRecord` (lines 147-156) | -|-----------------------|---------------------|--------------------------------------------------|--------------------------------------------------------| -| `interpretedaddress` | 0, 8 bytes | 0, 8 bytes | 0, 8 bytes | -| `address` | 8, 8 bytes | 8, **4 bytes** | 8, 8 bytes | -| `ispointer` | 16, 4 bytes | **12**, 4 bytes | 16, **1 byte** | -| `countoffsets` | 20, 4 bytes | **16**, 4 bytes | 20, 4 bytes | -| `offsets` | 24, 8 bytes | 24, 8 bytes | 24, 8 bytes | -| `description` | 32, 8 bytes | 32, 8 bytes | 32, 8 bytes | -| `valuetype` | 40, 1 byte | 40, 1 byte | 40, 1 byte | -| `size` | 41, 1 byte | 41, 1 byte | 41, 1 byte | +| Field | Host type (oracle) | `cepluginsdk.pas` dword mirror (lines 161-170) | `cepluginsdk.pas` `TSelectedRecord` (lines 147-156) | +|----------------------|--------------------|------------------------------------------------|-----------------------------------------------------| +| `interpretedaddress` | 0, 8 bytes | 0, 8 bytes | 0, 8 bytes | +| `address` | 8, 8 bytes | 8, **4 bytes** | 8, 8 bytes | +| `ispointer` | 16, 4 bytes | **12**, 4 bytes | 16, **1 byte** | +| `countoffsets` | 20, 4 bytes | **16**, 4 bytes | 20, 4 bytes | +| `offsets` | 24, 8 bytes | 24, 8 bytes | 24, 8 bytes | +| `description` | 32, 8 bytes | 32, 8 bytes | 32, 8 bytes | +| `valuetype` | 40, 1 byte | 40, 1 byte | 40, 1 byte | +| `size` | 41, 1 byte | 41, 1 byte | 41, 1 byte | Which record the 7.7.0.10621 binary passes is `NotObserved`: no managed route reaches a type-0 registration, so the type-0 callback stays `void*`. @@ -130,13 +131,13 @@ not a supported CheatEngine.SDK profile.** Unloading a Native AOT library with ` supported by .NET (https://learn.microsoft.com/dotnet/core/deploying/native-aot/libraries, audit source EXT-01), and Cheat Engine removes a plugin with `FreeLibrary`. -| Profile | Status in CheatEngine.SDK 2.0 | Evidence and boundary | -|---|---|---| -| Historical CLR route: `MSCorEE.dll` hosting with a string entry point, as in the historical public C# template | Documentary only, **not supported** | Described by the pinned public source (`ce-public-src-ec45d5f`), which is never qualifiable. The SDK does not downgrade to that bootstrap. | -| **Managed hostfxr route** | **The only qualifiable profile**: `ce-7.7.0.10621-x64-managed-hostfxr` | Cheat Engine 7.7.0.10621 x64 (`cheatengine-x86_64.exe` SHA-256 `9727076da50924e4a097b49a02155e4b34759269c3017ff31375364b8826eb4d`), with a `ce.runtimeconfig.json` recorded as a local modification (`LocalModified`), never an installer baseline. The plugin is a framework-dependent folder; the SDK generates `int CESDK.CESDK.CEPluginInitialize(IntPtr args, int size)`, which fills the 36-byte packed `PluginInitRecord` and receives the 48-byte managed exports table. | -| NativeAOT plugin DLL | **Not supported** | Cheat Engine unloads plugins with `FreeLibrary`, which .NET does not support for NativeAOT libraries. No residence model exists in 2.0: a resident native adapter separate from an AOT component is a possible future architecture with its own contract and proof (audit A04-07, deferred), not a change of the existing profile. Q42 is recorded `NotApplicable` for this reason. | -| Classic native plugin exporting `CEPlugin_*` | **Not provided by the SDK** | The classic path receives the 159-slot classic table (the committed registry above); no managed route reaches it and the SDK has no classic facade. A package can never add native exports to a consumer: only `UnmanagedCallersOnly` methods of the published assembly become exports (https://learn.microsoft.com/dotnet/core/deploying/native-aot/interop#native-exports). | -| x86 or ARM64 host | **Not supported** | `AbiArchitecture` accepts x64 only; the packaged target refuses other explicit `PlatformTarget` values with `CESDK9101`. x64 layout tests make no x86 or ARM64 promise. | +| Profile | Status in CheatEngine.SDK 2.0 | Evidence and boundary | +|----------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Historical CLR route: `MSCorEE.dll` hosting with a string entry point, as in the historical public C# template | Documentary only, **not supported** | Described by the pinned public source (`ce-public-src-ec45d5f`), which is never qualifiable. The SDK does not downgrade to that bootstrap. | +| **Managed hostfxr route** | **The only qualifiable profile**: `ce-7.7.0.10621-x64-managed-hostfxr` | Cheat Engine 7.7.0.10621 x64 (`cheatengine-x86_64.exe` SHA-256 `9727076da50924e4a097b49a02155e4b34759269c3017ff31375364b8826eb4d`), with a `ce.runtimeconfig.json` recorded as a local modification (`LocalModified`), never an installer baseline. The plugin is a framework-dependent folder; the SDK generates `int CESDK.CESDK.CEPluginInitialize(IntPtr args, int size)`, which fills the 36-byte packed `PluginInitRecord` and receives the 48-byte managed exports table. | +| NativeAOT plugin DLL | **Not supported** | Cheat Engine unloads plugins with `FreeLibrary`, which .NET does not support for NativeAOT libraries. No residence model exists in 2.0: a resident native adapter separate from an AOT component is a possible future architecture with its own contract and proof (audit A04-07, deferred), not a change of the existing profile. Q42 is recorded `NotApplicable` for this reason. | +| Classic native plugin exporting `CEPlugin_*` | **Not provided by the SDK** | The classic path receives the 159-slot classic table (the committed registry above); no managed route reaches it and the SDK has no classic facade. A package can never add native exports to a consumer: only `UnmanagedCallersOnly` methods of the published assembly become exports (https://learn.microsoft.com/dotnet/core/deploying/native-aot/interop#native-exports). | +| x86 or ARM64 host | **Not supported** | `AbiArchitecture` accepts x64 only; the packaged target refuses other explicit `PlatformTarget` values with `CESDK9101`. x64 layout tests make no x86 or ARM64 promise. | **What "AOT-compatible libraries" means.** The shipping libraries set `IsAotCompatible=true`, and `tests/CheatEngine.SDK.AotProbe` publishes the complete shipping graph as a standalone Native AOT executable. That @@ -159,10 +160,10 @@ NativeAOT publish success is never a Cheat Engine load success.** 4. **Coexistence.** Even a future residence model would have to repeat the two-plugin protocol (Q09, Q10): a solution to unloading does not isolate static state or Lua globals by itself. -| Diagnostic | Where | What it catches | -|---|---|---| -| `CESDK9102` (`analyzers/docs/CESDK9102.md`) | MSBuild warning of the packaged `build/CheatEngine.SDK.targets` (target `CheatEngineSdkWarnNativeAotPluginProfile`), direct package consumers only | A library (not `Exe`/`WinExe`) that sets `PublishAot=true`, with or without `NativeLib`. Suppressible with `NoWarn`. | -| `CESDK0006` (`analyzers/docs/CESDK0006.md`) | Roslyn analyzer shipped in the package | An `[UnmanagedCallersOnly]` method whose constant `EntryPoint` starts with `CEPlugin_`, including `NativeExportNames.*`. Unprefixed historical names are not flagged (documented limitation). | +| Diagnostic | Where | What it catches | +|---------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `CESDK9102` (`analyzers/docs/CESDK9102.md`) | MSBuild warning of the packaged `build/CheatEngine.SDK.targets` (target `CheatEngineSdkWarnNativeAotPluginProfile`), direct package consumers only | A library (not `Exe`/`WinExe`) that sets `PublishAot=true`, with or without `NativeLib`. Suppressible with `NoWarn`. | +| `CESDK0006` (`analyzers/docs/CESDK0006.md`) | Roslyn analyzer shipped in the package | An `[UnmanagedCallersOnly]` method whose constant `EntryPoint` starts with `CEPlugin_`, including `NativeExportNames.*`. Unprefixed historical names are not flagged (documented limitation). | **Evidence.** Q41 (NativeAOT publish and export inspection, C0/C2): C0 is `Passed` from the static contract tests below — the loader harness refuses any `CEPlugin_*` export, any missing probe export and any unexpected export diff --git a/libs/CheatEngine.SDK.Engine/AddressList/AddressListCalls.cs b/libs/CheatEngine.SDK.Engine/AddressList/AddressListCalls.cs index 30036470..ca6eaa62 100644 --- a/libs/CheatEngine.SDK.Engine/AddressList/AddressListCalls.cs +++ b/libs/CheatEngine.SDK.Engine/AddressList/AddressListCalls.cs @@ -32,7 +32,7 @@ public static bool TryGetGlobal(LuaRef cache, ReadOnlySpan try { if (!LuaGlobalFunctions.TryPush(state, cache, global) || !state.TryCall(0, 1).IsOk || - !TMarshaller.TryRead(state, -1, out result)) + !TMarshaller.TryRead(state, -1, out result)) { return LuaCallSupport.Fail(state, top, out result); } diff --git a/libs/CheatEngine.SDK.Engine/AddressList/AddressListMutations.cs b/libs/CheatEngine.SDK.Engine/AddressList/AddressListMutations.cs index 721ed89a..b0a697bd 100644 --- a/libs/CheatEngine.SDK.Engine/AddressList/AddressListMutations.cs +++ b/libs/CheatEngine.SDK.Engine/AddressList/AddressListMutations.cs @@ -438,7 +438,7 @@ private static MemoryRecordMutationOutcome ValidateParentChain(LuaState state, M { HashSet seen = new(); MemoryRecord current = proposedParent; - for (int hops = 0; ; hops++) + for (int hops = 0;; hops++) { LuaStatus status = current.Handle.TryGetProperty(state, "ID"u8); if (!status.IsOk) diff --git a/libs/CheatEngine.SDK.Engine/AddressList/MemoryRecordActivationOutcome.cs b/libs/CheatEngine.SDK.Engine/AddressList/MemoryRecordActivationOutcome.cs index a85ace9a..7ff0bc40 100644 --- a/libs/CheatEngine.SDK.Engine/AddressList/MemoryRecordActivationOutcome.cs +++ b/libs/CheatEngine.SDK.Engine/AddressList/MemoryRecordActivationOutcome.cs @@ -9,7 +9,8 @@ namespace CheatEngine.SDK.Engine.AddressList; /// /// follows from : is /// ; and -/// are ; every +/// are ; +/// every /// other kind is . The before and after states are the values actually read; /// means that no value was observed. /// diff --git a/libs/CheatEngine.SDK.Engine/Allocation/AllocatedRegion.cs b/libs/CheatEngine.SDK.Engine/Allocation/AllocatedRegion.cs index 2184a939..10e168c9 100644 --- a/libs/CheatEngine.SDK.Engine/Allocation/AllocatedRegion.cs +++ b/libs/CheatEngine.SDK.Engine/Allocation/AllocatedRegion.cs @@ -291,7 +291,7 @@ private TargetMemoryOperationOutcome ReleaseTakenWithOutcome() return outcome; } catch (InvalidOperationException) when (!LuaRuntime.IsAttached || - !EngineResourceOrigin.IsCurrent(Origin.Runtime)) + !EngineResourceOrigin.IsCurrent(Origin.Runtime)) { // The binding could not acquire a Lua operation: deAlloc never ran. _lastReleaseOutcome = TargetReleaseOutcome.NotInvoked(EngineFailureKind.BindingFailure); @@ -313,7 +313,7 @@ private TargetMemoryOperationOutcome ReleaseTakenWithOutcome() private void ThrowForReleaseOutcome(TargetMemoryOperationOutcome outcome) { if (outcome.Kind is TargetMemoryOperationOutcomeKind.TargetIdentityUnavailable or - TargetMemoryOperationOutcomeKind.TargetIdentityMismatch) + TargetMemoryOperationOutcomeKind.TargetIdentityMismatch) { throw new EngineTargetIdentityException("TargetMemoryDeallocate", LastReleaseOutcome.TargetCheck.GetValueOrDefault()); diff --git a/libs/CheatEngine.SDK.Engine/Allocation/TargetMemoryAllocator.cs b/libs/CheatEngine.SDK.Engine/Allocation/TargetMemoryAllocator.cs index 6413a29e..cfd4413b 100644 --- a/libs/CheatEngine.SDK.Engine/Allocation/TargetMemoryAllocator.cs +++ b/libs/CheatEngine.SDK.Engine/Allocation/TargetMemoryAllocator.cs @@ -403,7 +403,7 @@ private static void ThrowForAllocationOutcome(TargetMemoryOperationOutcome outco } if (outcome.Kind is TargetMemoryOperationOutcomeKind.TargetIdentityUnavailable or - TargetMemoryOperationOutcomeKind.TargetIdentityMismatch) + TargetMemoryOperationOutcomeKind.TargetIdentityMismatch) { throw new EngineTargetIdentityException(AllocateOperation, GetUnavailableTargetCheck()); } diff --git a/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerOptions.cs b/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerOptions.cs index f8ad8cfd..d24d7326 100644 --- a/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerOptions.cs +++ b/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerOptions.cs @@ -3,7 +3,8 @@ namespace CheatEngine.SDK.Engine.Assembly; /// -/// Bounds and opt-ins for +/// Bounds and opt-ins for +/// /// and . /// /// @@ -21,7 +22,8 @@ namespace CheatEngine.SDK.Engine.Assembly; /// /// /// Values are validated when the options are used: an out-of-range value makes the call throw -/// before any Lua work. Instances are immutable after initialization and +/// before any Lua work. Instances are immutable after initialization +/// and /// can be shared between threads. /// /// diff --git a/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerPatcher.cs b/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerPatcher.cs index 9bc6a283..9ae4c9ab 100644 --- a/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerPatcher.cs +++ b/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerPatcher.cs @@ -32,7 +32,8 @@ namespace CheatEngine.SDK.Engine.Assembly; /// /// /// autoAssemble is called with three results (success, disable information or error detail, compilation -/// warnings) so that no result Cheat Engine returns is dropped. +/// warnings) so that no result Cheat Engine returns is dropped. +/// /// reports every result as an ; the older and /// keep their Boolean and exception contracts. Both globals are resolved through the SDK's /// cached, protected global push. @@ -148,7 +149,10 @@ public static AutoAssemblerApplyOutcome TryApplyWithOutcome(string script, AutoA /// Checks with autoAssembleCheck and . /// /// The Auto Assembler script to check. - /// to check the [ENABLE] section, for [DISABLE]. + /// + /// to check the [ENABLE] section, for + /// [DISABLE]. + /// /// The outcome of the check. /// is empty or white-space only. /// The plugin is not enabled or the calling thread has no Lua state. @@ -163,7 +167,10 @@ public static AutoAssemblerCheckOutcome TryCheck(string script, bool enable) /// (never targetself). /// /// The Auto Assembler script to check. - /// to check the [ENABLE] section, for [DISABLE]. + /// + /// to check the [ENABLE] section, for + /// [DISABLE]. + /// /// The host-text opt-in and bound. /// The outcome of the check. /// is empty or white-space only. @@ -338,7 +345,8 @@ internal static AutoAssemblerApplyOutcome ApplyCore(string script, AutoAssembler // Retain the original table on the stack while the copy is rooted. A failed root leaves the original table as // the one remaining authority for a direct, target-checked disable. - LuaRef? disableInfo = TryTrackDisableInfo(state, detail, warnings, disableInfoTracker, out Exception? trackingFailure); + LuaRef? disableInfo = + TryTrackDisableInfo(state, detail, warnings, disableInfoTracker, out Exception? trackingFailure); if (disableInfo is null) { cause = trackingFailure; @@ -352,7 +360,7 @@ internal static AutoAssemblerApplyOutcome ApplyCore(string script, AutoAssembler { snapshot = AutoAssemblerDisableInfoSnapshot.Read(state, detail, options); patch = patchFactory(script, disableInfo, origin, snapshot, postCheck) ?? - throw new InvalidOperationException("The Auto Assembler patch factory returned no patch."); + throw new InvalidOperationException("The Auto Assembler patch factory returned no patch."); } catch (Exception exception) { diff --git a/libs/CheatEngine.SDK.Engine/Assembly/InstructionAssembly.cs b/libs/CheatEngine.SDK.Engine/Assembly/InstructionAssembly.cs index 1843a035..df4a1e1b 100644 --- a/libs/CheatEngine.SDK.Engine/Assembly/InstructionAssembly.cs +++ b/libs/CheatEngine.SDK.Engine/Assembly/InstructionAssembly.cs @@ -11,7 +11,9 @@ namespace CheatEngine.SDK.Engine.Assembly; /// The same instruction text assembles to different bytes for a different origin, jump preference or range-check /// option, or for another target profile. This value keeps them together with the result so that bytes are never /// reused in a context they were not produced for (audit ch.15, A15-04). It is filled on every outcome of -/// : +/// +/// : /// the context fields always echo the request, while is non-zero only on success. /// /// It owns no Lua storage and no Cheat Engine object; it stays valid after the Lua runtime detaches. diff --git a/libs/CheatEngine.SDK.Engine/Assembly/InstructionDisassembler.cs b/libs/CheatEngine.SDK.Engine/Assembly/InstructionDisassembler.cs index d889fb9e..e3588c99 100644 --- a/libs/CheatEngine.SDK.Engine/Assembly/InstructionDisassembler.cs +++ b/libs/CheatEngine.SDK.Engine/Assembly/InstructionDisassembler.cs @@ -120,9 +120,9 @@ public static InstructionOperationStatus TryDisassemble(InstructionTargetProfile } if (!state.TryReadUtf8(-4, out ReadOnlySpan addressUtf8) || - !state.TryReadUtf8(-3, out ReadOnlySpan bytesUtf8) || - !state.TryReadUtf8(-2, out ReadOnlySpan opcodeUtf8) || - !state.TryReadUtf8(-1, out ReadOnlySpan extraUtf8)) + !state.TryReadUtf8(-3, out ReadOnlySpan bytesUtf8) || + !state.TryReadUtf8(-2, out ReadOnlySpan opcodeUtf8) || + !state.TryReadUtf8(-1, out ReadOnlySpan extraUtf8)) { return InstructionOperationStatus.InvalidResult; } diff --git a/libs/CheatEngine.SDK.Engine/Assembly/InstructionProfiles.cs b/libs/CheatEngine.SDK.Engine/Assembly/InstructionProfiles.cs index 8f263bf4..6ae45ddf 100644 --- a/libs/CheatEngine.SDK.Engine/Assembly/InstructionProfiles.cs +++ b/libs/CheatEngine.SDK.Engine/Assembly/InstructionProfiles.cs @@ -64,8 +64,8 @@ public static InstructionOperationStatus TryObserveCurrent(out InstructionTarget } if (!RuntimeInfo.TryDeriveTargetArchitecture(probe.IsX86Family.GetValueOrDefault(), - probe.IsArmFamily.GetValueOrDefault(), probe.Is64Bit.GetValueOrDefault(), - out CheatEngineArchitecture architecture)) + probe.IsArmFamily.GetValueOrDefault(), probe.Is64Bit.GetValueOrDefault(), + out CheatEngineArchitecture architecture)) { return InstructionOperationStatus.InvalidProfile; } diff --git a/libs/CheatEngine.SDK.Engine/Enums/CEEnumNames.cs b/libs/CheatEngine.SDK.Engine/Enums/CEEnumNames.cs index b130deb9..b793f0af 100644 --- a/libs/CheatEngine.SDK.Engine/Enums/CEEnumNames.cs +++ b/libs/CheatEngine.SDK.Engine/Enums/CEEnumNames.cs @@ -312,8 +312,8 @@ public static ReadOnlySpan ToCEName(this MemoryProtection value) public static bool TryParseCEName(ReadOnlySpan ceName, out MemoryProtection value) { for (MemoryProtection candidate = MemoryProtection.ReadOnly; - candidate <= MemoryProtection.ExecuteWriteCopy; - candidate = (MemoryProtection) ((uint) candidate << 1)) + candidate <= MemoryProtection.ExecuteWriteCopy; + candidate = (MemoryProtection) ((uint) candidate << 1)) { if (ceName.SequenceEqual(candidate.ToCEName())) { diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineGlobalUnavailableException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineGlobalUnavailableException.cs index 0493514c..f504b52b 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineGlobalUnavailableException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineGlobalUnavailableException.cs @@ -49,6 +49,6 @@ public string Operation private static string CreateDefaultMessage(string operation) { return "The required binding global for Cheat Engine operation '" + - RequireText(operation, nameof(operation)) + "' is unavailable."; + RequireText(operation, nameof(operation)) + "' is unavailable."; } } diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineLuaException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineLuaException.cs index 0ff4c182..77bb10a3 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineLuaException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineLuaException.cs @@ -75,6 +75,6 @@ private static string CreateDefaultMessage(string operation, LuaStatus status) } return "The protected Lua operation '" + RequireText(operation, nameof(operation)) + "' failed with status " + - status + "."; + status + "."; } } diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs index 41a9fb49..a8fb204b 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs @@ -87,8 +87,8 @@ private static string CreateDefaultMessage(string operation, EngineMarshallingDi string directionText = ValidateDirection(direction) == EngineMarshallingDirection.Argument ? "argument" : "result"; return "The " + directionText + " of Cheat Engine operation '" + - RequireText(operation, nameof(operation)) + "' could not be marshalled: expected " + - RequireText(expected, nameof(expected)) + ", observed " + RequireText(actual, nameof(actual)) + "."; + RequireText(operation, nameof(operation)) + "' could not be marshalled: expected " + + RequireText(expected, nameof(expected)) + ", observed " + RequireText(actual, nameof(actual)) + "."; } private static EngineMarshallingDirection ValidateDirection(EngineMarshallingDirection direction) diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineResourceHandoffException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineResourceHandoffException.cs index f29f792e..a95af947 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineResourceHandoffException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineResourceHandoffException.cs @@ -48,7 +48,7 @@ public TargetReleaseOutcome CleanupOutcome private static string CreateMessage(string operation, TargetReleaseOutcome cleanupOutcome) { return "The Engine operation '" + RequireText(operation, nameof(operation)) + - "' completed before its ownership could be published; compensation ended as " + - cleanupOutcome.Status + "."; + "' completed before its ownership could be published; compensation ended as " + + cleanupOutcome.Status + "."; } } diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineTargetIdentityException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineTargetIdentityException.cs index 0791a540..40e0063f 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineTargetIdentityException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineTargetIdentityException.cs @@ -36,6 +36,6 @@ public TargetIdentityCheck Check private static string CreateMessage(string operation, TargetIdentityCheck check) { return "The Engine operation '" + RequireText(operation, nameof(operation)) + - "' was refused because its original target is not verified as current (" + check.Kind + ")."; + "' was refused because its original target is not verified as current (" + check.Kind + ")."; } } diff --git a/libs/CheatEngine.SDK.Engine/Inspection/EngineInspection.cs b/libs/CheatEngine.SDK.Engine/Inspection/EngineInspection.cs index 73b5aedf..e081e23c 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/EngineInspection.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/EngineInspection.cs @@ -512,7 +512,7 @@ private static InspectionStatus ReadModuleCollection(LuaState state, int tableIn for (int index = 0; index < sequenceCount; index++) { if (state.RawGetSequenceItem(tableIndex, index) != LuaType.Table || - !TryReadModuleInfo(state, -1, out snapshot[index])) + !TryReadModuleInfo(state, -1, out snapshot[index])) { return InspectionStatus.InvalidResult; } @@ -554,7 +554,7 @@ private static InspectionStatus ReadSectionCollection(LuaState state, int tableI for (int index = 0; index < sequenceCount; index++) { if (state.RawGetSequenceItem(tableIndex, index) != LuaType.Table || - !TryReadModuleSectionInfo(state, -1, out snapshot[index])) + !TryReadModuleSectionInfo(state, -1, out snapshot[index])) { return InspectionStatus.InvalidResult; } @@ -596,7 +596,7 @@ private static InspectionStatus ReadMemoryRegionCollection(LuaState state, int t for (int index = 0; index < sequenceCount; index++) { if (state.RawGetSequenceItem(tableIndex, index) != LuaType.Table || - !TryReadMemoryRegionInfo(state, -1, out snapshot[index])) + !TryReadMemoryRegionInfo(state, -1, out snapshot[index])) { return InspectionStatus.InvalidResult; } @@ -627,10 +627,10 @@ private static bool TryReadModuleInfo(LuaState state, int tableIndex, out Module { module = default; if (!TryReadRequiredStringField(state, tableIndex, "Name"u8, out string? name) || - !TryReadAddressField(state, tableIndex, "Address"u8, out Address address) || - !TryReadOptionalMemorySizeField(state, tableIndex, "Size"u8, out MemorySize? size) || - !TryReadBooleanField(state, tableIndex, "Is64Bit"u8, out bool is64Bit) || - !TryReadRequiredStringField(state, tableIndex, "PathToFile"u8, out string? pathToFile)) + !TryReadAddressField(state, tableIndex, "Address"u8, out Address address) || + !TryReadOptionalMemorySizeField(state, tableIndex, "Size"u8, out MemorySize? size) || + !TryReadBooleanField(state, tableIndex, "Is64Bit"u8, out bool is64Bit) || + !TryReadRequiredStringField(state, tableIndex, "PathToFile"u8, out string? pathToFile)) { return false; } @@ -643,9 +643,9 @@ private static bool TryReadModuleSectionInfo(LuaState state, int tableIndex, out { section = default; if (!TryReadRequiredStringField(state, tableIndex, "Name"u8, out string? name) || - !TryReadMemorySizeField(state, tableIndex, "Size"u8, out MemorySize size) || - !TryReadAddressField(state, tableIndex, "Address"u8, out Address address) || - !TryReadUInt64Field(state, tableIndex, "FileAddress"u8, out ulong fileAddress)) + !TryReadMemorySizeField(state, tableIndex, "Size"u8, out MemorySize size) || + !TryReadAddressField(state, tableIndex, "Address"u8, out Address address) || + !TryReadUInt64Field(state, tableIndex, "FileAddress"u8, out ulong fileAddress)) { return false; } @@ -658,9 +658,9 @@ private static bool TryReadSymbolInfo(LuaState state, int tableIndex, out Symbol { symbol = default; if (!TryReadRequiredStringField(state, tableIndex, "modulename"u8, out string? moduleName) || - !TryReadRequiredStringField(state, tableIndex, "searchkey"u8, out string? searchKey) || - !TryReadAddressField(state, tableIndex, "address"u8, out Address address) || - !TryReadMemorySizeField(state, tableIndex, "symbolsize"u8, out MemorySize size)) + !TryReadRequiredStringField(state, tableIndex, "searchkey"u8, out string? searchKey) || + !TryReadAddressField(state, tableIndex, "address"u8, out Address address) || + !TryReadMemorySizeField(state, tableIndex, "symbolsize"u8, out MemorySize size)) { return false; } @@ -673,14 +673,14 @@ private static bool TryReadMemoryRegionInfo(LuaState state, int tableIndex, out { region = default; if (!TryReadAddressField(state, tableIndex, "BaseAddress"u8, out Address baseAddress) || - !TryReadAddressField(state, tableIndex, "AllocationBase"u8, out Address allocationBase) || - !TryReadProtectionField(state, tableIndex, "AllocationProtect"u8, - out MemoryProtection allocationProtection) || - !TryReadMemorySizeField(state, tableIndex, "RegionSize"u8, out MemorySize size) || - !TryReadUInt32Field(state, tableIndex, "State"u8, out uint stateValue) || - !TryReadProtectionField(state, tableIndex, "Protect"u8, out MemoryProtection protection) || - !TryReadUInt32Field(state, tableIndex, "Type"u8, out uint typeValue) || - !TryReadOptionalStringField(state, tableIndex, "Extra"u8, out string? extra)) + !TryReadAddressField(state, tableIndex, "AllocationBase"u8, out Address allocationBase) || + !TryReadProtectionField(state, tableIndex, "AllocationProtect"u8, + out MemoryProtection allocationProtection) || + !TryReadMemorySizeField(state, tableIndex, "RegionSize"u8, out MemorySize size) || + !TryReadUInt32Field(state, tableIndex, "State"u8, out uint stateValue) || + !TryReadProtectionField(state, tableIndex, "Protect"u8, out MemoryProtection protection) || + !TryReadUInt32Field(state, tableIndex, "Type"u8, out uint typeValue) || + !TryReadOptionalStringField(state, tableIndex, "Extra"u8, out string? extra)) { return false; } diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationHandoffException.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationHandoffException.cs index 03049b96..2bbef454 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationHandoffException.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationHandoffException.cs @@ -39,7 +39,8 @@ public SymbolListRegistrationReleaseOutcome CleanupOutcome private static string CreateMessage(SymbolListRegistrationReleaseOutcome cleanupOutcome) { - return "Cheat Engine registered a symbol list before its managed lease could be published; compensation ended as " + - cleanupOutcome.UnregisterKind + "."; + return + "Cheat Engine registered a symbol list before its managed lease could be published; compensation ended as " + + cleanupOutcome.UnregisterKind + "."; } } diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationLease.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationLease.cs index ddccbf9f..d3c1801c 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationLease.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationLease.cs @@ -18,7 +18,8 @@ namespace CheatEngine.SDK.Engine.Inspection; /// /// Created by , which transfers the list's into the /// lease. The order of is fixed: an already terminal lease reports -/// ; a detached runtime or another Lua universe reports +/// ; a detached runtime or another Lua universe +/// reports /// and abandons the list without any Cheat Engine call; /// an unavailable unregister member reports /// and keeps the lease retryable; an unregister() that raised reports @@ -140,7 +141,8 @@ public SymbolListRegistrationReleaseOutcome Release() if (!invoked) { // No unregister began (member absent, or its resolution failed): nothing changed, retry later. - return new SymbolListRegistrationReleaseOutcome(SymbolRegistrationReleaseKind.CleanupUnavailable, status, + return new SymbolListRegistrationReleaseOutcome(SymbolRegistrationReleaseKind.CleanupUnavailable, + status, default); } diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationReleaseOutcome.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationReleaseOutcome.cs index 4d600137..035d0bc1 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationReleaseOutcome.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolListRegistrationReleaseOutcome.cs @@ -19,7 +19,8 @@ internal SymbolListRegistrationReleaseOutcome(SymbolRegistrationReleaseKind unre /// /// Gets how the unregister step ended: , - /// , , + /// , + /// , /// (retryable) or /// . /// @@ -53,5 +54,6 @@ public TargetReleaseOutcome ListRelease /// Gets whether no later release attempt can be made through the lease. public bool IsTerminal => - UnregisterKind is not (SymbolRegistrationReleaseKind.Unknown or SymbolRegistrationReleaseKind.CleanupUnavailable); + UnregisterKind is not (SymbolRegistrationReleaseKind.Unknown + or SymbolRegistrationReleaseKind.CleanupUnavailable); } diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolLists.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolLists.cs index bcc7e6ee..c29a3694 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolLists.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolLists.cs @@ -38,7 +38,8 @@ public static class SymbolLists /// Creates one empty, unregistered, plugin-owned symbol list with createSymbolList(). /// The owner on success; otherwise. /// - /// with an owner, , + /// with an owner, + /// , /// , , or /// when Cheat Engine returned something that is not a host /// object. @@ -157,7 +158,8 @@ internal static LuaOperationStatus TryRegisterCore(Owned list, out S try { lease = leaseFactory(transferred, true) ?? - throw new InvalidOperationException("The symbol-list registration lease factory returned no lease."); + throw new InvalidOperationException( + "The symbol-list registration lease factory returned no lease."); } catch (Exception exception) { diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistrationLease.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistrationLease.cs index 659d02f9..2571e17b 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistrationLease.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistrationLease.cs @@ -17,7 +17,8 @@ namespace CheatEngine.SDK.Engine.Inspection; /// newer third-party definition is never removed. The check is best effort and not atomic: a third party can /// still replace the name between the lookup and the unregister, and a name that parses as an expression or that /// collides case-insensitively with another symbol can produce a conservative Replaced. It must never be -/// interpreted as exclusive host-wide ownership. Leases made through +/// interpreted as exclusive host-wide ownership. Leases made through +/// /// in this SDK instance additionally never unregister a newer lease's registration of the same name. /// /// diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistrationReleaseOutcome.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistrationReleaseOutcome.cs index da11ae70..f312857b 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistrationReleaseOutcome.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistrationReleaseOutcome.cs @@ -22,9 +22,11 @@ public SymbolRegistrationReleaseKind Kind /// /// Gets the status of the last CE call the release made: the unregister call, or the name lookup for - /// , + /// , + /// /// and a lookup failure. when no CE call was made at all - /// (, , + /// (, + /// , /// before any call). This is deliberately a nullable /// value rather than (): a no-call outcome must never /// be mistaken for regardless of which member of diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistry.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistry.cs index 7375e67c..28fa5fbc 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistry.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistry.cs @@ -206,7 +206,7 @@ internal static SymbolRegistrationReleaseOutcome ReleaseOwned(SymbolRegistration } if (!SOwnedRegistrations.TryGetValue(lease.Name, out SymbolRegistrationLease? current) || - !ReferenceEquals(current, lease)) + !ReferenceEquals(current, lease)) { lease.MarkTerminalAndObserve(SymbolRegistrationReleaseKind.Superseded); return new SymbolRegistrationReleaseOutcome(SymbolRegistrationReleaseKind.Superseded, NoBindingCall); @@ -238,7 +238,7 @@ private static SymbolRegistrationReleaseOutcome ReleaseCurrentLease(SymbolRegist status = UnregisterCore(lease.Name); } catch (InvalidOperationException) when (!LuaRuntime.IsAttached || - lease.Identity != LuaRuntime.CurrentStateIdentity) + lease.Identity != LuaRuntime.CurrentStateIdentity) { return MarkStaleRuntime(lease, NoBindingCall); } @@ -367,7 +367,7 @@ private static SymbolRegistrationReleaseOutcome CompensateFailedPublication(Symb status = UnregisterCore(name); } catch (InvalidOperationException) when (!LuaRuntime.IsAttached || - identity != LuaRuntime.CurrentStateIdentity) + identity != LuaRuntime.CurrentStateIdentity) { return new SymbolRegistrationReleaseOutcome(SymbolRegistrationReleaseKind.StaleRuntime, NoBindingCall); } @@ -407,7 +407,7 @@ private static void SupersedeCurrentLease(SymbolName name) private static void RemoveCurrentLease(SymbolRegistrationLease lease) { if (SOwnedRegistrations.TryGetValue(lease.Name, out SymbolRegistrationLease? current) && - ReferenceEquals(current, lease)) + ReferenceEquals(current, lease)) { SOwnedRegistrations.Remove(lease.Name); } diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolTableReader.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolTableReader.cs index e5f03cd5..53cdda0f 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolTableReader.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolTableReader.cs @@ -27,7 +27,7 @@ internal static bool TryRead(LuaState state, int index, out SymbolInfo symbol) using LuaFrame frame = new(state); if (!TryReadString(state, table, "modulename"u8, out string? moduleName) || - !TryReadString(state, table, "searchkey"u8, out string? searchKey)) + !TryReadString(state, table, "searchkey"u8, out string? searchKey)) { return false; } diff --git a/libs/CheatEngine.SDK.Engine/Memory/HostMemory.cs b/libs/CheatEngine.SDK.Engine/Memory/HostMemory.cs index 7a499299..e1bbb821 100644 --- a/libs/CheatEngine.SDK.Engine/Memory/HostMemory.cs +++ b/libs/CheatEngine.SDK.Engine/Memory/HostMemory.cs @@ -83,8 +83,8 @@ public static bool TryReadInt8(HostAddress address, out sbyte value, out MemoryA public static bool TryReadUInt16(HostAddress address, out ushort value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadSmallInteger, "readSmallIntegerLocal"u8, address.ToInt64(), false, - true, - out long raw, out failure) || raw < 0 || raw > ushort.MaxValue) + true, + out long raw, out failure) || raw < 0 || raw > ushort.MaxValue) { value = default; if (failure == MemoryAccessFailure.None) @@ -103,8 +103,8 @@ public static bool TryReadUInt16(HostAddress address, out ushort value, out Memo public static bool TryReadInt16(HostAddress address, out short value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadSmallInteger, "readSmallIntegerLocal"u8, address.ToInt64(), true, - true, - out long raw, out failure) || raw < short.MinValue || raw > short.MaxValue) + true, + out long raw, out failure) || raw < short.MinValue || raw > short.MaxValue) { value = default; if (failure == MemoryAccessFailure.None) @@ -123,8 +123,8 @@ public static bool TryReadInt16(HostAddress address, out short value, out Memory public static bool TryReadUInt32(HostAddress address, out uint value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadInteger, "readIntegerLocal"u8, address.ToInt64(), false, - true, out long raw, - out failure) || raw < 0 || (ulong) raw > uint.MaxValue) + true, out long raw, + out failure) || raw < 0 || (ulong) raw > uint.MaxValue) { value = default; if (failure == MemoryAccessFailure.None) @@ -143,8 +143,8 @@ public static bool TryReadUInt32(HostAddress address, out uint value, out Memory public static bool TryReadInt32(HostAddress address, out int value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadInteger, "readIntegerLocal"u8, address.ToInt64(), true, - true, out long raw, - out failure) || raw < int.MinValue || raw > int.MaxValue) + true, out long raw, + out failure) || raw < int.MinValue || raw > int.MaxValue) { value = default; if (failure == MemoryAccessFailure.None) @@ -163,8 +163,8 @@ public static bool TryReadInt32(HostAddress address, out int value, out MemoryAc public static bool TryReadUInt64(HostAddress address, out ulong value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadQword, "readQwordLocal"u8, address.ToInt64(), false, - false, out long raw, - out failure)) + false, out long raw, + out failure)) { value = default; return false; @@ -186,8 +186,8 @@ public static bool TryReadInt64(HostAddress address, out long value, out MemoryA public static bool TryReadPointer(HostAddress address, out HostAddress value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadPointer, "readPointerLocal"u8, address.ToInt64(), false, - false, out long raw, - out failure)) + false, out long raw, + out failure)) { value = default; return false; diff --git a/libs/CheatEngine.SDK.Engine/Memory/MemoryLua.cs b/libs/CheatEngine.SDK.Engine/Memory/MemoryLua.cs index 342fe523..6ac46977 100644 --- a/libs/CheatEngine.SDK.Engine/Memory/MemoryLua.cs +++ b/libs/CheatEngine.SDK.Engine/Memory/MemoryLua.cs @@ -288,7 +288,7 @@ private static bool TryCopyCompleteBytes(LuaState state, int table, Span d { LuaType type = state.RawGetIndex(table, index + 1L); bool valid = type == LuaType.Number && state.TryReadInteger(-1, out long value) - && (ulong) value <= byte.MaxValue; + && (ulong) value <= byte.MaxValue; state.Pop(1); if (!valid) { @@ -319,7 +319,7 @@ private static bool TryCopyPartialBytes(LuaState state, int table, Span de LuaType type = state.RawGetIndex(table, index + 1L); long value = default; bool valid = type == LuaType.Number && state.TryReadInteger(-1, out value) - && (ulong) value <= byte.MaxValue; + && (ulong) value <= byte.MaxValue; state.Pop(1); if (!valid) { diff --git a/libs/CheatEngine.SDK.Engine/Memory/TargetMemory.cs b/libs/CheatEngine.SDK.Engine/Memory/TargetMemory.cs index 35cccc18..28021e82 100644 --- a/libs/CheatEngine.SDK.Engine/Memory/TargetMemory.cs +++ b/libs/CheatEngine.SDK.Engine/Memory/TargetMemory.cs @@ -69,8 +69,8 @@ public static class TargetMemory public static bool TryReadUInt8(Address address, out byte value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadByte, "readByte"u8, address.ToInt64(), false, - false, out long raw, - out failure)) + false, out long raw, + out failure)) { value = default; return false; @@ -96,9 +96,9 @@ public static bool TryReadInt8(Address address, out sbyte value, out MemoryAcces public static bool TryReadUInt16(Address address, out ushort value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadSmallInteger, "readSmallInteger"u8, address.ToInt64(), false, - true, - out long raw, - out failure)) + true, + out long raw, + out failure)) { value = default; return false; @@ -111,9 +111,9 @@ public static bool TryReadUInt16(Address address, out ushort value, out MemoryAc public static bool TryReadInt16(Address address, out short value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadSmallInteger, "readSmallInteger"u8, address.ToInt64(), true, - true, - out long raw, - out failure)) + true, + out long raw, + out failure)) { value = default; return false; @@ -126,8 +126,8 @@ public static bool TryReadInt16(Address address, out short value, out MemoryAcce public static bool TryReadUInt32(Address address, out uint value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadInteger, "readInteger"u8, address.ToInt64(), false, - true, out long raw, - out failure)) + true, out long raw, + out failure)) { value = default; return false; @@ -140,8 +140,8 @@ public static bool TryReadUInt32(Address address, out uint value, out MemoryAcce public static bool TryReadInt32(Address address, out int value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadInteger, "readInteger"u8, address.ToInt64(), true, - true, out long raw, - out failure)) + true, out long raw, + out failure)) { value = default; return false; @@ -154,8 +154,8 @@ public static bool TryReadInt32(Address address, out int value, out MemoryAccess public static bool TryReadUInt64(Address address, out ulong value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadQword, "readQword"u8, address.ToInt64(), false, - false, out long raw, - out failure)) + false, out long raw, + out failure)) { value = default; return false; @@ -176,8 +176,8 @@ public static bool TryReadInt64(Address address, out long value, out MemoryAcces public static bool TryReadPointer(Address address, out Address value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadPointer, "readPointer"u8, address.ToInt64(), false, - false, out long raw, - out failure)) + false, out long raw, + out failure)) { value = default; return false; diff --git a/libs/CheatEngine.SDK.Engine/Objects/EngineResourceOrigin.cs b/libs/CheatEngine.SDK.Engine/Objects/EngineResourceOrigin.cs index d5956eb0..1f91d5bf 100644 --- a/libs/CheatEngine.SDK.Engine/Objects/EngineResourceOrigin.cs +++ b/libs/CheatEngine.SDK.Engine/Objects/EngineResourceOrigin.cs @@ -64,7 +64,7 @@ public TargetProcessIncarnation? Target /// origin is never current. /// public bool IsCurrentRuntime => Runtime.AttachEpoch != 0 && LuaRuntime.IsAttached && - Runtime == LuaRuntime.CurrentStateIdentity; + Runtime == LuaRuntime.CurrentStateIdentity; /// Captures the current runtime identity, without a target component. internal static EngineResourceOrigin CaptureRuntime() diff --git a/libs/CheatEngine.SDK.Engine/Objects/Owned.cs b/libs/CheatEngine.SDK.Engine/Objects/Owned.cs index e0719fec..10458e32 100644 --- a/libs/CheatEngine.SDK.Engine/Objects/Owned.cs +++ b/libs/CheatEngine.SDK.Engine/Objects/Owned.cs @@ -57,7 +57,8 @@ namespace CheatEngine.SDK.Engine.Objects; /// Failure modes. When the destroy call raises (the object is already gone, for example destroyed by its /// parent, or its class refuses), the wrapper is still marked empty: a destroy is never retried, because the /// object may be half freed. returns that status with the message on the stack; -/// intentionally discards it after an invocation began, and +/// intentionally discards it after an invocation began, and +/// /// records it as unconfirmed. By contrast, a detached runtime, a missing pusher, or a state that is unavailable on /// the calling thread prevents an invocation from beginning. Those cases make and /// throw and retain this owner, so the plugin can retry before disable finishes or @@ -76,7 +77,6 @@ namespace CheatEngine.SDK.Engine.Objects; public sealed class Owned : IDisposable where T : struct, ICEObject { - private TargetReleaseOutcome _lastReleaseOutcome; private T _value; /// @@ -156,7 +156,11 @@ public EngineResourceOrigin Origin /// when could not begin a call. /// while the owner is live, and after a transfer or an abandonment. /// - public TargetReleaseOutcome LastReleaseOutcome => _lastReleaseOutcome; + public TargetReleaseOutcome LastReleaseOutcome + { + get; + private set; + } /// /// Destroys the object through on the ambient state, discarding a protected Lua @@ -206,7 +210,7 @@ public TargetReleaseOutcome ReleaseWithOutcome() { if (IsDisposed) { - return _lastReleaseOutcome; + return LastReleaseOutcome; } if (!IsOriginCurrent()) @@ -374,16 +378,16 @@ private bool IsOriginCurrent() private TargetReleaseOutcome Consume(LuaStatus destroyStatus) { _value = default; - _lastReleaseOutcome = destroyStatus.IsOk + LastReleaseOutcome = destroyStatus.IsOk ? TargetReleaseOutcome.Released() : TargetReleaseOutcome.Unconfirmed(EngineFailureKind.ProtectedLuaFailure); - return _lastReleaseOutcome; + return LastReleaseOutcome; } private TargetReleaseOutcome ConsumeWithoutDestroy(TargetReleaseOutcome outcome) { _value = default; - _lastReleaseOutcome = outcome; + LastReleaseOutcome = outcome; return outcome; } diff --git a/libs/CheatEngine.SDK.Engine/Objects/StringLists.cs b/libs/CheatEngine.SDK.Engine/Objects/StringLists.cs index 13a2823a..1ea7939a 100644 --- a/libs/CheatEngine.SDK.Engine/Objects/StringLists.cs +++ b/libs/CheatEngine.SDK.Engine/Objects/StringLists.cs @@ -31,8 +31,8 @@ public static bool TryCreate([NotNullWhen(true)] out Owned? list) LuaState state = operation.State; using LuaFrame frame = new(state); if (!LuaGlobalFunctions.TryPush(state, SCreateStringList, "createStringlist"u8) || - !state.TryCall(0, 1).IsOk || - !CEObject.TryRead(state, -1, out CEObject handle)) + !state.TryCall(0, 1).IsOk || + !CEObject.TryRead(state, -1, out CEObject handle)) { list = null; return false; diff --git a/libs/CheatEngine.SDK.Engine/Processes/RuntimeHostOperations.cs b/libs/CheatEngine.SDK.Engine/Processes/RuntimeHostOperations.cs index 8af5ab5f..c5fa140f 100644 --- a/libs/CheatEngine.SDK.Engine/Processes/RuntimeHostOperations.cs +++ b/libs/CheatEngine.SDK.Engine/Processes/RuntimeHostOperations.cs @@ -157,7 +157,8 @@ public static LuaOperationStatus TryGetTargetAbi(out TargetAbi abi) /// /// The plugin is not enabled or the calling thread has no Lua state. /// - /// getCheatEngineFileVersion may legitimately return no value; + /// getCheatEngineFileVersion may legitimately return no value; + /// /// is then , as for an absent global. Nothing is inferred between the fields. /// [RequiresPluginEnabled] @@ -360,7 +361,7 @@ private static LuaOperationStatus TryReadFileVersion(LuaState state, out CheatEn } if (!state.IsInteger(packedIndex) || !state.TryReadInteger(packedIndex, out long packed) || - !RuntimeInfo.TryDecodeFileVersion(packed, out CheatEngineVersion decoded)) + !RuntimeInfo.TryDecodeFileVersion(packed, out CheatEngineVersion decoded)) { return LuaOperationStatus.InvalidResult; } @@ -464,7 +465,7 @@ private static LuaOperationStatus TryGetCheatEngineVersion(LuaState state, out d } if (state.TypeOf(-1) != LuaType.Number || !state.TryReadNumber(-1, out version) || - !double.IsFinite(version) || version < 0) + !double.IsFinite(version) || version < 0) { version = default; return state.IsNil(-1) ? LuaOperationStatus.NilResult : LuaOperationStatus.InvalidResult; diff --git a/libs/CheatEngine.SDK.Engine/Processes/RuntimeObservations.cs b/libs/CheatEngine.SDK.Engine/Processes/RuntimeObservations.cs index c95641f7..345ecf99 100644 --- a/libs/CheatEngine.SDK.Engine/Processes/RuntimeObservations.cs +++ b/libs/CheatEngine.SDK.Engine/Processes/RuntimeObservations.cs @@ -38,10 +38,7 @@ public static class RuntimeObservations RuntimeOwnership.None, RuntimeReturnSemantics.Value); private static readonly RuntimeCapabilityContract SHostOptionalValue = - SHostValue with - { - ReturnSemantics = RuntimeReturnSemantics.OptionalValue - }; + SHostValue with { ReturnSemantics = RuntimeReturnSemantics.OptionalValue }; private static readonly RuntimeCapabilityContract STargetValue = new(CheatEngineVersion.Ce77010621, RuntimeArchitectureScope.Target, RuntimeArchitectureRequirement.Unknown, RuntimeThreadRequirement.Unknown, @@ -75,7 +72,8 @@ public static ProcessOperationStatus TryObserveRuntimeInfo(out RuntimeInfo? info try { LuaOperationStatus hostStatus = - RuntimeHostOperations.ObserveHost(state, out CheatEngineHostObservation host, out HostProbeFacts absent); + RuntimeHostOperations.ObserveHost(state, out CheatEngineHostObservation host, + out HostProbeFacts absent); if (!hostStatus.IsSuccess) { return FromHostStatus(hostStatus); @@ -150,7 +148,8 @@ private static RuntimeCapabilityAvailability Host(RuntimeCapabilityId capability // A capability is listed only when its globals were probed: unavailable when any of them is absent, available when // all of them resolved to a well-formed value. - private static void AddTarget(RuntimeCapabilityAvailability[] entries, ref int count, RuntimeCapabilityId capability, + private static void AddTarget(RuntimeCapabilityAvailability[] entries, ref int count, + RuntimeCapabilityId capability, TargetProbeFacts facts, in TargetProbeResult probe) { if ((probe.Absent & facts) != TargetProbeFacts.None) diff --git a/libs/CheatEngine.SDK.Engine/Processes/RuntimeProcessOperations.cs b/libs/CheatEngine.SDK.Engine/Processes/RuntimeProcessOperations.cs index f0e5cf2d..e839de47 100644 --- a/libs/CheatEngine.SDK.Engine/Processes/RuntimeProcessOperations.cs +++ b/libs/CheatEngine.SDK.Engine/Processes/RuntimeProcessOperations.cs @@ -83,7 +83,7 @@ public static ProcessOperationStatus SelectAndObserve(TargetProcessId processId, status = TryGetOpenedProcessId(state, out TargetProcessId? observedProcessId); if (status.Kind == ProcessOperationStatusKind.TargetNotAttached || - (status.IsSuccess && observedProcessId != processId)) + (status.IsSuccess && observedProcessId != processId)) { observation = default; return ProcessOperationStatus.SelectionNotConfirmed; diff --git a/libs/CheatEngine.SDK.Engine/Processes/TargetArchitectureProbe.cs b/libs/CheatEngine.SDK.Engine/Processes/TargetArchitectureProbe.cs index d09e0c8a..8d8a2b61 100644 --- a/libs/CheatEngine.SDK.Engine/Processes/TargetArchitectureProbe.cs +++ b/libs/CheatEngine.SDK.Engine/Processes/TargetArchitectureProbe.cs @@ -16,7 +16,8 @@ namespace CheatEngine.SDK.Engine.Processes; /// /// Every call runs inside the caller's LuaRuntimeOperation and restores the recorded stack top on every /// exit path. Each global is resolved through LuaGlobalFunctions.TryPushWithOutcome and a static -/// cache, so an absent global, a raising global (with its protected ) +/// cache, so an absent global, a raising global (with its protected +/// ) /// and a value of the wrong type stay three distinct outcomes. No error text is read. /// /// @@ -103,7 +104,10 @@ internal static TargetProbeResult Observe(LuaState state, TargetProbeFacts read, /// Reads and classifies getOpenedProcessID once, leaving the stack as it found it. /// The admitted Lua state of the caller's operation. - /// The positive identifier when the result is ; otherwise zero. + /// + /// The positive identifier when the result is ; otherwise + /// zero. + /// /// The protected status of a ; otherwise OK. /// /// , , @@ -148,7 +152,10 @@ internal static TargetProbeStatus ReadProcessId(LuaState state, out int processI /// Classifies a raw getOpenedProcessID integer. /// The Lua integer. - /// The positive identifier when the result is ; otherwise zero. + /// + /// The positive identifier when the result is ; otherwise + /// zero. + /// /// The selected, no-target, file-as-process or invalid category. internal static TargetProbeStatus ClassifyProcessId(long raw, out int processId) { @@ -255,7 +262,8 @@ private static TargetProbeStatus ReadFact(LuaState state, TargetProbeFacts read, { // CE pushes these with lua_pushinteger. A float, even an integral one, and a value outside int are // refused rather than rounded or truncated. - if (!state.IsInteger(-1) || !state.TryReadInteger(-1, out long raw) || raw is < int.MinValue or > int.MaxValue) + if (!state.IsInteger(-1) || !state.TryReadInteger(-1, out long raw) || + raw is < int.MinValue or > int.MaxValue) { return TargetProbeStatus.InvalidResult; } @@ -317,7 +325,7 @@ internal void RecordProcessIdRead(TargetProbeStatus status) Absent |= TargetProbeFacts.SelectedProcess; } else if (status is TargetProbeStatus.Success or TargetProbeStatus.NoTargetSelected - or TargetProbeStatus.FileAsProcess) + or TargetProbeStatus.FileAsProcess) { Resolved |= TargetProbeFacts.SelectedProcess; } diff --git a/libs/CheatEngine.SDK.Engine/README.md b/libs/CheatEngine.SDK.Engine/README.md index 837a5839..973c1a5a 100644 --- a/libs/CheatEngine.SDK.Engine/README.md +++ b/libs/CheatEngine.SDK.Engine/README.md @@ -17,38 +17,38 @@ Cheat Engine. This library encodes each rule once, in a type. ## How it works -| Namespace | Types | Role | -|--------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `CheatEngine.SDK.Engine.Objects` | `CEObject`, `ICEObject` | Borrowed handle: the native object pointer, equal by identity, with property, index and method access | -| `CheatEngine.SDK.Engine.Objects` | `Owned`, `EngineResourceOrigin`, `EngineEffectState` | Ownership of an object the plugin created; `Dispose` destroys it once, never in another Lua universe; origin and effect vocabulary shared by every durable resource | -| `CheatEngine.SDK.Engine.Values` | `Address` | An address read from a Lua integer or hexadecimal text; its own Lua marshaller | -| `CheatEngine.SDK.Engine.Values` | `IndexBase`, `LuaSequence` | Zero-based indices over Cheat Engine objects and Lua sequences | -| `CheatEngine.SDK.Engine.Enums` | Enums, `CEEnumNames`, `EnumMarshaller` | Numeric constants, their Cheat Engine names, and Lua integer marshalling | -| `CheatEngine.SDK.Engine.Runtime` | `RuntimeInfo` (SDK-produced or caller-supplied), `RuntimeCapabilities`, `CheatEngineHostObservation`, `TargetArchitectureObservation`, `CheatEngineOperatingSystem`, `TargetBackend` | Separate host, target ISA family, bitness, configured pointer size, ABI, OS, Android and backend facts; never inferred from one another | -| `CheatEngine.SDK.Engine.Memory` | `TargetMemory`, `HostMemory`, `HostAddress` | Separate target/CE-host scalar, bounded span, target-width pointer, string and byte-table access | -| `CheatEngine.SDK.Engine.Inspection` | `EngineInspection`, `SymbolRegistry`, `SymbolLists`, `SymbolList` | Copied modules, sections, symbols, address resolution and memory-region snapshots; symbol registration leases and plugin-owned symbol lists | -| `CheatEngine.SDK.Engine.Allocation` | `TargetMemoryAllocator`, `AllocatedRegion`, `TargetAllocationAcquireOutcome` | Explicit ownership for target allocation, via a reviewed binding seam; never a live address without an owner or a reported compensation | -| `CheatEngine.SDK.Engine.Assembly` | `AutoAssemblerPatcher`, `AutoAssemblerPatch`, `InstructionProfiles`, `InstructionAssembler`, `InstructionDisassembler`, `InstructionNavigator` | Auto Assembler owns a single `disableInfo`; separately, bounded profile-qualified Lua instruction operations return copied values and structured outcomes | -| `CheatEngine.SDK.Engine.Scanning` | `AobScanner`, `AobScanBounds`, `StringList`, `MemoryScanSession` | AOB result ownership, the bounded exhaustive AOB route, and conservative MemScan/FoundList state transitions | -| `CheatEngine.SDK.Engine.AddressList` | `AddressListMutations`, `MemoryRecordId`, `MemoryRecordActivationOutcome` | ID-addressed record commands, including activation with its real effect; borrowed GUI views never become managed owners | -| `CheatEngine.SDK.Engine.Errors` | `EngineException` hierarchy, `EngineResourceHandoffException` | Stable distinction between expected CE, unavailable global, Lua, binding and marshalling failures; post-effect ownership publication reports its one cleanup attempt | -| `CheatEngine.SDK.Engine.Generated` | `MemoryScalars`, `RuntimeCapabilityProbes` | Generated wrappers: the earlier scalar memory contract, and raw read-only CE 7.7 runtime facts (ce77 spec) | +| Namespace | Types | Role | +|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `CheatEngine.SDK.Engine.Objects` | `CEObject`, `ICEObject` | Borrowed handle: the native object pointer, equal by identity, with property, index and method access | +| `CheatEngine.SDK.Engine.Objects` | `Owned`, `EngineResourceOrigin`, `EngineEffectState` | Ownership of an object the plugin created; `Dispose` destroys it once, never in another Lua universe; origin and effect vocabulary shared by every durable resource | +| `CheatEngine.SDK.Engine.Values` | `Address` | An address read from a Lua integer or hexadecimal text; its own Lua marshaller | +| `CheatEngine.SDK.Engine.Values` | `IndexBase`, `LuaSequence` | Zero-based indices over Cheat Engine objects and Lua sequences | +| `CheatEngine.SDK.Engine.Enums` | Enums, `CEEnumNames`, `EnumMarshaller` | Numeric constants, their Cheat Engine names, and Lua integer marshalling | +| `CheatEngine.SDK.Engine.Runtime` | `RuntimeInfo` (SDK-produced or caller-supplied), `RuntimeCapabilities`, `CheatEngineHostObservation`, `TargetArchitectureObservation`, `CheatEngineOperatingSystem`, `TargetBackend` | Separate host, target ISA family, bitness, configured pointer size, ABI, OS, Android and backend facts; never inferred from one another | +| `CheatEngine.SDK.Engine.Memory` | `TargetMemory`, `HostMemory`, `HostAddress` | Separate target/CE-host scalar, bounded span, target-width pointer, string and byte-table access | +| `CheatEngine.SDK.Engine.Inspection` | `EngineInspection`, `SymbolRegistry`, `SymbolLists`, `SymbolList` | Copied modules, sections, symbols, address resolution and memory-region snapshots; symbol registration leases and plugin-owned symbol lists | +| `CheatEngine.SDK.Engine.Allocation` | `TargetMemoryAllocator`, `AllocatedRegion`, `TargetAllocationAcquireOutcome` | Explicit ownership for target allocation, via a reviewed binding seam; never a live address without an owner or a reported compensation | +| `CheatEngine.SDK.Engine.Assembly` | `AutoAssemblerPatcher`, `AutoAssemblerPatch`, `InstructionProfiles`, `InstructionAssembler`, `InstructionDisassembler`, `InstructionNavigator` | Auto Assembler owns a single `disableInfo`; separately, bounded profile-qualified Lua instruction operations return copied values and structured outcomes | +| `CheatEngine.SDK.Engine.Scanning` | `AobScanner`, `AobScanBounds`, `StringList`, `MemoryScanSession` | AOB result ownership, the bounded exhaustive AOB route, and conservative MemScan/FoundList state transitions | +| `CheatEngine.SDK.Engine.AddressList` | `AddressListMutations`, `MemoryRecordId`, `MemoryRecordActivationOutcome` | ID-addressed record commands, including activation with its real effect; borrowed GUI views never become managed owners | +| `CheatEngine.SDK.Engine.Errors` | `EngineException` hierarchy, `EngineResourceHandoffException` | Stable distinction between expected CE, unavailable global, Lua, binding and marshalling failures; post-effect ownership publication reports its one cleanup attempt | +| `CheatEngine.SDK.Engine.Generated` | `MemoryScalars`, `RuntimeCapabilityProbes` | Generated wrappers: the earlier scalar memory contract, and raw read-only CE 7.7 runtime facts (ce77 spec) | The CE 7.7 vertical slices add the following public domains. They use the same protected Lua boundary, but their evidence and availability are intentionally separate: a catalogued Lua name is not a guarantee that every later CE host has the same contract. -| Namespace | Public surface | Boundary and result contract | -|----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `Runtime` | `RuntimeInfo`, `RuntimeCapabilities`, `RuntimeCapabilityContract`, `CheatEngineHostObservation`, `TargetArchitectureObservation`, `TargetBackend`; produced by `Processes.RuntimeObservations` | An immutable snapshot of explicitly observed version, architecture, configured pointer size, backend and availability facts. Unknown remains unknown; an available global does not fill an unobserved ownership, thread or return field, and no fact is derived from another (see [Runtime facts and target backends](#runtime-facts-and-target-backends)). | -| `Memory` | `TargetMemory`, `HostMemory`, `Address`, `HostAddress`, `PointerSize`, `MemoryAccessFailure` | Keeps attached-target addresses distinct from CE-host addresses. Target-width pointer, scalar, bounded-span, and string calls report expected CE/binding/Lua/result failures through `Try*` results; they do not claim a universal GUI-thread rule. | -| `Inspection` | `EngineInspection` and module, section, symbol and region value types | Returns copied managed snapshots. `NotFound` is used only where the CE 7.7 Lua contract documents `nil`; malformed data and Lua failures remain distinct status values. | -| `Allocation` | `TargetMemoryAllocator`, `AllocatedRegion`, `TargetAllocationAcquireOutcome` | Models one target allocation as an explicit, single-use owner bound to its Lua runtime identity and target incarnation. It does not infer a GUI-thread requirement from an unspecific CE global, and reports a failed post-effect owner handoff with its one compensation outcome. | -| `Objects` / `Scanning.Aob` | `StringList`, `StringLists`, `AobScanner`, `AobScanBounds`, `AobBoundedScanResult` | `StringLists.TryCreate` and a successful `AobScanner.TryScan` out value yield `Owned` only after a host object is returned; a failed owner publication destroys the raw list once. `TryScanWithinBounds` is the bounded, exhaustive AOB route. A list borrowed from CE must never be wrapped or destroyed by plugin code. | -| `Scanning.Values` | `MemScan`, `FoundList`, `MemoryScanSessions`, `MemoryScanSession`, scan requests and states | The factory creates and owns the scanner/child pair, retains rollback authority through publication, and the session serializes documented state transitions, stops a running scan cooperatively on release, and releases the child before the parent. It is explicitly main-thread-only; the generic `Owned` wrapper is not. | -| `AddressList` | `AddressListAccess`, `AddressList`, `MemoryRecord`, `MemoryRecordId`, `AddressListMutations` | The current GUI list and records are borrowed CE-owned handles. Mutations resolve IDs inside one protected command and report completed, not-started, or indeterminate effect (activation: before/after state, host refusal, pending); they do not promise historic record identity. | +| Namespace | Public surface | Boundary and result contract | +|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Runtime` | `RuntimeInfo`, `RuntimeCapabilities`, `RuntimeCapabilityContract`, `CheatEngineHostObservation`, `TargetArchitectureObservation`, `TargetBackend`; produced by `Processes.RuntimeObservations` | An immutable snapshot of explicitly observed version, architecture, configured pointer size, backend and availability facts. Unknown remains unknown; an available global does not fill an unobserved ownership, thread or return field, and no fact is derived from another (see [Runtime facts and target backends](#runtime-facts-and-target-backends)). | +| `Memory` | `TargetMemory`, `HostMemory`, `Address`, `HostAddress`, `PointerSize`, `MemoryAccessFailure` | Keeps attached-target addresses distinct from CE-host addresses. Target-width pointer, scalar, bounded-span, and string calls report expected CE/binding/Lua/result failures through `Try*` results; they do not claim a universal GUI-thread rule. | +| `Inspection` | `EngineInspection` and module, section, symbol and region value types | Returns copied managed snapshots. `NotFound` is used only where the CE 7.7 Lua contract documents `nil`; malformed data and Lua failures remain distinct status values. | +| `Allocation` | `TargetMemoryAllocator`, `AllocatedRegion`, `TargetAllocationAcquireOutcome` | Models one target allocation as an explicit, single-use owner bound to its Lua runtime identity and target incarnation. It does not infer a GUI-thread requirement from an unspecific CE global, and reports a failed post-effect owner handoff with its one compensation outcome. | +| `Objects` / `Scanning.Aob` | `StringList`, `StringLists`, `AobScanner`, `AobScanBounds`, `AobBoundedScanResult` | `StringLists.TryCreate` and a successful `AobScanner.TryScan` out value yield `Owned` only after a host object is returned; a failed owner publication destroys the raw list once. `TryScanWithinBounds` is the bounded, exhaustive AOB route. A list borrowed from CE must never be wrapped or destroyed by plugin code. | +| `Scanning.Values` | `MemScan`, `FoundList`, `MemoryScanSessions`, `MemoryScanSession`, scan requests and states | The factory creates and owns the scanner/child pair, retains rollback authority through publication, and the session serializes documented state transitions, stops a running scan cooperatively on release, and releases the child before the parent. It is explicitly main-thread-only; the generic `Owned` wrapper is not. | +| `AddressList` | `AddressListAccess`, `AddressList`, `MemoryRecord`, `MemoryRecordId`, `AddressListMutations` | The current GUI list and records are borrowed CE-owned handles. Mutations resolve IDs inside one protected command and report completed, not-started, or indeterminate effect (activation: before/after state, host refusal, pending); they do not promise historic record identity. | | `Assembly` | `InstructionTargetProfile`, `InstructionAssembler`, `InstructionAssembly`, `AssemblePreference`, `InstructionDisassembler`, `InstructionNavigator`, `InstructionDisassembly`, `InstructionOperationStatus` | `InstructionProfiles` observes PID/probe/PID under one Lua admission and maps CE's x86 family plus 64-bit flag to x64. Each instruction call validates target width and rechecks that PID before and after CE's ambient operation; its result is copied and bounded, and the detailed assembler overload echoes the origin, jump preference and range-check option it sent. That coherence check is not a target lock or a live-host qualification. | -| `Errors` | `EngineException` and stable subclasses | Separates expected operation failure, global absence, Lua failure, binding violation and marshalling violation instead of exposing a raw Lua stack error as the public Engine contract. | +| `Errors` | `EngineException` and stable subclasses | Separates expected operation failure, global absence, Lua failure, binding violation and marshalling violation instead of exposing a raw Lua stack error as the public Engine contract. | The per-capability provenance, minimum CE version, architecture, thread, ownership and return semantics are tracked against the audit's Lua surface register; executed host evidence is a separate, qualified claim. Fixture tests @@ -107,8 +107,9 @@ Engine or attaches another process. `RuntimeInfo` is an immutable snapshot, produced by `RuntimeObservations.TryObserveRuntimeInfo` or supplied by an integration layer through its legacy constructor. The SDK-produced snapshot carries a `CheatEngineHostObservation` and, -when a target is selected, a `TargetArchitectureObservation`; its `PointerSize` is Cheat Engine's configured pointer size -(`getPointerSize`), not the target bitness. It deliberately does not turn a legacy floating-point `getCEVersion` result +when a target is selected, a `TargetArchitectureObservation`; its `PointerSize` is Cheat Engine's configured pointer +size (`getPointerSize`), not the target bitness. It deliberately does not turn a legacy floating-point `getCEVersion` +result into a complete file version (it reads `getCheatEngineFileVersion` instead) and does not infer target architecture, pointer width, ABI, ownership, return semantics or thread affinity. `RuntimeCapabilities` records each probed capability as available or unavailable with the evidence fields that are actually known; a capability that was not probed stays @@ -144,7 +145,8 @@ effect, so an external selection transition in that interval, including an unsee `InstructionProfiles.TryObserveCurrent` has a narrower purpose than process qualification: it reads CE's selected PID, the documented target ISA probes, and the PID again to construct an `InstructionTargetProfile`. On Cheat Engine an x64 target is the x86 family plus the 64-bit flag (`targetIsX86() == true` and `targetIs64Bit() == true`), so the profile -follows `RuntimeInfo.TryDeriveTargetArchitecture` (see [Runtime facts and target backends](#runtime-facts-and-target-backends)): +follows `RuntimeInfo.TryDeriveTargetArchitecture` +(see [Runtime facts and target backends](#runtime-facts-and-target-backends)): x86 family gives X64 or X86, ARM family gives Arm64 or Arm32, and both families or neither is `InvalidProfile`. It never uses the managed host width or CE's configured pointer size. With no target selected CE reports x64-like facts, so a zero PID is `TargetNotSelected` before any probe; the file-as-process sentinel PID is `UnsupportedTargetBackend`. @@ -160,7 +162,8 @@ then returns managed strings; consumers never need to parse that UI text. `Instr CE's documented estimate semantics. These mappings use protected Lua globals only. The historical classic `Assembler`, `Disassembler`, `disassembleEx`, `previousOpcode`, and `nextOpcode` slots remain unprojected because their reviewed ABI and output-capacity evidence is conflicting or -insufficient; their buffer-based forms are not applicable to the managed-hostfxr profile (audit A15-19). Fixture tests verify these managed contracts; no test in this repository qualifies a live CE target, +insufficient; their buffer-based forms are not applicable to the managed-hostfxr profile (audit A15-19). Fixture tests +verify these managed contracts; no test in this repository qualifies a live CE target, target architecture, selection lock, relocation backend, or plugin Native AOT loading. `TargetMemoryAllocator` uses the production `allocateMemory`/`deAlloc` binding by default and retains @@ -179,7 +182,8 @@ allocated but no owner can be published (an unqualified target, a Lua runtime id failed owner publication), it makes exactly one target-qualified compensation and reports it as `Compensation`, so an applied allocation never leaves without an owner or a compensation result. -An allocation is bound to the runtime identity and target incarnation that created it (`AllocatedRegion.Origin`). After a +An allocation is bound to the runtime identity and target incarnation that created it (`AllocatedRegion.Origin`). After +a re-enable or a controlled state replacement the region refuses cleanup without any call (`RefusedRuntimeChanged`) and reports the residue; after a detach, cleanup cannot begin (`NotInvoked`). It never reopens or reselects a target. `Dispose` and `ReleaseWithTargetOutcome` never throw once ownership is taken; `Release` and `ReleaseWithOutcome` throw a @@ -194,7 +198,8 @@ cleanup that could not begin, and an effect requiring manual recovery. malformed-result and successful-list outcomes; `TryScan` keeps its compatible `bool` projection and supplies a caller-owned `Owned` through its `out` parameter. A valid empty list is still a successful caller-owned result, not a match classification. `AobScanner.TryScanOutcome` adds the factual distinction that a valid `StringList` -with a verified zero count is `NoMatches`; raw `nil` remains a distinct result, never a no-match inference. On the pinned +with a verified zero count is `NoMatches`; raw `nil` remains a distinct result, never a no-match inference. On the +pinned profile `ce-7.7.0.10621-x64-managed-hostfxr`, zero matches are reported this way: `AOBScan` returns no value, which the SDK reports as `NoResult`, and an empty list was never observed (host observation, spike 2026-09-22; the Q27 C3 receipt is still pending). `NoMatches` on this global route stays reserved for a valid empty list and is unreachable on that @@ -215,14 +220,16 @@ reports a factual `NoMatches` when no row lies in the bounds and CE reported no route returned exactly the in-module subset of the global route (Lua-only host observation, spike D4; the Q28 C3 receipt is still pending). A deadline overload and the session's `TryWaitForCompletion`/`TryTerminateScan` are `[Experimental("CESDK5010")]` because CE's timed-out wait and `terminateScan` were not observed on the pinned host; the -separately named first-found opt-in, `TryFindFirstFoundWithinBounds`, is `[Experimental("CESDK5011")]` because its result +separately named first-found opt-in, `TryFindFirstFoundWithinBounds`, is `[Experimental("CESDK5011")]` because its +result is "first found, order unspecified", never a uniqueness proof. See [Scan limits and cost](#scan-limits-and-cost). `MemScan` and `FoundList` are borrowed handle values, while `MemoryScanSessions.TryCreate` is the SDK's source-backed CE 7.7 creation path: it immediately owns the returned parent and child, holds one Lua operation across both calls, retains raw handles until their owner is published, rolls the child back before its parent on every later failure, and transfers the pair only to `MemoryScanSession`; an ordinary consumer cannot create an `Owned` or `Owned` -manually. Releasing a session whose scan may still run first requests one cooperative stop (`terminateScan(false)`, then a +manually. Releasing a session whose scan may still run first requests one cooperative stop (`terminateScan(false)`, then +a five-second bounded wait), then destroys the child and the parent once each even when the stop is not confirmed, which can block CE's main thread; `MemoryScanReleaseOutcome.Termination` reports the stop. CE's waits can run queued main-thread work (`waitTillDone` pumps `CheckSynchronize`) that calls back into the session: while one session member is @@ -367,19 +374,19 @@ difference as `TargetChanged`; instruction operations re-check it before and aft `TargetSelection.ObserveCurrent` and `RuntimeProcessOperations.ObserveCurrent` read it once, before their other probes, and `RuntimeProcessOperations.SelectAndObserve` reads it once, after `openProcess`, to confirm the selection. -| Fact | CE global | SDK member | When unknown | -|--------------------------------------|-----------------------------|------------------------------------------------------------------------------------------------------|-----------------------------------------------| -| CE file version | `getCheatEngineFileVersion` | `RuntimeHostOperations.TryGetCheatEngineFileVersion`, `CheatEngineHostObservation.FileVersion` | absent global or no value returned | -| CE host architecture | `getSystemArchitecture` | `RuntimeHostOperations.TryGetSystemArchitecture`, `CheatEngineHostObservation.SystemArchitecture` | absent global | -| CE is 64-bit | `cheatEngineIs64Bit` | `RuntimeHostOperations.TryIsCheatEngine64Bit`, `CheatEngineHostObservation.CheatEngineIs64Bit` | absent global; never taken from the host arch | -| CE operating system | `getOperatingSystem` | `RuntimeHostOperations.TryGetOperatingSystem`, `CheatEngineHostObservation.OperatingSystem` | absent global | -| Selected process | `getOpenedProcessID` | `TargetArchitectureObservation.ProcessId` | 0: no target, no fact is read | -| Target backend | `isConnectedToCEServer` | `TargetArchitectureObservation.Backend`, `TargetSelectionObservation.Backend` | absent global: `Unknown` | -| Target bitness (CE's 64-bit flag) | `targetIs64Bit` | `TargetArchitectureObservation.Bitness`, `CurrentProcessObservation.PointerSize` | required by the target observation | -| Target ISA family | `targetIsX86`, `targetIsArm` | `TargetArchitectureObservation.IsX86Family`, `.IsArmFamily`, `.Architecture` | absent global: `null`, architecture `Unknown` | -| Android target | `targetIsAndroid` | `TargetArchitectureObservation.IsAndroid` | absent global: `null` | -| Target ABI | `getABI` | `TargetArchitectureObservation.AbiCode`, `.Abi` | absent global, or an undocumented code (kept raw) | -| CE's configured pointer size | `getPointerSize` | `RuntimeProcessOperations.TryGetConfiguredPointerSize`, `TargetArchitectureObservation.ConfiguredPointerSize`, `RuntimeInfo.PointerSize` | absent global, or any value other than 4 or 8 (kept raw) | +| Fact | CE global | SDK member | When unknown | +|-----------------------------------|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------| +| CE file version | `getCheatEngineFileVersion` | `RuntimeHostOperations.TryGetCheatEngineFileVersion`, `CheatEngineHostObservation.FileVersion` | absent global or no value returned | +| CE host architecture | `getSystemArchitecture` | `RuntimeHostOperations.TryGetSystemArchitecture`, `CheatEngineHostObservation.SystemArchitecture` | absent global | +| CE is 64-bit | `cheatEngineIs64Bit` | `RuntimeHostOperations.TryIsCheatEngine64Bit`, `CheatEngineHostObservation.CheatEngineIs64Bit` | absent global; never taken from the host arch | +| CE operating system | `getOperatingSystem` | `RuntimeHostOperations.TryGetOperatingSystem`, `CheatEngineHostObservation.OperatingSystem` | absent global | +| Selected process | `getOpenedProcessID` | `TargetArchitectureObservation.ProcessId` | 0: no target, no fact is read | +| Target backend | `isConnectedToCEServer` | `TargetArchitectureObservation.Backend`, `TargetSelectionObservation.Backend` | absent global: `Unknown` | +| Target bitness (CE's 64-bit flag) | `targetIs64Bit` | `TargetArchitectureObservation.Bitness`, `CurrentProcessObservation.PointerSize` | required by the target observation | +| Target ISA family | `targetIsX86`, `targetIsArm` | `TargetArchitectureObservation.IsX86Family`, `.IsArmFamily`, `.Architecture` | absent global: `null`, architecture `Unknown` | +| Android target | `targetIsAndroid` | `TargetArchitectureObservation.IsAndroid` | absent global: `null` | +| Target ABI | `getABI` | `TargetArchitectureObservation.AbiCode`, `.Abi` | absent global, or an undocumented code (kept raw) | +| CE's configured pointer size | `getPointerSize` | `RuntimeProcessOperations.TryGetConfiguredPointerSize`, `TargetArchitectureObservation.ConfiguredPointerSize`, `RuntimeInfo.PointerSize` | absent global, or any value other than 4 or 8 (kept raw) | `RuntimeObservations.TryObserveRuntimeInfo` reads all of them in one admission and produces a `RuntimeInfo`; `RuntimeCapabilityProbes` (generated from the `ce77` runtime spec) exposes the raw values for callers that need them. @@ -409,20 +416,22 @@ is why the process identifier comes first. The configured pointer size is not the bitness. On the same host, `setPointerSize(4)` on an x64 target made `getPointerSize()` return 4 while `targetIs64Bit()` stayed true and `readPointer` kept reading 8 bytes; -`setPointerSize(2)` was accepted, and selecting the target again reset the value (spike C3 D3). The SDK therefore reports +`setPointerSize(2)` was accepted, and selecting the target again reset the value (spike C3 D3). The SDK therefore +reports both, keeps any raw configured value, never calls `setPointerSize`, and never takes a target width from `IntPtr.Size`. `PointerSize.FromArchitecture` is obsolete ([CESDK7001](../../analyzers/docs/CESDK7001.md)). The little-endian pointer -encoding of `PointerSize.TryReadLittleEndian`/`TryWriteLittleEndian` is an assumption of the local x86/x64 profile, not a +encoding of `PointerSize.TryReadLittleEndian`/`TryWriteLittleEndian` is an assumption of the local x86/x64 profile, not +a general Cheat Engine fact (audit A12-04). Target backends produce different evidence and are separate profiles (audit A12-03, ADR-11): -| Backend | How the SDK recognises it | Incarnation evidence | Qualified backend | -|-----------------|----------------------------------------------------------------------------------|-----------------------|-------------------------------------------------------| -| `LocalProcess` | `isConnectedToCEServer() == false` and a PID in (0, `int.MaxValue`] | PID + local StartTime | yes, profile `ce-7.7.0.10621-x64-managed-hostfxr` | -| `FileAsProcess` | sentinel PID 4294967295 (CE source `ec45d5f`, ObservedSource; ToQualify on 7.7) | none | no | -| `CEServer` | `isConnectedToCEServer() == true` | none | no | -| `Unknown` | `isConnectedToCEServer` absent | none | no | +| Backend | How the SDK recognises it | Incarnation evidence | Qualified backend | +|-----------------|---------------------------------------------------------------------------------|-----------------------|---------------------------------------------------| +| `LocalProcess` | `isConnectedToCEServer() == false` and a PID in (0, `int.MaxValue`] | PID + local StartTime | yes, profile `ce-7.7.0.10621-x64-managed-hostfxr` | +| `FileAsProcess` | sentinel PID 4294967295 (CE source `ec45d5f`, ObservedSource; ToQualify on 7.7) | none | no | +| `CEServer` | `isConnectedToCEServer() == true` | none | no | +| `Unknown` | `isConnectedToCEServer` absent | none | no | A file opened as a process has no operating-system process: the SDK refuses it and never searches for a Windows process (A12-07). A local BCL PID and creation time do not describe a PID served remotely by CEServer (A12-05). Cheat Engine's @@ -442,16 +451,16 @@ and never owns destroy itself. Only sourced SDK factories create owners, a gette no finalizer ever repairs a forgotten cleanup. Effects use one vocabulary, `EngineEffectState` (`Unknown = 0`, `NotStarted`, `NotApplied`, `Applied`). -| Resource | Origin captured | Release action | External-destruction risk | On target change | On Lua state change / re-enable | On detach | Retry policy | -|----------|-----------------|----------------|---------------------------|------------------|---------------------------------|-----------|--------------| -| `Owned` (StringList, SymbolList, MemScan/FoundList inside a session) | Runtime identity, inside the creating factory's admitted operation; a transfer keeps it | One `destroy()` (`Dispose`, `TryDestroy`, `ReleaseWithOutcome`) | A parent or CE destroys the object first: the destroy raises, `UnconfirmedAfterInvocation` | Not target-bound | Consumed without a call, `RefusedRuntimeChanged` (residue) | `Dispose`/`TryDestroy` throw and retain; `ReleaseWithOutcome` consumes, `NotInvoked` | Never after a destroy began | -| `AllocatedRegion` | Runtime identity and qualified incarnation, around the allocating call | One target-validated `deAlloc` | The target exits or its PID is reused: refused; a later allocation at the same address is never freed through this owner | Refused (`RefusedTargetChanged`, `RefusedProcessReused`, `RefusedNoTarget`), residue reported, never reselects | Refused without a call, `RefusedRuntimeChanged` | `NotInvoked` | Never | -| `AutoAssemblerPatch` | Runtime identity and incarnation, validated again right after the effect | One `autoAssemble(script, disableInfo)` with the rooted table | A script or table disables it, or the target exits: the disable fails, manual recovery | Refused, token kept until consumed; a change during the effect is `AppliedTargetChanged` | Refused without a call, `RefusedRuntimeChanged`; the reference is dropped without touching the new state | `NotInvoked` | Never | -| `SymbolRegistrationLease` | Runtime identity and the registered address | Name lookup, then one `unregisterSymbol(name)` only if the name still maps to the address | A third party replaces or removes the name: `Replaced` / `ExternallyRemoved`, no unregister | Not target-bound (a lookup in another target reads as a conservative `Replaced`/`ExternallyRemoved`) | `StaleRuntime`, no call | `StaleRuntime`, no call | Only `CleanupUnavailable` (no call began) | -| `SymbolListRegistrationLease` | The list owner's runtime identity | `unregister()`, then the list's one `destroy()` | CE destroys the list: `unregister()` raises, `CleanupIndeterminate`, abandoned without destroy | Not target-bound | `StaleRuntime`, list abandoned without a call | `StaleRuntime`, list abandoned without a call | Only when `unregister` is unavailable | -| `MemoryScanSession` (S-SCAN, Wave 2) | `RuntimeIdentity` and target observation (an `Origin` property is added by S-SCAN) | FoundList `deinitialize`/`destroy`, then MemScan `destroy` | CE or a parent destroys a child: unconfirmed | Refused without cleanup | Consumed without cleanup | Consumed without cleanup | Never | -| `MemoryRecord` (address list) | None: a borrowed CE-owned record | None by the plugin; `AddressListMutations` commands resolve the record by identifier in each command | A table reload, a parent delete or CE removes it: `RecordNotFound` | Not target-bound | Commands resolve again; an identifier is never a historic identity | Commands throw (lifecycle) | Never; a second delete reports `RecordNotFound` | -| Timers, hotkeys, lookup callbacks | Placeholder: S-EVT, Wave 3 | | | | | | | +| Resource | Origin captured | Release action | External-destruction risk | On target change | On Lua state change / re-enable | On detach | Retry policy | +|-------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------|-------------------------------------------------| +| `Owned` (StringList, SymbolList, MemScan/FoundList inside a session) | Runtime identity, inside the creating factory's admitted operation; a transfer keeps it | One `destroy()` (`Dispose`, `TryDestroy`, `ReleaseWithOutcome`) | A parent or CE destroys the object first: the destroy raises, `UnconfirmedAfterInvocation` | Not target-bound | Consumed without a call, `RefusedRuntimeChanged` (residue) | `Dispose`/`TryDestroy` throw and retain; `ReleaseWithOutcome` consumes, `NotInvoked` | Never after a destroy began | +| `AllocatedRegion` | Runtime identity and qualified incarnation, around the allocating call | One target-validated `deAlloc` | The target exits or its PID is reused: refused; a later allocation at the same address is never freed through this owner | Refused (`RefusedTargetChanged`, `RefusedProcessReused`, `RefusedNoTarget`), residue reported, never reselects | Refused without a call, `RefusedRuntimeChanged` | `NotInvoked` | Never | +| `AutoAssemblerPatch` | Runtime identity and incarnation, validated again right after the effect | One `autoAssemble(script, disableInfo)` with the rooted table | A script or table disables it, or the target exits: the disable fails, manual recovery | Refused, token kept until consumed; a change during the effect is `AppliedTargetChanged` | Refused without a call, `RefusedRuntimeChanged`; the reference is dropped without touching the new state | `NotInvoked` | Never | +| `SymbolRegistrationLease` | Runtime identity and the registered address | Name lookup, then one `unregisterSymbol(name)` only if the name still maps to the address | A third party replaces or removes the name: `Replaced` / `ExternallyRemoved`, no unregister | Not target-bound (a lookup in another target reads as a conservative `Replaced`/`ExternallyRemoved`) | `StaleRuntime`, no call | `StaleRuntime`, no call | Only `CleanupUnavailable` (no call began) | +| `SymbolListRegistrationLease` | The list owner's runtime identity | `unregister()`, then the list's one `destroy()` | CE destroys the list: `unregister()` raises, `CleanupIndeterminate`, abandoned without destroy | Not target-bound | `StaleRuntime`, list abandoned without a call | `StaleRuntime`, list abandoned without a call | Only when `unregister` is unavailable | +| `MemoryScanSession` (S-SCAN, Wave 2) | `RuntimeIdentity` and target observation (an `Origin` property is added by S-SCAN) | FoundList `deinitialize`/`destroy`, then MemScan `destroy` | CE or a parent destroys a child: unconfirmed | Refused without cleanup | Consumed without cleanup | Consumed without cleanup | Never | +| `MemoryRecord` (address list) | None: a borrowed CE-owned record | None by the plugin; `AddressListMutations` commands resolve the record by identifier in each command | A table reload, a parent delete or CE removes it: `RecordNotFound` | Not target-bound | Commands resolve again; an identifier is never a historic identity | Commands throw (lifecycle) | Never; a second delete reports `RecordNotFound` | +| Timers, hotkeys, lookup callbacks | Placeholder: S-EVT, Wave 3 | | | | | | | An external `resetLuaState` that bypasses the SDK's controlled replacement is not detected today: the state generation does not advance, so this policy does not trigger; detection is a Lua runtime concern. Every row is a fixture contract @@ -472,12 +481,14 @@ A scan has four distinct limits, named the same way in the types and XML docs: The global `AOBScan` route has none of these: its native cost is a scan of the whole address space, whatever the caller filters or caps afterwards. The bounded route bounds the CE work, and its copy reads one `getAddress` per needed row and -never `getValue`. `AobBoundedScanResult` reports `HostScanElapsed` (from just before the SDK's first-scan call to the end of +never `getValue`. `AobBoundedScanResult` reports `HostScanElapsed` (from just before the SDK's first-scan call to the +end of the wait, so it also contains the SDK's two target-identity checks and `FoundList.initialize`), `CopyElapsed` (count, error text and rows) and `TotalElapsed` (session creation to release) separately. Indicative host figures, from the Lua-only C3 spike of 2026-09-22 on the pinned profile under about 41 % concurrent CPU -load (not a receipt, not SDK code): when 1 of 100 291 global matches lay in the scanned module, the range route took about +load (not a receipt, not SDK code): when 1 of 100 291 global matches lay in the scanned module, the range route took +about 31–34 ms against about 455–470 ms for the global route plus a managed filter (roughly 14 times cheaper); when all 7628 matches lay in the module, both were comparable (68–73 ms against 75–86 ms), because the per-row copy (about 5 µs per `getAddress`) dominated. This is why the copy is bounded by the destination and reads addresses only. The fixture tests @@ -517,7 +528,8 @@ The tests in `tests/CheatEngine.SDK.Engine.Tests` drive a simulated Cheat Engine 12. Inspection publishes complete snapshots only, and distinguishes `nil`, malformed result, unavailable global and Lua failure (`EngineInspectionTests`). 13. Allocation ownership is consumed once; `TryAllocate` never yields a live address without an owner or a reported - compensation, a release after detach reports `NotInvoked` and after re-enable is refused, and a released region never + compensation, a release after detach reports `NotInvoked` and after re-enable is refused, and a released region + never frees a later allocation at the same address (`AllocatedRegionTests`, `TargetMemoryAllocatorTests`, `AllocationLifecycleTests`, `TargetBoundAllocationTests`). AOB lists are owned deterministically (a failed owner publication destroys the raw list once), and the MemScan/FoundList state machine destroys its child before its diff --git a/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineHostObservation.cs b/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineHostObservation.cs index f9473272..790c7931 100644 --- a/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineHostObservation.cs +++ b/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineHostObservation.cs @@ -17,7 +17,10 @@ namespace CheatEngine.SDK.Engine.Runtime; /// /// The complete file version from getCheatEngineFileVersion, or . /// The host architecture from getSystemArchitecture, or unknown. -/// Whether cheatEngineIs64Bit reported a 64-bit Cheat Engine, or . +/// +/// Whether cheatEngineIs64Bit reported a 64-bit Cheat Engine, or +/// . +/// /// The operating system from getOperatingSystem, or unknown. [StructLayout(LayoutKind.Auto)] public readonly record struct CheatEngineHostObservation( diff --git a/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineOperatingSystem.cs b/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineOperatingSystem.cs index 9c39fbcb..869d1d56 100644 --- a/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineOperatingSystem.cs +++ b/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineOperatingSystem.cs @@ -5,7 +5,8 @@ namespace CheatEngine.SDK.Engine.Runtime; /// /// Values are semantic, not the raw Lua integers: maps the /// codes documented by the CE 7.7 Lua catalogue (celua.txt:14: 0, 1, 2 for Windows, macOS and Linux). -/// The public CE source at ec45d5f returns 0 on Windows and 1 on every other build (LuaHandler.pas:14863-14867, +/// The public CE source at ec45d5f returns 0 on Windows and 1 on every other build ( +/// LuaHandler.pas:14863-14867, /// ObservedSource), so a non-Windows code is catalogue evidence only. /// /// diff --git a/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineVersion.cs b/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineVersion.cs index a1c63ec5..c0d717bc 100644 --- a/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineVersion.cs +++ b/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineVersion.cs @@ -110,9 +110,9 @@ public override int GetHashCode() public override string ToString() { return Major.ToString(CultureInfo.InvariantCulture) + "." + - Minor.ToString(CultureInfo.InvariantCulture) + "." + - Release.ToString(CultureInfo.InvariantCulture) + "." + - Build.ToString(CultureInfo.InvariantCulture); + Minor.ToString(CultureInfo.InvariantCulture) + "." + + Release.ToString(CultureInfo.InvariantCulture) + "." + + Build.ToString(CultureInfo.InvariantCulture); } /// Tests two versions for equality. diff --git a/libs/CheatEngine.SDK.Engine/Runtime/RuntimeInfo.cs b/libs/CheatEngine.SDK.Engine/Runtime/RuntimeInfo.cs index 7a1c7908..31325f6a 100644 --- a/libs/CheatEngine.SDK.Engine/Runtime/RuntimeInfo.cs +++ b/libs/CheatEngine.SDK.Engine/Runtime/RuntimeInfo.cs @@ -8,8 +8,10 @@ namespace CheatEngine.SDK.Engine.Runtime; /// /// /// -/// The SDK produces a snapshot with CheatEngine.SDK.Engine.Processes.RuntimeObservations.TryObserveRuntimeInfo, -/// which fills and, when a target is selected, ; the legacy properties are +/// The SDK produces a snapshot with +/// CheatEngine.SDK.Engine.Processes.RuntimeObservations.TryObserveRuntimeInfo, +/// which fills and, when a target is selected, ; the legacy properties +/// are /// then derived from those observations without inference. A snapshot can also carry caller-supplied facts /// through the legacy constructor, in which case and are /// . @@ -33,7 +35,10 @@ public sealed class RuntimeInfo /// The ABI family reported by getABI, or unknown. /// The immutable optional-capability observations for this snapshot. /// is . - /// This constructor records caller-supplied facts as-is; and stay . + /// + /// This constructor records caller-supplied facts as-is; and stay + /// . + /// public RuntimeInfo( CheatEngineVersion version, CheatEngineArchitecture systemArchitecture, @@ -76,7 +81,10 @@ public RuntimeInfo(CheatEngineHostObservation host, TargetArchitectureObservatio Capabilities = capabilities ?? throw new ArgumentNullException(nameof(capabilities)); } - /// Gets the Cheat Engine host observation of an SDK-produced snapshot, or for caller-supplied facts. + /// + /// Gets the Cheat Engine host observation of an SDK-produced snapshot, or for + /// caller-supplied facts. + /// public CheatEngineHostObservation? Host { get; @@ -86,7 +94,10 @@ public CheatEngineHostObservation? Host /// Gets the selected target's observation of an SDK-produced snapshot, or when no target /// was selected, its facts could not be read, or the snapshot holds caller-supplied facts. /// - /// The target bitness is ; it is not . + /// + /// The target bitness is ; it is not + /// . + /// public TargetArchitectureObservation? Target { get; diff --git a/libs/CheatEngine.SDK.Engine/Runtime/TargetArchitectureObservation.cs b/libs/CheatEngine.SDK.Engine/Runtime/TargetArchitectureObservation.cs index 9bad0e18..76d68b71 100644 --- a/libs/CheatEngine.SDK.Engine/Runtime/TargetArchitectureObservation.cs +++ b/libs/CheatEngine.SDK.Engine/Runtime/TargetArchitectureObservation.cs @@ -72,26 +72,38 @@ public TargetBackend Backend get; } - /// Gets Cheat Engine's 64-bit process flag (targetIs64Bit) as a width; this is not the configured pointer size. + /// + /// Gets Cheat Engine's 64-bit process flag (targetIs64Bit) as a width; this is not the configured pointer + /// size. + /// public PointerSize Bitness { get; } - /// Gets whether Cheat Engine reports the x86 ISA family (targetIsX86), or when absent. + /// + /// Gets whether Cheat Engine reports the x86 ISA family (targetIsX86), or when + /// absent. + /// /// An x64 target is reported as the x86 family with the 64-bit flag set. public bool? IsX86Family { get; } - /// Gets whether Cheat Engine reports the ARM ISA family (targetIsArm), or when absent. + /// + /// Gets whether Cheat Engine reports the ARM ISA family (targetIsArm), or when + /// absent. + /// public bool? IsArmFamily { get; } - /// Gets whether Cheat Engine reports an Android target (targetIsAndroid), or when absent. + /// + /// Gets whether Cheat Engine reports an Android target (targetIsAndroid), or when + /// absent. + /// /// means the global is absent; it is never read as . public bool? IsAndroid { diff --git a/libs/CheatEngine.SDK.Engine/Runtime/TargetBackend.cs b/libs/CheatEngine.SDK.Engine/Runtime/TargetBackend.cs index 188ebdd6..a40a8ce5 100644 --- a/libs/CheatEngine.SDK.Engine/Runtime/TargetBackend.cs +++ b/libs/CheatEngine.SDK.Engine/Runtime/TargetBackend.cs @@ -10,22 +10,33 @@ namespace CheatEngine.SDK.Engine.Runtime; /// /// /// -/// -/// isConnectedToCEServer() returned for a selected process identifier. +/// +/// +/// +/// +/// isConnectedToCEServer() returned for a selected process +/// identifier. +/// /// /// -/// +/// +/// +/// /// /// getOpenedProcessID() returned the file-as-process sentinel 4294967295 (CE source ec45d5f, /// ObservedSource; not yet observed on the 7.7 binary). /// /// /// -/// +/// +/// +/// /// isConnectedToCEServer() returned . /// /// -/// +/// +/// +/// /// The isConnectedToCEServer global is absent, so the backend cannot be established. /// /// diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobBoundedScan.cs b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobBoundedScan.cs index 558a4d49..5df945dc 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobBoundedScan.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobBoundedScan.cs @@ -97,7 +97,7 @@ private static void RunSession(LuaState state, MemoryScanSession session, string } if (staging is not null && - facts.Kind is AobBoundedScanOutcomeKind.Matches or AobBoundedScanOutcomeKind.NoMatches) + facts.Kind is AobBoundedScanOutcomeKind.Matches or AobBoundedScanOutcomeKind.NoMatches) { staging.AsSpan(0, facts.Written).CopyTo(destination); } @@ -135,7 +135,8 @@ private static AobBoundedScanOutcomeKind Execute(LuaState state, MemoryScanSessi // An omitted protection string is CE's "find everything" value, never a nil (celua.txt line 847). FirstScanRequest request = FirstScanRequest.ByteArray(pattern, bounds.Start, bounds.Stop, - options.ProtectionFlags ?? string.Empty, options.AlignmentMethod, options.AlignmentParameter ?? string.Empty); + options.ProtectionFlags ?? string.Empty, options.AlignmentMethod, + options.AlignmentParameter ?? string.Empty); long scanStarted = Stopwatch.GetTimestamp(); session.StartFirstScan(in request); AobBoundedScanOutcomeKind waited = Wait(state, session, waitMilliseconds, ref facts); @@ -228,7 +229,7 @@ private static AobBoundedScanOutcomeKind ReadRows(LuaState state, MemoryScanSess out int staging) { // Rows are addressed with CE's Int32 index; rows beyond it stay unread and make the in-bounds count inexact. - ulong readable = Math.Min(count, (ulong) int.MaxValue); + ulong readable = Math.Min(count, int.MaxValue); staging = 0; for (int index = 0; (ulong) index < readable && staging < staged.Length; index++) { @@ -322,11 +323,7 @@ private static AobBoundedScanOutcomeKind FromContext(MemoryScanMaterializationSt private static AobBoundedScanResult Refused(AobBoundedScanOutcomeKind kind) { - AobBoundedScanFacts facts = new() - { - Kind = kind, - Termination = MemoryScanTerminationStatus.NotRequired - }; + AobBoundedScanFacts facts = new() { Kind = kind, Termination = MemoryScanTerminationStatus.NotRequired }; return new AobBoundedScanResult(in facts); } diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobFirstFoundScan.cs b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobFirstFoundScan.cs index cd0b5025..e5d3873a 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobFirstFoundScan.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobFirstFoundScan.cs @@ -89,7 +89,8 @@ private static AobFirstFoundOutcomeKind Execute(LuaState state, MemoryScanSessio } FirstScanRequest request = FirstScanRequest.ByteArray(pattern, bounds.Start, bounds.Stop, - options.ProtectionFlags ?? string.Empty, options.AlignmentMethod, options.AlignmentParameter ?? string.Empty); + options.ProtectionFlags ?? string.Empty, options.AlignmentMethod, + options.AlignmentParameter ?? string.Empty); long scanStarted = Stopwatch.GetTimestamp(); session.StartFirstScan(in request); MemoryScanMaterializationStatus context = session.TryEnsureCurrentContextCore(state); @@ -152,7 +153,9 @@ private static AobFirstFoundOutcomeKind FromException(MemoryScanException except case MemoryScanFailureKind.UnexpectedResult: return AobFirstFoundOutcomeKind.InvalidResult; default: - luaStatus = exception.InnerException is LuaException lua ? FailureStatus(lua.Status) : LuaStatus.RuntimeError; + luaStatus = exception.InnerException is LuaException lua + ? FailureStatus(lua.Status) + : LuaStatus.RuntimeError; return AobFirstFoundOutcomeKind.ScanFailed; } } diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanBounds.cs b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanBounds.cs index b405d2e7..85ca2a04 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanBounds.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanBounds.cs @@ -7,13 +7,17 @@ namespace CheatEngine.SDK.Engine.Scanning.Aob; /// /// A non-empty, half-open target-address range [Start, Stop): the CE work limit of -/// . +/// +/// . /// /// /// /// is exclusive and is passed to CE as the MemScan stop address: on the pinned profile -/// ce-7.7.0.10621-x64-managed-hostfxr, CE reports a match only when it fits entirely below it (Lua-only host -/// observation, spike 2026-09-22, D4.1). is inclusive for the caller, but CE does not treat it +/// ce-7.7.0.10621-x64-managed-hostfxr, CE reports a match only when it fits entirely below it (Lua-only +/// host +/// observation, spike 2026-09-22, D4.1). is inclusive for the caller, but CE does not treat +/// it /// byte-exactly (D4.2): the bounded route drops, and counts, every address CE returns below it. /// /// @@ -65,7 +69,10 @@ public bool Contains(Address address) /// The inclusive lower bound. /// The exclusive upper bound. /// The range when the method returns ; otherwise the invalid default. - /// when the range is empty or inverted ( not above ). + /// + /// when the range is empty or inverted ( not above + /// ). + /// public static bool TryCreate(Address start, Address stop, out AobScanBounds bounds) { if (stop <= start) @@ -95,7 +102,7 @@ public static bool TryCreate(Address start, Address stop, out AobScanBounds boun public static bool TryFromModule(in ModuleInfo module, out AobScanBounds bounds) { if (module.ImageSize is not { } size || size.Value == 0 || - size.Value > ulong.MaxValue - module.BaseAddress.Value) + size.Value > ulong.MaxValue - module.BaseAddress.Value) { bounds = default; return false; diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOptions.cs b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOptions.cs index db1f5304..90dbe341 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOptions.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOptions.cs @@ -94,8 +94,8 @@ public string? AlignmentParameter public bool Equals(AobScanOptions other) { return string.Equals(ProtectionFlags, other.ProtectionFlags, StringComparison.Ordinal) && - AlignmentMethod == other.AlignmentMethod && - string.Equals(AlignmentParameter, other.AlignmentParameter, StringComparison.Ordinal); + AlignmentMethod == other.AlignmentMethod && + string.Equals(AlignmentParameter, other.AlignmentParameter, StringComparison.Ordinal); } /// diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOutcomeKind.cs b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOutcomeKind.cs index e31f602c..28e3d923 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOutcomeKind.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOutcomeKind.cs @@ -14,7 +14,9 @@ namespace CheatEngine.SDK.Engine.Scanning.Aob; /// profile, is therefore unreachable on the global route, and /// means "zero matches or a host failure that also produced no list": the SDK keeps it raw rather than /// converting it to a no-match classification. Only the bounded MemScan route, -/// , +/// +/// , /// reports a factual zero on that profile. /// /// Categories come from the result's Lua type and arity only, never from a Lua error message. diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanner.cs b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanner.cs index 60f8b58b..007198d1 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanner.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanner.cs @@ -325,7 +325,8 @@ public static AobBoundedScanResult TryScanWithinBounds(string pattern, AobScanBo /// the stop. The timed-out wait and terminateScan were not observed on the pinned CE 7.7.0.10621 host /// (spike D4.7), which is why this overload is experimental. /// - [Experimental("CESDK5010", UrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md")] + [Experimental("CESDK5010", + UrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md")] [MainThreadOnly] [RequiresPluginEnabled] public static AobBoundedScanResult TryScanWithinBounds(string pattern, AobScanBounds bounds, AobScanOptions options, @@ -342,7 +343,10 @@ public static AobBoundedScanResult TryScanWithinBounds(string pattern, AobScanBo /// /// CE's byte-array pattern text, passed without normalization. /// The CE work limit [Start, Stop); an invalid value is refused before any CE call. - /// CE's protection and alignment arguments; a protection string means "find everything". + /// + /// CE's protection and alignment arguments; a protection string means "find + /// everything". + /// /// /// Observed before the session is created and before the scan starts; it cannot interrupt the scan. /// @@ -370,7 +374,8 @@ public static AobBoundedScanResult TryScanWithinBounds(string pattern, AobScanBo /// were not observed on the pinned CE 7.7.0.10621 host, which is why it is experimental (CESDK5011). /// /// - [Experimental("CESDK5011", UrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md")] + [Experimental("CESDK5011", + UrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md")] [MainThreadOnly] [RequiresPluginEnabled] public static AobFirstFoundResult TryFindFirstFoundWithinBounds(string pattern, AobScanBounds bounds, diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Values/FirstScanRequest.cs b/libs/CheatEngine.SDK.Engine/Scanning/Values/FirstScanRequest.cs index a545b809..d1655cc4 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Values/FirstScanRequest.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Values/FirstScanRequest.cs @@ -216,8 +216,12 @@ public static FirstScanRequest ExactValue(VariableType variableType, string inpu /// The lower bound; not byte-exact on the pinned CE 7.7 profile (post-filter results). /// The exclusive upper bound; a match is reported only when it fits entirely below it. /// - /// The fourteen CE positions (soExactValue, vtByteArray, rtRounded, pattern, "", startAddress, stopAddress, "", - /// fsmNotAligned, "", true, false, false, false). + /// The fourteen CE positions + /// + /// (soExactValue, vtByteArray, rtRounded, pattern, "", startAddress, stopAddress, "", + /// fsmNotAligned, "", true, false, false, false) + /// + /// . /// /// is . /// @@ -245,8 +249,12 @@ public static FirstScanRequest ByteArray(string pattern, Address startAddress, A /// The address-alignment rule. /// The alignment rule's CE string parameter; empty for no alignment. /// - /// The fourteen CE positions (soExactValue, vtByteArray, rtRounded, pattern, "", startAddress, stopAddress, - /// protectionFlags, fastScanMethod, alignmentParameter, true, false, false, false). + /// The fourteen CE positions + /// + /// (soExactValue, vtByteArray, rtRounded, pattern, "", startAddress, stopAddress, + /// protectionFlags, fastScanMethod, alignmentParameter, true, false, false, false) + /// + /// . /// /// A string argument is . /// diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSession.cs b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSession.cs index 2ea4164d..ff5e8239 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSession.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSession.cs @@ -85,27 +85,36 @@ public sealed class MemoryScanSession : IDisposable private const string ResultCountOperation = "MemoryScan.ResultCount"; private const string ResultAddressOperation = "MemoryScan.ResultAddress"; private const string ResultValueOperation = "MemoryScan.ResultValue"; + + /// The maximum number of UTF-8 bytes that copies from CE. + public const int HostErrorTextMaximumUtf8Bytes = 1024; + + /// + /// The bounded wait, in milliseconds, after the one cooperative stop request that release and the bounded AOB + /// route issue for a scan that may still be running. + /// + internal const int ReleaseTerminationWaitMilliseconds = 5000; + + // The member whose CE calls are in progress, or null, and whether that member is the release itself. CE's waits, + // resets and destroys can run queued main-thread work that calls back into this session (see the type remarks). + // While a member is active, every other member is refused, and a release or abandon requested meanwhile is + // recorded here and run by the active member once its CE calls have returned. + private string? _activeOperation; + private DeferredDisposal _deferredDisposal; private Owned? _foundList; private bool _isBound; - private Owned? _scanner; + private bool _releaseInProgress; // True from immediately before a firstScan/nextScan call (CE may have started work even if the call then fails) // until a wait reports completion, a cooperative stop is confirmed, or a reset succeeds. private bool _scanMayBeRunning; + private Owned? _scanner; + private TargetSelectionObservation _targetObservation; + private MemoryScanTerminationStatus _termination; // The one cooperative stop request of the current scan, if any: it is never repeated, and its status is what a // later release reports when the stop stayed unconfirmed. private bool _terminationAttempted; - private MemoryScanTerminationStatus _termination; - private TargetSelectionObservation _targetObservation; - - // The member whose CE calls are in progress, or null, and whether that member is the release itself. CE's waits, - // resets and destroys can run queued main-thread work that calls back into this session (see the type remarks). - // While a member is active, every other member is refused, and a release or abandon requested meanwhile is - // recorded here and run by the active member once its CE calls have returned. - private string? _activeOperation; - private bool _releaseInProgress; - private DeferredDisposal _deferredDisposal; private MemoryScanSession(Owned scanner, Owned foundList) { @@ -114,15 +123,6 @@ private MemoryScanSession(Owned scanner, Owned foundList) State = MemoryScanState.New; } - /// The maximum number of UTF-8 bytes that copies from CE. - public const int HostErrorTextMaximumUtf8Bytes = 1024; - - /// - /// The bounded wait, in milliseconds, after the one cooperative stop request that release and the bounded AOB - /// route issue for a scan that may still be running. - /// - internal const int ReleaseTerminationWaitMilliseconds = 5000; - /// Gets the session's conservative, managed state. public MemoryScanState State { @@ -268,6 +268,10 @@ public ulong ResultCount } } + // Whether a release or abandon was requested from inside the active member's CE calls: that member then makes no + // further CE call. + private bool IsDisposalRequested => _deferredDisposal != DeferredDisposal.None; + /// Best-effort, no-throw disposal that consumes both owners and never implicitly retries CE cleanup. /// /// Use when the factual child and parent outcomes matter. This method is @@ -664,7 +668,7 @@ public void ResetCancellable(CancellationToken cancellationToken) } if (State == MemoryScanState.Scanning || - (_terminationAttempted && _termination != MemoryScanTerminationStatus.Confirmed)) + (_terminationAttempted && _termination != MemoryScanTerminationStatus.Confirmed)) { ThrowWrongState("Reset"); } @@ -726,7 +730,8 @@ public void ResetCancellable(CancellationToken cancellationToken) /// (timed-out) path was not observed on the pinned CE 7.7.0.10621 host (spike D4.7), which is why this member is /// experimental. It blocks CE's main thread for at most the deadline. /// - [Experimental("CESDK5010", UrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md")] + [Experimental("CESDK5010", + UrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md")] [MainThreadOnly] [RequiresPluginEnabled] public MemoryScanWaitStatus TryWaitForCompletion(TimeSpan timeout) @@ -792,7 +797,8 @@ public MemoryScanWaitStatus TryWaitForCompletion(TimeSpan timeout) /// (spike D4.7), which is why this member is experimental. /// /// - [Experimental("CESDK5010", UrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md")] + [Experimental("CESDK5010", + UrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md")] [MainThreadOnly] [RequiresPluginEnabled] public MemoryScanTerminationStatus TryTerminateScan(TimeSpan waitTimeout) @@ -1251,7 +1257,8 @@ internal static int ToWaitMilliseconds(TimeSpan timeout, string parameterName) } long ticks = timeout.Ticks; - long milliseconds = (ticks / TimeSpan.TicksPerMillisecond) + (ticks % TimeSpan.TicksPerMillisecond == 0 ? 0 : 1); + long milliseconds = (ticks / TimeSpan.TicksPerMillisecond) + + (ticks % TimeSpan.TicksPerMillisecond == 0 ? 0 : 1); if (milliseconds > int.MaxValue) { throw new ArgumentOutOfRangeException(parameterName, timeout, @@ -1365,7 +1372,7 @@ private MemoryScanTerminationStatus SettleAfterTermination(LuaState state, int w using LuaFrame frame = new(state); state.PushInteger(waitMilliseconds); if (!_scanner!.Value.Handle.TryCallMethod(state, "waitTillDone"u8, 1, 1).IsOk || - state.TypeOf(-1) != LuaType.Boolean) + state.TypeOf(-1) != LuaType.Boolean) { return MemoryScanTerminationStatus.WaitFailed; } @@ -1379,7 +1386,7 @@ internal bool TryReadHostErrorTextCore(LuaState state, [NotNullWhen(true)] out s { using LuaFrame frame = new(state); if (!_scanner!.Value.Handle.TryGetProperty(state, "ErrorString"u8).IsOk || - !state.TryReadUtf8(-1, out ReadOnlySpan utf8)) + !state.TryReadUtf8(-1, out ReadOnlySpan utf8)) { text = null; truncated = false; @@ -1620,10 +1627,6 @@ private void EndSessionCall() _ = ReleaseAsActiveCall(); } - // Whether a release or abandon was requested from inside the active member's CE calls: that member then makes no - // further CE call. - private bool IsDisposalRequested => _deferredDisposal != DeferredDisposal.None; - // After a lifecycle member returned: a release deferred from inside its CE calls has disposed the session, so the // member must not report a completed transition. private void ThrowIfReleasedDuringCall(string operation) @@ -1650,7 +1653,7 @@ private MemoryScanReleaseOutcome CompleteRelease(TargetReleaseOutcome foundListO private TargetReleaseOutcome CreateRefusedReleaseOutcome(MemoryScanMaterializationStatus context) { if (context is MemoryScanMaterializationStatus.TargetIdentityUnavailable or - MemoryScanMaterializationStatus.TargetIdentityMismatch && LastTargetCheck.HasValue) + MemoryScanMaterializationStatus.TargetIdentityMismatch && LastTargetCheck.HasValue) { return TargetReleaseOutcome.Refused(LastTargetCheck.GetValueOrDefault()); } diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSessions.cs b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSessions.cs index 642212d6..3502fd93 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSessions.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSessions.cs @@ -157,8 +157,8 @@ private static MemoryScanCreationStatus TryCreateDetailedCore([NotNullWhen(true) bool foundListRollbackFailed = !TryRollback(state, foundList, foundListHandle); bool scannerRollbackFailed = !TryRollback(state, scanner, scannerHandle); if ((foundListRollbackFailed || scannerRollbackFailed) - && session is null - && status != MemoryScanCreationStatus.Success) + && session is null + && status != MemoryScanCreationStatus.Success) { status = MemoryScanCreationStatus.RollbackUnconfirmed; } diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanStateException.cs b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanStateException.cs index 4c84d6be..74d26907 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanStateException.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanStateException.cs @@ -18,7 +18,7 @@ internal MemoryScanStateException(string operation, MemoryScanState state) // A re-entrant call: work that Cheat Engine ran from inside the session's active CE call called back into it. internal MemoryScanStateException(string operation, MemoryScanState state, string activeOperation) : base("The memory-scan operation '" + operation + "' was refused because the session's '" + activeOperation + - "' operation is still inside a Cheat Engine call (the call came from work Cheat Engine ran during it).") + "' operation is still inside a Cheat Engine call (the call came from work Cheat Engine ran during it).") { Operation = operation; State = state; diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanTerminationStatus.cs b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanTerminationStatus.cs index 40e2f7fe..9b24933f 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanTerminationStatus.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanTerminationStatus.cs @@ -1,7 +1,8 @@ namespace CheatEngine.SDK.Engine.Scanning.Values; /// -/// Classifies the one cooperative stop request for a memory scan that may still be running: terminateScan(false) +/// Classifies the one cooperative stop request for a memory scan that may still be running: +/// terminateScan(false) /// followed by a bounded waitTillDone(timeout). /// /// diff --git a/libs/CheatEngine.SDK.Engine/Tables/CheatTableFiles.cs b/libs/CheatEngine.SDK.Engine/Tables/CheatTableFiles.cs index d53c39ba..54aeba0e 100644 --- a/libs/CheatEngine.SDK.Engine/Tables/CheatTableFiles.cs +++ b/libs/CheatEngine.SDK.Engine/Tables/CheatTableFiles.cs @@ -20,7 +20,8 @@ namespace CheatEngine.SDK.Engine.Tables; /// /// Overload policy. Only the file overloads are projected. The file overload of loadTable has no /// option to suppress the Lua-script dialog, so a table that contains Lua scripts may prompt the user or execute -/// Lua. The stream overloads (loadTable(stream, merge, ignoreluascriptdialog), saveTable(stream, ...)) +/// Lua. The stream overloads (loadTable(stream, merge, ignoreluascriptdialog), +/// saveTable(stream, ...)) /// and the protect / dontDeactivateDesignerForms options of saveTable are not projected until /// a Cheat Engine stream projection exists; the Lua surface catalogue records them as deferred. /// diff --git a/libs/CheatEngine.SDK.Engine/Targets/TargetSelection.cs b/libs/CheatEngine.SDK.Engine/Targets/TargetSelection.cs index 6cadc03d..700e8f3e 100644 --- a/libs/CheatEngine.SDK.Engine/Targets/TargetSelection.cs +++ b/libs/CheatEngine.SDK.Engine/Targets/TargetSelection.cs @@ -34,7 +34,9 @@ namespace CheatEngine.SDK.Engine.Targets; /// /// /// -/// isConnectedToCEServer() == true +/// +/// isConnectedToCEServer() == true +/// /// /// : a local PID and creation /// time do not describe a PID served by CEServer, so no lookup runs and no incarnation is emitted. @@ -214,7 +216,7 @@ private static bool TryObserveIncarnation(int processId, out TargetProcessIncarn return true; } catch (Exception exception) when (exception is ArgumentException or InvalidOperationException or Win32Exception - or NotSupportedException or UnauthorizedAccessException) + or NotSupportedException or UnauthorizedAccessException) { incarnation = default; return false; diff --git a/libs/CheatEngine.SDK.Engine/Targets/TargetSelectionObservation.cs b/libs/CheatEngine.SDK.Engine/Targets/TargetSelectionObservation.cs index 73ebf36e..6b8cae4a 100644 --- a/libs/CheatEngine.SDK.Engine/Targets/TargetSelectionObservation.cs +++ b/libs/CheatEngine.SDK.Engine/Targets/TargetSelectionObservation.cs @@ -66,7 +66,8 @@ internal static TargetSelectionObservation Qualified(TargetProcessIncarnation in { return new TargetSelectionObservation(TargetSelectionObservationStatus.CurrentTargetQualified, TargetIdentityEvidence.CheatEngineSelectedProcessId | TargetIdentityEvidence.LocalBackendConfirmed | - TargetIdentityEvidence.LocalProcessStartTime, incarnation.ProcessId, incarnation, TargetBackend.LocalProcess); + TargetIdentityEvidence.LocalProcessStartTime, incarnation.ProcessId, incarnation, + TargetBackend.LocalProcess); } internal static TargetSelectionObservation NoTarget() diff --git a/libs/CheatEngine.SDK.Engine/Values/Address.cs b/libs/CheatEngine.SDK.Engine/Values/Address.cs index c71ddf7e..5c01ee30 100644 --- a/libs/CheatEngine.SDK.Engine/Values/Address.cs +++ b/libs/CheatEngine.SDK.Engine/Values/Address.cs @@ -574,7 +574,7 @@ private static int HexDigitValue(byte b) private static void ThrowFormat(ReadOnlySpan text) { throw new FormatException("'" + text.ToString() + - "' is not a hexadecimal address (digits with an optional 0x prefix)."); + "' is not a hexadecimal address (digits with an optional 0x prefix)."); } [DoesNotReturn] diff --git a/libs/CheatEngine.SDK.Engine/Values/IndexBase.cs b/libs/CheatEngine.SDK.Engine/Values/IndexBase.cs index 7f5b3ebe..e69da332 100644 --- a/libs/CheatEngine.SDK.Engine/Values/IndexBase.cs +++ b/libs/CheatEngine.SDK.Engine/Values/IndexBase.cs @@ -69,7 +69,7 @@ public static int FromLuaKey(long luaKey) /// when the key is below one or the index would not fit an . public static bool TryFromLuaKey(long luaKey, out int zeroBasedIndex) { - if (luaKey is < FirstLuaKey or > (int.MaxValue + FirstLuaKey)) + if (luaKey is < FirstLuaKey or > int.MaxValue + FirstLuaKey) { zeroBasedIndex = 0; return false; diff --git a/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs b/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs index ec7dada4..93f13ee7 100644 --- a/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs +++ b/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs @@ -139,7 +139,7 @@ private static bool TryEnterLifecycleCallback(string callback) if (SGate.IsHeldByCurrentThread) { HostLog.Error(callback + - ": re-entered from plugin code while OnEnable or OnDisable is running on this thread; the call is refused and the outer transition decides the state."); + ": re-entered from plugin code while OnEnable or OnDisable is running on this thread; the call is refused and the outer transition decides the state."); return false; } @@ -149,7 +149,7 @@ private static bool TryEnterLifecycleCallback(string callback) } HostLog.Error(callback + - ": another lifecycle transition is already running; concurrent callbacks fail immediately and do not wait for plugin code."); + ": another lifecycle transition is already running; concurrent callbacks fail immediately and do not wait for plugin code."); return false; } @@ -220,7 +220,7 @@ private static LifecycleStart TryStartEnable(out PluginDescriptor? descriptor) if (Phase is not PluginHostLifecyclePhase.Registered) { HostLog.Error("EnablePlugin: the plugin lifecycle is in " + Phase + - "; enable is valid only from Registered."); + "; enable is valid only from Registered."); return LifecycleStart.Refused; } @@ -537,17 +537,17 @@ private static LifecycleStart SelectDisableStart( if (context is null) { HostLog.Error("DisablePlugin: the plugin lifecycle is in " + Phase + - "; disable is valid only from Enabled or incomplete failed-enable cleanup."); + "; disable is valid only from Enabled or incomplete failed-enable cleanup."); return LifecycleStart.Refused; } if (Phase is PluginHostLifecyclePhase.Disabling) { if (Volatile.Read(ref s_incompleteEnableCleanup) == 0 - || Volatile.Read(ref s_incompleteEnableCleanupActive) != 0) + || Volatile.Read(ref s_incompleteEnableCleanupActive) != 0) { HostLog.Error("DisablePlugin: the plugin lifecycle is in " + Phase + - "; a disable transition is already completing."); + "; a disable transition is already completing."); return LifecycleStart.Refused; } @@ -557,7 +557,7 @@ private static LifecycleStart SelectDisableStart( if (Phase is not PluginHostLifecyclePhase.Enabled) { HostLog.Error("DisablePlugin: the plugin lifecycle is in " + Phase + - "; disable is valid only from Enabled or incomplete failed-enable cleanup."); + "; disable is valid only from Enabled or incomplete failed-enable cleanup."); return LifecycleStart.Refused; } diff --git a/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.cs b/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.cs index 5721509f..9dc32b20 100644 --- a/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.cs +++ b/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.cs @@ -124,8 +124,8 @@ internal static MainThreadWorkAdmission AdmitMainThreadWork(PluginContext contex lock (SAdmissionGate) { if (Phase is not PluginHostLifecyclePhase.Enabled || - !ReferenceEquals(context, Volatile.Read(ref s_context)) || - Volatile.Read(ref s_acceptingMainThreadWork) == 0) + !ReferenceEquals(context, Volatile.Read(ref s_context)) || + Volatile.Read(ref s_acceptingMainThreadWork) == 0) { throw new InvalidOperationException( "The plugin is stopping or disabled and no longer accepts new main-thread dispatch work."); diff --git a/libs/CheatEngine.SDK.Hosting/Diagnostics/LoadIdentification.cs b/libs/CheatEngine.SDK.Hosting/Diagnostics/LoadIdentification.cs index 93c64b36..49febe33 100644 --- a/libs/CheatEngine.SDK.Hosting/Diagnostics/LoadIdentification.cs +++ b/libs/CheatEngine.SDK.Hosting/Diagnostics/LoadIdentification.cs @@ -47,10 +47,10 @@ internal static unsafe partial class LoadIdentification private const long MaxHashedFileBytes = 16 * 1024 * 1024; [GeneratedRegex("(? @@ -90,7 +90,7 @@ internal static string Build(ManagedExportedFunctions* exports, uint pluginId, T AppendLuaFields(builder); AppendCeFields(builder); AppendField(builder, "runtime", RuntimeInformation.FrameworkDescription); - AppendField(builder, "arch", RuntimeInformation.ProcessArchitecture.ToString(), last: true); + AppendField(builder, "arch", RuntimeInformation.ProcessArchitecture.ToString(), true); if (builder.Length > MaxEntryLength) { @@ -108,9 +108,9 @@ private static void AppendSdkVersion(StringBuilder builder) string abiVersion = ReadInformationalVersion(typeof(AbiConstants).Assembly); bool consistent = string.Equals(hostingVersion, luaVersion, StringComparison.Ordinal) - && string.Equals(hostingVersion, luaInteropVersion, StringComparison.Ordinal) - && string.Equals(hostingVersion, abiVersion, StringComparison.Ordinal) - && !string.Equals(hostingVersion, Unknown, StringComparison.Ordinal); + && string.Equals(hostingVersion, luaInteropVersion, StringComparison.Ordinal) + && string.Equals(hostingVersion, abiVersion, StringComparison.Ordinal) + && !string.Equals(hostingVersion, Unknown, StringComparison.Ordinal); AppendField(builder, "sdk.version", hostingVersion); AppendField(builder, "sdk.commit", ParseCommit(hostingVersion)); @@ -217,7 +217,7 @@ private static void ReadBridgeFacts(out string fingerprint, out string sha256) try { if (!NativeLibrary.TryLoad("cheatengine-sdk-lua-bridge", typeof(PluginHost).Assembly, - DllImportSearchPath.AssemblyDirectory, out nint handle)) + DllImportSearchPath.AssemblyDirectory, out nint handle)) { return; } @@ -225,7 +225,7 @@ private static void ReadBridgeFacts(out string fingerprint, out string sha256) try { if (NativeLibrary.TryGetExport(handle, "cheatengine_sdk_lua_bridge_source_fingerprint", - out nint export)) + out nint export)) { string? text = ReadBoundedAnsiString((byte*) export, 160); if (text is not null && BridgeFingerprintPattern().IsMatch(text)) diff --git a/libs/CheatEngine.SDK.Hosting/Threading/MainThreadDispatcher.cs b/libs/CheatEngine.SDK.Hosting/Threading/MainThreadDispatcher.cs index e4d4c5ca..ff27264e 100644 --- a/libs/CheatEngine.SDK.Hosting/Threading/MainThreadDispatcher.cs +++ b/libs/CheatEngine.SDK.Hosting/Threading/MainThreadDispatcher.cs @@ -104,7 +104,7 @@ internal static void Dispatch(MainThreadWorkItem item) if (!status.IsOk) { throw new InvalidOperationException("The host's 'synchronize' global could not be read: " + - LuaError.FromStack(l, status).Message); + LuaError.FromStack(l, status).Message); } if (!l.IsFunction(-1)) @@ -118,7 +118,7 @@ internal static void Dispatch(MainThreadWorkItem item) if (!status.IsOk) { throw new InvalidOperationException("The dispatch callback could not be created: " + - LuaError.FromStack(l, status).Message); + LuaError.FromStack(l, status).Message); } using (callback) @@ -134,7 +134,7 @@ internal static void Dispatch(MainThreadWorkItem item) if (!status.IsOk) { throw new InvalidOperationException("The host's 'synchronize' call failed: " + - LuaError.FromStack(l, status).Message); + LuaError.FromStack(l, status).Message); } } diff --git a/libs/CheatEngine.SDK.Lua.Interop/CheatEngine.SDK.Lua.Interop.csproj b/libs/CheatEngine.SDK.Lua.Interop/CheatEngine.SDK.Lua.Interop.csproj index ac3825a3..df008f66 100644 --- a/libs/CheatEngine.SDK.Lua.Interop/CheatEngine.SDK.Lua.Interop.csproj +++ b/libs/CheatEngine.SDK.Lua.Interop/CheatEngine.SDK.Lua.Interop.csproj @@ -19,7 +19,7 @@ - + diff --git a/libs/CheatEngine.SDK.Lua.Interop/GlobalUsings.cs b/libs/CheatEngine.SDK.Lua.Interop/GlobalUsings.cs index 9ecce11a..f2afb927 100644 --- a/libs/CheatEngine.SDK.Lua.Interop/GlobalUsings.cs +++ b/libs/CheatEngine.SDK.Lua.Interop/GlobalUsings.cs @@ -5,6 +5,7 @@ // Scalars (luaconf.h of a default 64-bit build: LUA_INT_LONGLONG + LUA_REAL_DOUBLE, which is what Cheat Engine ships). // Function-pointer typedefs. Lua is cdecl; the convention is a no-op on x64 but matters on x86, so it is spelled out. + global using unsafe lua_Alloc = delegate* unmanaged[Cdecl]; global using unsafe lua_CFunction = delegate* unmanaged[Cdecl]; global using unsafe lua_Hook = diff --git a/libs/CheatEngine.SDK.Lua.Interop/Protected/LuaBridgeContract.cs b/libs/CheatEngine.SDK.Lua.Interop/Protected/LuaBridgeContract.cs index 918b1510..ec24718c 100644 --- a/libs/CheatEngine.SDK.Lua.Interop/Protected/LuaBridgeContract.cs +++ b/libs/CheatEngine.SDK.Lua.Interop/Protected/LuaBridgeContract.cs @@ -38,15 +38,15 @@ internal struct LuaBridgeContract internal readonly bool IsCompatible() { return Magic == ExpectedMagic && - ContractSize == (uint) Unsafe.SizeOf() && - AbiMajor == ExpectedMajor && - AbiMinor >= MinimumMinor && - PointerSize == (byte) lua_KContext.Size && - LuaIntegerSize == (byte) Unsafe.SizeOf() && - SizeTSize == (byte) Unsafe.SizeOf() && - ExportTableSize == (uint) Unsafe.SizeOf() && - Reserved == 0 && - (SupportedOperations & LuaProtectedOperationContract.RequiredBitmap) == - LuaProtectedOperationContract.RequiredBitmap; + ContractSize == (uint) Unsafe.SizeOf() && + AbiMajor == ExpectedMajor && + AbiMinor >= MinimumMinor && + PointerSize == (byte) lua_KContext.Size && + LuaIntegerSize == (byte) Unsafe.SizeOf() && + SizeTSize == (byte) Unsafe.SizeOf() && + ExportTableSize == (uint) Unsafe.SizeOf() && + Reserved == 0 && + (SupportedOperations & LuaProtectedOperationContract.RequiredBitmap) == + LuaProtectedOperationContract.RequiredBitmap; } } diff --git a/libs/CheatEngine.SDK.Lua/Callbacks/LuaCallback.cs b/libs/CheatEngine.SDK.Lua/Callbacks/LuaCallback.cs index 66626f81..bbf67dbf 100644 --- a/libs/CheatEngine.SDK.Lua/Callbacks/LuaCallback.cs +++ b/libs/CheatEngine.SDK.Lua/Callbacks/LuaCallback.cs @@ -160,8 +160,8 @@ protected virtual void Dispose(bool disposing) } if (result is LuaRuntime.LuaCallbackDisposeOperationResult.AdmissionClosed - or LuaRuntime.LuaCallbackDisposeOperationResult.ThreadNotAdmitted - or LuaRuntime.LuaCallbackDisposeOperationResult.ExternalStateReset) + or LuaRuntime.LuaCallbackDisposeOperationResult.ThreadNotAdmitted + or LuaRuntime.LuaCallbackDisposeOperationResult.ExternalStateReset) { // This result was observed atomically with the closed gate, the thread-admission refusal or the detected // external reset. A later failed Detach can reopen admission, but cannot make it safe to abandon the diff --git a/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscription.cs b/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscription.cs index ff6ee0fc..ca7ebca3 100644 --- a/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscription.cs +++ b/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscription.cs @@ -109,8 +109,8 @@ public void Dispose() } if (result is LuaRuntime.LuaCallbackDisposeOperationResult.AdmissionClosed - or LuaRuntime.LuaCallbackDisposeOperationResult.ThreadNotAdmitted - or LuaRuntime.LuaCallbackDisposeOperationResult.ExternalStateReset) + or LuaRuntime.LuaCallbackDisposeOperationResult.ThreadNotAdmitted + or LuaRuntime.LuaCallbackDisposeOperationResult.ExternalStateReset) { // The lifecycle transition still owns the linked registration and has the only state allowed to unregister // it. In particular, do not consume the action here: a failed transition can reopen the old binding, and a @@ -240,9 +240,9 @@ private bool TryEnterCallback(out Action callback) { callback = null!; if (!_acceptCallbacks - || !LuaRuntime.IsAttached - || LuaRuntime.CurrentStateIdentity != Identity - || _callback is null) + || !LuaRuntime.IsAttached + || LuaRuntime.CurrentStateIdentity != Identity + || _callback is null) { return false; } diff --git a/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscriptionRegistry.cs b/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscriptionRegistry.cs index eef08c4a..3a5bde31 100644 --- a/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscriptionRegistry.cs +++ b/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscriptionRegistry.cs @@ -47,8 +47,8 @@ internal static bool TryAdd(LuaHostSubscription subscription) lock (Gate) { if (!s_acceptRegistrations - || !LuaRuntime.IsAttached - || LuaRuntime.CurrentStateIdentity != subscription.Identity) + || !LuaRuntime.IsAttached + || LuaRuntime.CurrentStateIdentity != subscription.Identity) { return false; } diff --git a/libs/CheatEngine.SDK.Lua/CompilerServices/LuaCallSupport.cs b/libs/CheatEngine.SDK.Lua/CompilerServices/LuaCallSupport.cs index e1208da5..d3cd12ad 100644 --- a/libs/CheatEngine.SDK.Lua/CompilerServices/LuaCallSupport.cs +++ b/libs/CheatEngine.SDK.Lua/CompilerServices/LuaCallSupport.cs @@ -153,7 +153,8 @@ public static bool TryReadOptional(LuaState state, int index, ou { if (index <= 0) { - throw new ArgumentOutOfRangeException(nameof(index), index, "An optional value is read at a positive, absolute index."); + throw new ArgumentOutOfRangeException(nameof(index), index, + "An optional value is read at a positive, absolute index."); } if (index > state.Top) @@ -298,6 +299,6 @@ public static void ThrowUnexpectedResult(LuaState state, int top, int index, str string typeName = Encoding.UTF8.GetString(state.TypeName(index)); state.SetTop(top); throw new LuaException("The Lua global '" + globalName + "' returned a " + typeName + " value, not " + - expected + "."); + expected + "."); } } diff --git a/libs/CheatEngine.SDK.Lua/Marshalling/Int64Marshaller.cs b/libs/CheatEngine.SDK.Lua/Marshalling/Int64Marshaller.cs index 44d2a1d7..9c2e0004 100644 --- a/libs/CheatEngine.SDK.Lua/Marshalling/Int64Marshaller.cs +++ b/libs/CheatEngine.SDK.Lua/Marshalling/Int64Marshaller.cs @@ -10,7 +10,8 @@ namespace CheatEngine.SDK.Lua.Marshalling; /// /// /// -/// Reading never lets a value pass through a lossy : an integer subtype reads exactly; a float +/// Reading never lets a value pass through a lossy : an integer subtype reads exactly; a +/// float /// reads only when it is integral and of magnitude below 2^53 (3.0 succeeds, 9007199254740992.0, /// 1e19 and 2.5 fail); a string reads only when it is a Lua integer numeral that fits 64 bits /// ("42", " 0x10 ", "-9223372036854775808" succeed; "3.0", "1e3", diff --git a/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs b/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs index 9d4190d4..f3385044 100644 --- a/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs +++ b/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs @@ -84,7 +84,7 @@ private static bool AcceptConverted(LuaState state, int index, bool acceptIntege // lua_tointegerx already refused a non-integral, infinite or NaN float and one outside the long range. LuaType.Number => value is > -FloatExactLimit and < FloatExactLimit, LuaType.String => acceptIntegerNumerals && state.TryReadUtf8(index, out ReadOnlySpan text) && - IsIntegerNumeral(text), + IsIntegerNumeral(text), _ => false }; @@ -124,7 +124,7 @@ private static bool TryScanDecimal(ReadOnlySpan text, bool negative, ref i { int digit = text[i] - (byte) '0'; if (accumulated >= MaxIntegerDividedBy10 && - (accumulated > MaxIntegerDividedBy10 || digit > lastDigitLimit)) + (accumulated > MaxIntegerDividedBy10 || digit > lastDigitLimit)) { return false; } @@ -150,6 +150,6 @@ private static int SkipSpaces(ReadOnlySpan text, int i) private static bool IsHexadecimalDigit(byte character) { return (character >= (byte) '0' && character <= (byte) '9') || ((character | 0x20) >= (byte) 'a' && - (character | 0x20) <= (byte) 'f'); + (character | 0x20) <= (byte) 'f'); } } diff --git a/libs/CheatEngine.SDK.Lua/Marshalling/LuaOptional.cs b/libs/CheatEngine.SDK.Lua/Marshalling/LuaOptional.cs index a2084e29..b9e80c0e 100644 --- a/libs/CheatEngine.SDK.Lua/Marshalling/LuaOptional.cs +++ b/libs/CheatEngine.SDK.Lua/Marshalling/LuaOptional.cs @@ -59,7 +59,8 @@ public static LuaOptional Of(T value) /// . /// /// -/// The type is an ordinary (non-) struct, so a span cannot be optional; an optional text value +/// The type is an ordinary (non-) struct, so a span cannot be optional; an optional text +/// value /// is a LuaOptional<string>. Creating one allocates nothing beyond the value itself. /// /// @@ -139,7 +140,7 @@ public bool TryGetValue([MaybeNullWhen(false)] out T value) public bool Equals(LuaOptional other) { return _state == other._state - && (_state != ValueState || EqualityComparer.Default.Equals(_value, other._value)); + && (_state != ValueState || EqualityComparer.Default.Equals(_value, other._value)); } /// diff --git a/libs/CheatEngine.SDK.Lua/References/LuaRef.cs b/libs/CheatEngine.SDK.Lua/References/LuaRef.cs index e8b04e94..c873039e 100644 --- a/libs/CheatEngine.SDK.Lua/References/LuaRef.cs +++ b/libs/CheatEngine.SDK.Lua/References/LuaRef.cs @@ -162,8 +162,8 @@ public void Release(LuaState state) { LuaRefBinding? binding = Interlocked.Exchange(ref _binding, null); if (binding is not null && binding.Reference != NoReference && - binding.Identity == LuaRuntime.CurrentStateIdentity && - !state.IsNull) + binding.Identity == LuaRuntime.CurrentStateIdentity && + !state.IsNull) { LuaReferences.Release(state, binding.Reference); } diff --git a/libs/CheatEngine.SDK.Lua/Registration/LuaRegistrationSet.cs b/libs/CheatEngine.SDK.Lua/Registration/LuaRegistrationSet.cs index 8ee670fb..03750711 100644 --- a/libs/CheatEngine.SDK.Lua/Registration/LuaRegistrationSet.cs +++ b/libs/CheatEngine.SDK.Lua/Registration/LuaRegistrationSet.cs @@ -35,7 +35,7 @@ public static LuaRegistrationResult Register(LuaState state, ReadOnlySpanThe factual reason did, or did not, admit an operation. +/// +/// The factual reason did, or did not, admit an +/// operation. +/// /// /// The zero value is ; a default value never reads as admitted. Callers must switch on this /// enum instead of parsing an exception message: throws a diff --git a/libs/CheatEngine.SDK.Lua/Runtime/LuaHostBinding.cs b/libs/CheatEngine.SDK.Lua/Runtime/LuaHostBinding.cs index 318baa78..faf0bfff 100644 --- a/libs/CheatEngine.SDK.Lua/Runtime/LuaHostBinding.cs +++ b/libs/CheatEngine.SDK.Lua/Runtime/LuaHostBinding.cs @@ -113,7 +113,7 @@ public int MainThreadId public bool Equals(LuaHostBinding other) { return StateProvider == other.StateProvider && HostObjectPusher == other.HostObjectPusher && - MainThreadId == other.MainThreadId; + MainThreadId == other.MainThreadId; } /// diff --git a/libs/CheatEngine.SDK.Lua/Runtime/LuaRuntime.cs b/libs/CheatEngine.SDK.Lua/Runtime/LuaRuntime.cs index 9ed0d4a7..f2f155e3 100644 --- a/libs/CheatEngine.SDK.Lua/Runtime/LuaRuntime.cs +++ b/libs/CheatEngine.SDK.Lua/Runtime/LuaRuntime.cs @@ -59,9 +59,13 @@ namespace CheatEngine.SDK.Lua.Runtime; /// policy from pointer inequality nor claims a live concurrency qualification. /// /// -/// Threading and Lua concurrency contract (ADR-07, unqualified pending a future host-based validation run; no -/// local CE qualification is currently available). The 2.0 default is : -/// a new -family call is refused with +/// +/// Threading and Lua concurrency contract (ADR-07, unqualified pending a future host-based validation run; no +/// local CE qualification is currently available). +/// +/// The 2.0 default is : +/// a new -family call is refused with +/// /// before the host's state provider ever runs, unless the calling thread is the host's captured main thread, the /// call is nested inside a Lua operation or callback already admitted on that thread, or it is the single /// documented default exception: the worker-side synchronize hand-off behind @@ -109,7 +113,6 @@ public static unsafe class LuaRuntime // The private-registry universe stamp (WI-3 / A08-21, A08-22, A20-Q17-3, A20-Q18-2). Key is unique per SDK copy and // never moves; s_stamped guards the one-time write per attachment so later admissions only verify it. - private static readonly nint s_stampKey = RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(LuaRuntime), 1); private static int s_stamped; private static int s_externalResetDetected; @@ -130,7 +133,10 @@ public static unsafe class LuaRuntime internal static Action? OperationAdmissionClosedForTesting; /// The universe stamp's private-registry key. For tests only (distinctness from other private keys). - internal static nint StampKeyForTests => s_stampKey; + internal static nint StampKeyForTests + { + get; + } = RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(LuaRuntime), 1); /// Gets a value indicating whether a host binding is attached. Lock-free; any thread. public static bool IsAttached => Read(ref s_services) is not null; @@ -260,7 +266,10 @@ public static bool TryAcquireOperation(out LuaRuntimeOperation operation) /// /// Non-throwing that reports the factual admission reason instead of a boolean. /// - /// The admitted operation when the result is ; default otherwise. + /// + /// The admitted operation when the result is ; default + /// otherwise. + /// /// The factual admission outcome. Never derive a reason from an exception message instead of this enum. [RequiresPluginEnabled] public static LuaAdmissionStatus TryAcquireOperationWithOutcome(out LuaRuntimeOperation operation) @@ -278,7 +287,8 @@ public static LuaAdmissionStatus TryAcquireOperationWithOutcome(out LuaRuntimeOp /// The result is selected while SOperationGate is held. In particular, an /// result cannot be reinterpreted as detached /// after an unsuccessful transition reopens admission: callback disposal must leave registry ownership with that - /// transition until a state has neutralized the Lua closure. + /// transition until a state has neutralized the Lua closure. + /// /// and are treated the same way by callers: /// never abandon the closure early from a thread or a universe the SDK does not currently trust. /// @@ -811,8 +821,8 @@ internal static void CloseHostSubscriptionAdmissionAndDrain() internal static bool IsGeneratedFunctionRegistrationCurrent(int attachEpoch, int stateGeneration) { return Read(ref s_services) is not null - && Read(ref s_identity) == PackIdentity(attachEpoch, stateGeneration) - && IsOperationAdmissionOpen(); + && Read(ref s_identity) == PackIdentity(attachEpoch, stateGeneration) + && IsOperationAdmissionOpen(); } /// @@ -883,7 +893,7 @@ internal static void ExitOperation() // Evaluates the 2.0 admission policy under SOperationGate, entirely before services.Provider() ever runs on a // refused thread (pitfall 2): detached, external reset, transitioning and thread-not-admitted are all decided // without creating a coroutine. Only then is the provider called and the universe stamp verified. - private static unsafe LuaAdmissionStatus TryEnterProviderOperationWithOutcome(out LuaState state, + private static LuaAdmissionStatus TryEnterProviderOperationWithOutcome(out LuaState state, bool bypassThreadAdmission) { LuaAdmissionStatus gateStatus = TryEnterAdmissionGate(bypassThreadAdmission, out LuaHostServices? services); @@ -953,9 +963,9 @@ private static LuaAdmissionStatus TryEnterAdmissionGate(bool bypassThreadAdmissi } if (!bypassThreadAdmission - && Read(ref s_threadAdmission) == (int) LuaThreadAdmission.MainThreadOnly - && Environment.CurrentManagedThreadId != services.MainThreadId - && t_operationDepth == 0) + && Read(ref s_threadAdmission) == (int) LuaThreadAdmission.MainThreadOnly + && Environment.CurrentManagedThreadId != services.MainThreadId + && t_operationDepth == 0) { return LuaAdmissionStatus.ThreadNotAdmitted; } @@ -971,8 +981,8 @@ private static bool TryStampOrVerify(LuaState state) { if (Interlocked.CompareExchange(ref s_stamped, 1, 0) == 0) { - state.PushLightUserdata(s_stampKey); - state.RawSetPointer(LuaState.RegistryIndex, s_stampKey); + state.PushLightUserdata(StampKeyForTests); + state.RawSetPointer(LuaState.RegistryIndex, StampKeyForTests); return true; } @@ -982,8 +992,8 @@ private static bool TryStampOrVerify(LuaState state) // Raw, non-allocating, no metamethod (pitfall 6c): a plain rawgetp/touserdata/pop. ZeroAllocationTests gates this. private static bool CheckStamp(LuaState state) { - LuaType type = state.RawGetPointer(LuaState.RegistryIndex, s_stampKey); - bool matches = type == LuaType.LightUserdata && state.ToUserdata(-1) == s_stampKey; + LuaType type = state.RawGetPointer(LuaState.RegistryIndex, StampKeyForTests); + bool matches = type == LuaType.LightUserdata && state.ToUserdata(-1) == StampKeyForTests; state.Pop(1); return matches; } @@ -991,7 +1001,7 @@ private static bool CheckStamp(LuaState state) // Best-effort eager stamp at Attach (or after CompleteStateReset) time, on the state the binding already // provides. Deferred to the first admitted acquisition when the provider yields no state yet (pitfall 6a: tests // may attach with a provider returning null). - private static unsafe void StampIfStateAvailable(LuaHostServices services) + private static void StampIfStateAvailable(LuaHostServices services) { lua_State* l = services.Provider(); if (l is null) @@ -1004,8 +1014,8 @@ private static unsafe void StampIfStateAvailable(LuaHostServices services) { if (Interlocked.CompareExchange(ref s_stamped, 1, 0) == 0) { - state.PushLightUserdata(s_stampKey); - state.RawSetPointer(LuaState.RegistryIndex, s_stampKey); + state.PushLightUserdata(StampKeyForTests); + state.RawSetPointer(LuaState.RegistryIndex, StampKeyForTests); } } catch @@ -1021,7 +1031,7 @@ private static unsafe void StampIfStateAvailable(LuaHostServices services) // BeginStateReset) would otherwise unref and neutralize against. Never mutates anything and never releases a // reference: a mismatch means the whole registry belongs to a different Lua universe (A08-22), so the caller // must abandon instead of unregistering into it. - private static unsafe bool DetectExternalResetForDetach(LuaHostServices services, out LuaState state) + private static bool DetectExternalResetForDetach(LuaHostServices services, out LuaState state) { if (Read(ref s_externalResetDetected) != 0) { diff --git a/libs/CheatEngine.SDK.Lua/Runtime/LuaThreadAdmission.cs b/libs/CheatEngine.SDK.Lua/Runtime/LuaThreadAdmission.cs index c8022b97..9607574b 100644 --- a/libs/CheatEngine.SDK.Lua/Runtime/LuaThreadAdmission.cs +++ b/libs/CheatEngine.SDK.Lua/Runtime/LuaThreadAdmission.cs @@ -20,7 +20,8 @@ public enum LuaThreadAdmission /// /// The conservative default: a new -family call is admitted only on /// the host's captured main thread, inside a host-invoked callback already running on the calling thread, or - /// through the single documented synchronize hand-off (). + /// through the single documented synchronize hand-off ( + /// ). /// MainThreadOnly = 0, diff --git a/libs/CheatEngine.SDK.Lua/State/LuaState.Tables.cs b/libs/CheatEngine.SDK.Lua/State/LuaState.Tables.cs index 1ccc62b1..8728ead4 100644 --- a/libs/CheatEngine.SDK.Lua/State/LuaState.Tables.cs +++ b/libs/CheatEngine.SDK.Lua/State/LuaState.Tables.cs @@ -86,7 +86,7 @@ public bool TryRawSet(int tableIndex) { int keyType = lua_type(Pointer, -2); if (keyType == LUA_TNIL || (keyType == LUA_TNUMBER && lua_isinteger(Pointer, -2) == 0 && - double.IsNaN(lua_tonumberx(Pointer, -2, null)))) + double.IsNaN(lua_tonumberx(Pointer, -2, null)))) { lua_settop(Pointer, -3); return false; diff --git a/native/cheatengine-sdk-lua-bridge/cheatengine_sdk_lua_bridge.c b/native/cheatengine-sdk-lua-bridge/cheatengine_sdk_lua_bridge.c index 06b878a5..e9b3923c 100644 --- a/native/cheatengine-sdk-lua-bridge/cheatengine_sdk_lua_bridge.c +++ b/native/cheatengine-sdk-lua-bridge/cheatengine_sdk_lua_bridge.c @@ -250,7 +250,7 @@ static int CHEATENGINE_SDK_CALL operation(lua_State* L) { case OP_PUSH_BYTES: { - static const char empty = 0; + static constexpr char empty = 0; if (c->input_count != 0 || (c->size != 0 && !c->data)) return fail(L, "CheatEngine.SDK protected byte push has invalid arguments"); a->pushlstring(L, c->size ? (const char*)c->data : &empty, c->size); diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/AnalyzerReleases.Unshipped.md b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/AnalyzerReleases.Unshipped.md index 7b32c473..231c0255 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/AnalyzerReleases.Unshipped.md +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/AnalyzerReleases.Unshipped.md @@ -4,7 +4,7 @@ ### New Rules Rule ID | Category | Severity | Notes ------------|---------------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------ +-----------|---------------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------- CESDK3001 | CheatEngine.SDK.EngineApi | Error | EngineApiGenerator, invalid curated API specification, [Documentation](https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/CESDK3001.md) CESDK3002 | CheatEngine.SDK.EngineApi | Error | EngineApiGenerator, generated-identity conflict, [Documentation](https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/CESDK3002.md) CESDK3003 | CheatEngine.SDK.EngineApi | Error | EngineApiGenerator, missing ce77 contract, [Documentation](https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/CESDK3003.md) diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Emit/EngineApiFileEmitter.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Emit/EngineApiFileEmitter.cs index 4251e4ee..6e77c7ac 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Emit/EngineApiFileEmitter.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Emit/EngineApiFileEmitter.cs @@ -187,8 +187,7 @@ private static void EmitAddressTypedWrapper(SourceWriter writer, SpecCallModel e LuaGlobalCallModel call = entry.Call; LuaGlobalCallModel core = call with { - Modifiers = "private static", - MethodName = CoreMethodName(call.MethodName) + Modifiers = "private static", MethodName = CoreMethodName(call.MethodName) }; writer.Write("// Raw core of '"); diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Model/SpecFiles.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Model/SpecFiles.cs index 777ac885..f87cc430 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Model/SpecFiles.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Model/SpecFiles.cs @@ -56,10 +56,7 @@ private static void AssignUniqueHintNames(List specs) } } - specs[i] = specs[i] with - { - HintName = hintName - }; + specs[i] = specs[i] with { HintName = hintName }; } } @@ -98,10 +95,7 @@ private static void SuppressCrossFileConflicts(List specs) foreach (int index in indices) { - specs[index] = specs[index] with - { - IsSuppressed = true - }; + specs[index] = specs[index] with { IsSuppressed = true }; } } } @@ -202,10 +196,7 @@ private static void AddConflict(ref SpecFileModel spec, int line, int column, st { List issues = [.. spec.Issues]; issues.Add(new SpecIssue(line, message, column, SpecIssueKind.Conflict)); - spec = spec with - { - Issues = new EquatableArray([.. issues]) - }; + spec = spec with { Issues = new EquatableArray([.. issues]) }; } private static string QualifiedTypeName(SpecFileModel spec) diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs index f0016a8c..f2a9be98 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs @@ -208,13 +208,13 @@ private static bool ParseHeader(List blocks, List issues, out } if (!ReadHeaderFields( - header, - issues, - out string? namespaceValue, - out string? typeValue, - out typeLine, - out typeColumn, - out contract)) + header, + issues, + out string? namespaceValue, + out string? typeValue, + out typeLine, + out typeColumn, + out contract)) { return false; } @@ -365,10 +365,10 @@ private static bool TryCreateCe77Contract(HeaderFields fields, Block header, Lis { contract = null; if (!TryRequireContractField(fields.Provenance, "provenance", header, issues, out SpecField provenance) - || !TryRequireContractField(fields.MinimumCe, "minimum-ce", header, issues, out SpecField minimumCe) - || !TryRequireContractField(fields.Architecture, "architecture", header, issues, out SpecField architecture) - || !TryRequireContractField(fields.Thread, "thread", header, issues, out SpecField thread) - || !TryRequireContractField(fields.Ownership, "ownership", header, issues, out SpecField ownership)) + || !TryRequireContractField(fields.MinimumCe, "minimum-ce", header, issues, out SpecField minimumCe) + || !TryRequireContractField(fields.Architecture, "architecture", header, issues, out SpecField architecture) + || !TryRequireContractField(fields.Thread, "thread", header, issues, out SpecField thread) + || !TryRequireContractField(fields.Ownership, "ownership", header, issues, out SpecField ownership)) { return false; } @@ -502,11 +502,11 @@ private static bool IsValidProvenance(string value) string status = value[..colon]; return string.Equals(status, "ExactBinary", StringComparison.Ordinal) - || string.Equals(status, "ExactInstalledFile", StringComparison.Ordinal) - || string.Equals(status, "PinnedUpstream", StringComparison.Ordinal) - || string.Equals(status, "ObservedLive", StringComparison.Ordinal) - || string.Equals(status, "Inferred", StringComparison.Ordinal) - || string.Equals(status, "Unknown", StringComparison.Ordinal); + || string.Equals(status, "ExactInstalledFile", StringComparison.Ordinal) + || string.Equals(status, "PinnedUpstream", StringComparison.Ordinal) + || string.Equals(status, "ObservedLive", StringComparison.Ordinal) + || string.Equals(status, "Inferred", StringComparison.Ordinal) + || string.Equals(status, "Unknown", StringComparison.Ordinal); } private static bool IsFourPartVersion(string value) @@ -541,23 +541,23 @@ private static bool IsFourPartVersion(string value) private static bool IsThreadAffinity(string value) { return string.Equals(value, "any", StringComparison.Ordinal) - || string.Equals(value, "main", StringComparison.Ordinal) - || string.Equals(value, "unknown", StringComparison.Ordinal); + || string.Equals(value, "main", StringComparison.Ordinal) + || string.Equals(value, "unknown", StringComparison.Ordinal); } private static bool IsOwnership(string value) { return string.Equals(value, "none", StringComparison.Ordinal) - || string.Equals(value, "borrowed", StringComparison.Ordinal) - || string.Equals(value, "owned", StringComparison.Ordinal); + || string.Equals(value, "borrowed", StringComparison.Ordinal) + || string.Equals(value, "owned", StringComparison.Ordinal); } private static bool IsNilSemantics(string value) { return string.Equals(value, "none", StringComparison.Ordinal) - || string.Equals(value, "absence", StringComparison.Ordinal) - || string.Equals(value, "expected-failure", StringComparison.Ordinal) - || string.Equals(value, "lua-error", StringComparison.Ordinal); + || string.Equals(value, "absence", StringComparison.Ordinal) + || string.Equals(value, "expected-failure", StringComparison.Ordinal) + || string.Equals(value, "lua-error", StringComparison.Ordinal); } private static SpecCallModel? ParseEntry(Block block, List issues, SpecFileContract? fileContract) @@ -597,7 +597,7 @@ private static bool IsNilSemantics(string value) } if (!TryParseReturnKind(fields, form == LuaCallForm.Throwing, block.StartLine, issues, - out LuaValueKind? returnKind, out bool returnIsNullable)) + out LuaValueKind? returnKind, out bool returnIsNullable)) { return null; } @@ -681,10 +681,12 @@ private static bool TrySetEntryField(EntryFields fields, HashSet singula case "return": return TrySetReturn(fields, singular, field, issues); case "arg": - fields.ArgumentTokens.Add(new SpecToken(field.Line, field.ValueColumn, field.Value, TokenRole.Argument)); + fields.ArgumentTokens.Add(new SpecToken(field.Line, field.ValueColumn, field.Value, + TokenRole.Argument)); return true; case "opt": - fields.ArgumentTokens.Add(new SpecToken(field.Line, field.ValueColumn, field.Value, TokenRole.Optional)); + fields.ArgumentTokens.Add(new SpecToken(field.Line, field.ValueColumn, field.Value, + TokenRole.Optional)); return true; case "fixed": fields.ArgumentTokens.Add(new SpecToken(field.Line, field.ValueColumn, field.Value, TokenRole.Fixed)); @@ -761,7 +763,7 @@ private static bool ValidateRequiredText(EntryFields fields, int startLine, bool form = LuaCallForm.Throwing; if (!ValidateRequiredPresence(fields, startLine, issues) - || !ValidateNilContract(fields, startLine, requiresCe77Contract, issues)) + || !ValidateNilContract(fields, startLine, requiresCe77Contract, issues)) { return false; } @@ -840,7 +842,8 @@ private static bool ValidateResultOrder(List tokens, LuaCallForm form } else if (token.Role == TokenRole.Argument && sawOptional) { - problem = "is a required 'result' after an 'opt-result': optional results come after every required one"; + problem = + "is a required 'result' after an 'opt-result': optional results come after every required one"; } else if (token.Role == TokenRole.Rest && form != LuaCallForm.Outcome) { @@ -907,8 +910,10 @@ private static bool TryParseReturnKind( if (sawOptional && token.Role != TokenRole.Optional) { issues.Add(new SpecIssue(token.Line, - "'" + token.Value + "' follows an 'opt' argument: only more 'opt' arguments may follow one, because Lua " - + "cannot receive an argument after an omitted one.", token.Column, SpecIssueKind.OptionalArgument)); + "'" + token.Value + + "' follows an 'opt' argument: only more 'opt' arguments may follow one, because Lua " + + "cannot receive an argument after an omitted one.", token.Column, + SpecIssueKind.OptionalArgument)); return null; } @@ -930,8 +935,8 @@ private static bool TryParseReturnKind( private static LuaArgumentModel? ParseValueArgument(SpecToken token, List issues) { if (!TryParseNamedValue(token.Value, out string name, out string kindToken) - || !SpecIdentifiers.IsValidIdentifier(name) - || !SpecValueKinds.TryParse(kindToken, out LuaValueKind kind, out bool nullable)) + || !SpecIdentifiers.IsValidIdentifier(name) + || !SpecValueKinds.TryParse(kindToken, out LuaValueKind kind, out bool nullable)) { issues.Add(new SpecIssue(token.Line, "'" + token.Value + "' is not a valid 'name:kind' argument.", token.Column)); @@ -946,7 +951,8 @@ private static bool TryParseReturnKind( if (nullable || !LuaValueKinds.CanBeOptional(kind)) { issues.Add(new SpecIssue(token.Line, - "'" + kindToken + "' cannot be an 'opt' kind: nil is the Nil state of LuaOptional, and a span cannot be " + "'" + kindToken + + "' cannot be an 'opt' kind: nil is the Nil state of LuaOptional, and a span cannot be " + "optional; use 'string' for optional text.", token.Column, SpecIssueKind.OptionalArgument)); return null; } @@ -960,9 +966,9 @@ private static bool TryParseReturnKind( private static LuaArgumentModel? ParseFixedArgument(SpecToken token, List issues) { if (!TryParseNamedValue(token.Value, out string kindToken, out string literal) - || !string.Equals(kindToken, "boolean", StringComparison.Ordinal) - || !(string.Equals(literal, "true", StringComparison.Ordinal) - || string.Equals(literal, "false", StringComparison.Ordinal))) + || !string.Equals(kindToken, "boolean", StringComparison.Ordinal) + || !(string.Equals(literal, "true", StringComparison.Ordinal) + || string.Equals(literal, "false", StringComparison.Ordinal))) { issues.Add(new SpecIssue(token.Line, "'" + token.Value + "' is not a valid fixed argument: expected 'boolean:true' or 'boolean:false'.", @@ -979,8 +985,8 @@ private static bool TryParseReturnKind( foreach (SpecToken token in tokens) { if (!TryParseNamedValue(token.Value, out string name, out string kindToken) - || !SpecIdentifiers.IsValidIdentifier(name) - || !SpecValueKinds.TryParse(kindToken, out LuaValueKind kind, out bool nullable)) + || !SpecIdentifiers.IsValidIdentifier(name) + || !SpecValueKinds.TryParse(kindToken, out LuaValueKind kind, out bool nullable)) { issues.Add(new SpecIssue(token.Line, "'" + token.Value + "' is not a valid 'name:kind' result.", token.Column)); @@ -1022,7 +1028,8 @@ private static bool TryParseReturnKind( return LuaResultModel.Optional(kind, name); case TokenRole.Rest when !LuaValueKinds.CanBeVariadicElement(kind) || kind == LuaValueKind.Address: issues.Add(new SpecIssue(token.Line, - "'" + kindToken + "' cannot be a 'rest' kind: expected 'int32', 'int64', 'single', 'double' or 'boolean'.", + "'" + kindToken + + "' cannot be a 'rest' kind: expected 'int32', 'int64', 'single', 'double' or 'boolean'.", token.Column, SpecIssueKind.ResultShape)); return null; case TokenRole.Rest: @@ -1238,8 +1245,8 @@ private static bool IsReservedBodyLocal(string name, LuaGlobalCallModel call) } if (string.Equals(name, "__engineApiSucceeded", StringComparison.Ordinal) - || string.Equals(name, "__engineApiStatus", StringComparison.Ordinal) - || string.Equals(name, "__engineApiRawResult", StringComparison.Ordinal)) + || string.Equals(name, "__engineApiStatus", StringComparison.Ordinal) + || string.Equals(name, "__engineApiRawResult", StringComparison.Ordinal)) { return true; } @@ -1252,7 +1259,7 @@ private static bool IsReservedBodyLocal(string name, LuaGlobalCallModel call) for (int i = 0; i < call.Results.Length; i++) { if (call.Results[i].Kind == LuaValueKind.Address - && string.Equals(name, RawResultName(i), StringComparison.Ordinal)) + && string.Equals(name, RawResultName(i), StringComparison.Ordinal)) { return true; } @@ -1320,8 +1327,8 @@ private static List DropCacheMemberCollisions(List foreach (SpecCallModel entry in entries) { bool conflicts = cacheFields.Contains(entry.Call.MethodName) - || (UsesAddressFacade(entry.Call) && - cacheFields.Contains(CoreMethodName(entry.Call.MethodName))); + || (UsesAddressFacade(entry.Call) && + cacheFields.Contains(CoreMethodName(entry.Call.MethodName))); if (!conflicts) { valid.Add(entry); @@ -1347,9 +1354,9 @@ private static List DropTypeMemberCollisions(List foreach (SpecCallModel entry in entries) { bool conflicts = string.Equals(entry.Call.MethodName, typeName, StringComparison.Ordinal) - || (UsesAddressFacade(entry.Call) - && string.Equals(CoreMethodName(entry.Call.MethodName), typeName, - StringComparison.Ordinal)); + || (UsesAddressFacade(entry.Call) + && string.Equals(CoreMethodName(entry.Call.MethodName), typeName, + StringComparison.Ordinal)); if (!conflicts) { valid.Add(entry); diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs index d845190a..ee692c81 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs @@ -86,7 +86,7 @@ public static string Escape(string identifier) private static bool IsStart(char c) { - return c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '_'; + return c is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or '_'; } private static bool IsPart(char c) diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/README.md b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/README.md index b2328a38..f8dc1414 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/README.md +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/README.md @@ -38,15 +38,15 @@ additional file: Only files explicitly included as `AdditionalFiles` participate in one generator invocation. Every production spec declares `contract: ce77` and parses without an issue, and they fall in three groups: -| Spec | Status | -|---------------------------------------------------|------------------------------------------------------------------------------------------------------------| -| `memory-scalars.cheatengine-sdk-api.txt` | Wired: generates `CheatEngine.SDK.Engine.Generated.MemoryScalars`. | -| `runtime-capabilities.cheatengine-sdk-api.txt` | Reviewed, not wired yet: runtime capability probes (the runtime lot wires it). | -| `allocation-protection.cheatengine-sdk-api.txt` | Reviewed, not wired: the public `Address`/`TargetAllocationRequest` contract is hand-written in Engine. | -| `modules-symbols-regions.cheatengine-sdk-api.txt` | Reviewed, not wired: the public inspection wrapper uses the same global directly. | -| `addresslist-memoryrecord.cheatengine-sdk-api.txt`| Header-only reservation: needs the object grammar. | -| `aob-stringlist.cheatengine-sdk-api.txt` | Header-only reservation: needs the object-result grammar. | -| `memscan-foundlist.cheatengine-sdk-api.txt` | Header-only reservation: needs the object-method grammar. | +| Spec | Status | +|----------------------------------------------------|---------------------------------------------------------------------------------------------------------| +| `memory-scalars.cheatengine-sdk-api.txt` | Wired: generates `CheatEngine.SDK.Engine.Generated.MemoryScalars`. | +| `runtime-capabilities.cheatengine-sdk-api.txt` | Reviewed, not wired yet: runtime capability probes (the runtime lot wires it). | +| `allocation-protection.cheatengine-sdk-api.txt` | Reviewed, not wired: the public `Address`/`TargetAllocationRequest` contract is hand-written in Engine. | +| `modules-symbols-regions.cheatengine-sdk-api.txt` | Reviewed, not wired: the public inspection wrapper uses the same global directly. | +| `addresslist-memoryrecord.cheatengine-sdk-api.txt` | Header-only reservation: needs the object grammar. | +| `aob-stringlist.cheatengine-sdk-api.txt` | Header-only reservation: needs the object-result grammar. | +| `memscan-foundlist.cheatengine-sdk-api.txt` | Header-only reservation: needs the object-method grammar. | A reviewed or reserved spec is not silently generated, and its presence does not imply that a wrapper exists. The number of entries is not a coverage measure: the four `MemoryScalars` entries are four explicit contracts, not the Lua @@ -76,28 +76,28 @@ A spec file is plain text made of `key: value` lines. Blank lines separate block every later block is one entry. A line that starts with `#` is a comment and never separates blocks. Indentation and CRLF line endings are tolerated. -| Key | Block | Count | Meaning | -|----------------|--------|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------| -| `namespace` | header | 1 | Namespace of the generated type. An empty value means the global namespace. | -| `type` | header | 1 | Name of the one `public static partial class` the file emits. | -| `contract` | header | 1 with entries | `ce77`: the mandatory, machine-validated CE 7.7 evidence contract below (`CESDK3003` when a file with entries omits it). | -| `provenance` | header | with `contract` | A proof status followed by `: ` and an immutable source reference. | -| `minimum-ce` | header | with `contract` | Exact four-part minimum CE version, for example `7.7.0.10621`. | -| `architecture` | header | with `contract` | `x64`; this generator makes no public target-address claim on another architecture. | -| `thread` | header | with `contract` | `any`, `main`, or `unknown`; `unknown` records absent proof rather than granting thread safety. | -| `ownership` | header | with `contract` | `none`, `borrowed`, or `owned`. Object contracts remain deliberately outside the scalar grammar. | -| `global` | entry | 1 | The Lua global to call: an ASCII identifier that is not a Lua 5.3 reserved word. | -| `method` | entry | 1 | The C# method name. A C# reserved word gets an `@` prefix. | +| Key | Block | Count | Meaning | +|----------------|--------|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `namespace` | header | 1 | Namespace of the generated type. An empty value means the global namespace. | +| `type` | header | 1 | Name of the one `public static partial class` the file emits. | +| `contract` | header | 1 with entries | `ce77`: the mandatory, machine-validated CE 7.7 evidence contract below (`CESDK3003` when a file with entries omits it). | +| `provenance` | header | with `contract` | A proof status followed by `: ` and an immutable source reference. | +| `minimum-ce` | header | with `contract` | Exact four-part minimum CE version, for example `7.7.0.10621`. | +| `architecture` | header | with `contract` | `x64`; this generator makes no public target-address claim on another architecture. | +| `thread` | header | with `contract` | `any`, `main`, or `unknown`; `unknown` records absent proof rather than granting thread safety. | +| `ownership` | header | with `contract` | `none`, `borrowed`, or `owned`. Object contracts remain deliberately outside the scalar grammar. | +| `global` | entry | 1 | The Lua global to call: an ASCII identifier that is not a Lua 5.3 reserved word. | +| `method` | entry | 1 | The C# method name. A C# reserved word gets an `@` prefix. | | `form` | entry | 1 | `try` returns `bool` and writes `out` results. `outcome` returns `LuaOperationStatus` and writes `out` results. `throwing` returns the value, or `void`, and raises `LuaException` when the Lua call fails. | -| `doc` | entry | 1 | One line of original English, emitted as the XML ``. Never copy Cheat Engine documentation. | -| `arg` | entry | 0 or more | `name:kind`, one pushed argument. `arg`, `fixed` and `opt` keep their textual order, which is the push order. | -| `fixed` | entry | 0 or more | `boolean:true` or `boolean:false`, one host-required Lua argument omitted from the C# signature. | -| `opt` | entry | 0 or more, last | `name:kind`, one `LuaOptional` argument: omitted (not pushed), `Nil` (pushed as `nil`) or a value. Only `opt` may follow (`CESDK3004`). | -| `result` | entry | `try`: 1 or more | `name:kind`, one `out` result, in read order. Not allowed in a `throwing` entry. | -| `opt-result` | entry | 0 or more | `name:kind`, one `out LuaOptional` result after the `result` values: a position Lua did not return is omitted (`CESDK3005`). | -| `rest` | entry | `outcome`: 0 or 1 | `name:kind`, the variadic tail `Span name, out int nameCount`, last; kinds `int32`, `int64`, `single`, `double`, `boolean`. | -| `return` | entry | `throwing`: 0 or 1 | The kind of the returned value. Omit it for `void`. Not allowed in a `try` entry. | -| `nil` | entry | with `contract` | `none`, `absence`, `expected-failure`, or `lua-error`: CE result semantics after a protected call succeeds. | +| `doc` | entry | 1 | One line of original English, emitted as the XML ``. Never copy Cheat Engine documentation. | +| `arg` | entry | 0 or more | `name:kind`, one pushed argument. `arg`, `fixed` and `opt` keep their textual order, which is the push order. | +| `fixed` | entry | 0 or more | `boolean:true` or `boolean:false`, one host-required Lua argument omitted from the C# signature. | +| `opt` | entry | 0 or more, last | `name:kind`, one `LuaOptional` argument: omitted (not pushed), `Nil` (pushed as `nil`) or a value. Only `opt` may follow (`CESDK3004`). | +| `result` | entry | `try`: 1 or more | `name:kind`, one `out` result, in read order. Not allowed in a `throwing` entry. | +| `opt-result` | entry | 0 or more | `name:kind`, one `out LuaOptional` result after the `result` values: a position Lua did not return is omitted (`CESDK3005`). | +| `rest` | entry | `outcome`: 0 or 1 | `name:kind`, the variadic tail `Span name, out int nameCount`, last; kinds `int32`, `int64`, `single`, `double`, `boolean`. | +| `return` | entry | `throwing`: 0 or 1 | The kind of the returned value. Omit it for `void`. Not allowed in a `try` entry. | +| `nil` | entry | with `contract` | `none`, `absence`, `expected-failure`, or `lua-error`: CE result semantics after a protected call succeeds. | The kinds are `int32`, `int64`, `single`, `double`, `boolean`, `address`, `utf8`, `string` and `string?`. A `utf8` value is valid only as an argument, because a span result would dangle once the wrapper restores the stack. `utf8` and @@ -172,20 +172,20 @@ A19-23). Three independent checks therefore exist: ## Promise -| You can rely on | Backed by | -|---------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------| -| The generator never ships. | `src/CheatEngine.SDK/CheatEngine.SDK.csproj` packs only the analyzer references it marks `PackAsAnalyzer`, and it does not reference this project. | -| Every invalid spec issue is a localized `CESDK3001` error; an unrelated valid entry still emits. | `Parsing/SpecFileParserTests.cs`, `Generator/DiagnosticsTests.cs` | -| A spec with entries must declare `contract: ce77` (`CESDK3003`); every production spec parses without an issue, cites the pinned `celua.txt` SHA-256, claims no unproven thread affinity, and is wired or reviewed. | `Parsing/ProductionSpecsTests.cs`, `Spec_with_entries_without_contract_reports_the_missing_ce77_contract` | -| `opt` arguments are omitted, `nil` or pushed exactly as declared; `opt-result` distinguishes zero results from `nil`; `rest` copies every value or reports the needed capacity; an absent global is `GlobalUnavailable` in the `outcome` form. | `EndToEnd/EngineApiOptionalEndToEndTests.cs`, `Parsing/SpecFileParserTests.cs` (`CESDK3004`/`CESDK3005` rows) | -| The wired `MemoryScalars` output is byte-identical to its committed text; a reformatted spec (spaces, comments, CRLF) keeps the same contract and call model. | `Memory_scalars_output_is_unchanged_by_the_new_grammar`, `Reformatting_a_spec_keeps_its_contract_and_call_model` | -| Every EngineApi diagnostic has a documentation page, a help link and a release-tracking row. | `Generator/EngineApiDiagnosticCatalogTests.cs` | -| A ce77 spec carries validated provenance/version/architecture/thread/ownership/return/nil facts on every entry and projects them into XML documentation. | `Parsing/SpecFileParserTests.cs`, `Generator/EmissionTests.cs` | -| A spec file exclusively owns its generated type; duplicate type/member/cache identities are `CESDK3002` errors at each exact field and emit neither file. | `Generator/DiagnosticsTests.cs` | -| Emitted code compiles without errors or warnings against the real `CheatEngine.SDK.Annotations`, `CheatEngine.SDK.Lua.Interop` and `CheatEngine.SDK.Lua`. | `Generator/EmissionTests.cs` | -| Editing one spec file re-emits only that file. An unrelated compilation edit recomputes nothing. | `Generator/IncrementalityTests.cs` | -| No parsed model in the pipeline holds a Roslyn object. | `Pipeline_step_values_hold_no_roslyn_objects` in `Generator/IncrementalityTests.cs` | -| Wrappers leave the Lua stack as they found it, allocate nothing on the warm success path, and throw `InvalidOperationException` while no runtime is attached. | `EndToEnd/MemoryScalarsEndToEndTests.cs`, run against stand-in Lua globals | +| You can rely on | Backed by | +|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------| +| The generator never ships. | `src/CheatEngine.SDK/CheatEngine.SDK.csproj` packs only the analyzer references it marks `PackAsAnalyzer`, and it does not reference this project. | +| Every invalid spec issue is a localized `CESDK3001` error; an unrelated valid entry still emits. | `Parsing/SpecFileParserTests.cs`, `Generator/DiagnosticsTests.cs` | +| A spec with entries must declare `contract: ce77` (`CESDK3003`); every production spec parses without an issue, cites the pinned `celua.txt` SHA-256, claims no unproven thread affinity, and is wired or reviewed. | `Parsing/ProductionSpecsTests.cs`, `Spec_with_entries_without_contract_reports_the_missing_ce77_contract` | +| `opt` arguments are omitted, `nil` or pushed exactly as declared; `opt-result` distinguishes zero results from `nil`; `rest` copies every value or reports the needed capacity; an absent global is `GlobalUnavailable` in the `outcome` form. | `EndToEnd/EngineApiOptionalEndToEndTests.cs`, `Parsing/SpecFileParserTests.cs` (`CESDK3004`/`CESDK3005` rows) | +| The wired `MemoryScalars` output is byte-identical to its committed text; a reformatted spec (spaces, comments, CRLF) keeps the same contract and call model. | `Memory_scalars_output_is_unchanged_by_the_new_grammar`, `Reformatting_a_spec_keeps_its_contract_and_call_model` | +| Every EngineApi diagnostic has a documentation page, a help link and a release-tracking row. | `Generator/EngineApiDiagnosticCatalogTests.cs` | +| A ce77 spec carries validated provenance/version/architecture/thread/ownership/return/nil facts on every entry and projects them into XML documentation. | `Parsing/SpecFileParserTests.cs`, `Generator/EmissionTests.cs` | +| A spec file exclusively owns its generated type; duplicate type/member/cache identities are `CESDK3002` errors at each exact field and emit neither file. | `Generator/DiagnosticsTests.cs` | +| Emitted code compiles without errors or warnings against the real `CheatEngine.SDK.Annotations`, `CheatEngine.SDK.Lua.Interop` and `CheatEngine.SDK.Lua`. | `Generator/EmissionTests.cs` | +| Editing one spec file re-emits only that file. An unrelated compilation edit recomputes nothing. | `Generator/IncrementalityTests.cs` | +| No parsed model in the pipeline holds a Roslyn object. | `Pipeline_step_values_hold_no_roslyn_objects` in `Generator/IncrementalityTests.cs` | +| Wrappers leave the Lua stack as they found it, allocate nothing on the warm success path, and throw `InvalidOperationException` while no runtime is attached. | `EndToEnd/MemoryScalarsEndToEndTests.cs`, run against stand-in Lua globals | ## Run the tests diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Emit/BootstrapEmitter.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Emit/BootstrapEmitter.cs index 6641af32..ffbb1dcd 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Emit/BootstrapEmitter.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Emit/BootstrapEmitter.cs @@ -95,8 +95,8 @@ public static SourceText Emit(BootstrapModel model) internal static string ChooseFactoryName(string fullyQualifiedPluginTypeName) { bool collides = fullyQualifiedPluginTypeName.StartsWith(QualifiedFactoryName, StringComparison.Ordinal) - && (fullyQualifiedPluginTypeName.Length == QualifiedFactoryName.Length - || fullyQualifiedPluginTypeName[QualifiedFactoryName.Length] == '.'); + && (fullyQualifiedPluginTypeName.Length == QualifiedFactoryName.Length + || fullyQualifiedPluginTypeName[QualifiedFactoryName.Length] == '.'); return collides ? AlternateFactoryName : FactoryName; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointContractSymbols.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointContractSymbols.cs index 8e008a51..7832ce47 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointContractSymbols.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointContractSymbols.cs @@ -93,7 +93,7 @@ public static EntryPointContractSymbols Resolve(Compilation compilation) foreach (MetadataReference reference in compilation.References) { if (compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly - && string.Equals(assembly.Identity.Name, assemblyName, StringComparison.Ordinal)) + && string.Equals(assembly.Identity.Name, assemblyName, StringComparison.Ordinal)) { return assembly.GetTypeByMetadataName(metadataName); } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointDeclaredDiagnosticIds.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointDeclaredDiagnosticIds.cs index 1e77ee26..5ba484e2 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointDeclaredDiagnosticIds.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointDeclaredDiagnosticIds.cs @@ -82,8 +82,8 @@ private static void CollectFrom( foreach (AttributeData attribute in attributes) { if (ReadDeclaredId(attribute, experimentalAttribute, obsoleteAttribute) is { } id - && IsUsableInPragma(id) - && (ids is null || !ids.Contains(id))) + && IsUsableInPragma(id) + && (ids is null || !ids.Contains(id))) { (ids ??= []).Add(id); } @@ -96,24 +96,24 @@ private static void CollectFrom( INamedTypeSymbol? obsoleteAttribute) { if (experimentalAttribute is not null - && SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, experimentalAttribute)) - // [Experimental(string diagnosticId)] + && SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, experimentalAttribute)) + // [Experimental(string diagnosticId)] { return attribute.ConstructorArguments.Length == 1 - && attribute.ConstructorArguments[0] is - { Kind: TypedConstantKind.Primitive, Value: string experimentalId } + && attribute.ConstructorArguments[0] is + { Kind: TypedConstantKind.Primitive, Value: string experimentalId } ? experimentalId : null; } if (obsoleteAttribute is not null - && SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, obsoleteAttribute)) - // [Obsolete(..., DiagnosticId = "ID")] + && SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, obsoleteAttribute)) + // [Obsolete(..., DiagnosticId = "ID")] { foreach (KeyValuePair argument in attribute.NamedArguments) { if (string.Equals(argument.Key, "DiagnosticId", StringComparison.Ordinal) - && argument.Value is { Kind: TypedConstantKind.Primitive, Value: string obsoleteId }) + && argument.Value is { Kind: TypedConstantKind.Primitive, Value: string obsoleteId }) { return obsoleteId; } @@ -129,7 +129,7 @@ private static void CollectFrom( private static bool IsUsableInPragma(string id) { return SyntaxFacts.IsValidIdentifier(id) - && SyntaxFacts.GetKeywordKind(id) == SyntaxKind.None - && SyntaxFacts.GetPreprocessorKeywordKind(id) == SyntaxKind.None; + && SyntaxFacts.GetKeywordKind(id) == SyntaxKind.None + && SyntaxFacts.GetPreprocessorKeywordKind(id) == SyntaxKind.None; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointGeneratedIdentity.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointGeneratedIdentity.cs index b32aaa9d..4620c2ca 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointGeneratedIdentity.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointGeneratedIdentity.cs @@ -29,8 +29,8 @@ public static bool HasEntryPointTypeCollision(Compilation compilation) foreach (INamedTypeSymbol type in @namespace.GetTypeMembers(ManagedEntryPointNames.TypeName)) { if (type.Arity == 0 - && !type.IsFileLocal - && SymbolEqualityComparer.Default.Equals(type.ContainingAssembly, compilation.Assembly)) + && !type.IsFileLocal + && SymbolEqualityComparer.Default.Equals(type.ContainingAssembly, compilation.Assembly)) { return true; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Emit/LuaObjectMembersFileEmitter.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Emit/LuaObjectMembersFileEmitter.cs index 11eef56a..7af12ef8 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Emit/LuaObjectMembersFileEmitter.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Emit/LuaObjectMembersFileEmitter.cs @@ -215,7 +215,7 @@ private static void WriteStackCheck(SourceWriter writer, LuaObjectMethodModel mo writer.Write('('); writer.Write(CSharpLiteral.ToStringLiteral( "The Lua stack could not grow by " + requiredSlots.ToString(CultureInfo.InvariantCulture) - + " slots to call '" + model.LuaName + "'.")); + + " slots to call '" + model.LuaName + "'.")); writer.WriteLine(");"); } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionModel.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionModel.cs index 4a6510f0..41dc2aa4 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionModel.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionModel.cs @@ -35,5 +35,5 @@ internal sealed record LuaFunctionModel( /// group). /// public bool IsValid => Issues == LuaFunctionShapeIssues.None && ContainingTypeIssues == ContainingTypeIssues.None && - Thunk is not null && !HasGeneratedIdentityCollision; + Thunk is not null && !HasGeneratedIdentityCollision; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionTables.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionTables.cs index d6b50a7f..203502fc 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionTables.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionTables.cs @@ -67,10 +67,7 @@ private static List AssignHintNames(List when a body can be emitted for this method. public bool IsValid => Issues == LuaGlobalShapeIssues.None && ContainingTypeIssues == ContainingTypeIssues.None && - Call is not null && !HasGeneratedIdentityCollision; + Call is not null && !HasGeneratedIdentityCollision; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaGlobalTables.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaGlobalTables.cs index d865efd9..8b4cf4b5 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaGlobalTables.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaGlobalTables.cs @@ -85,10 +85,7 @@ private static List AssignHintNames(List tables) for (int i = 0; i < tables.Count; i++) { string baseName = tables[i].ContainingType.HintBaseName; - tables[i] = tables[i] with - { - HintName = HintNames.AllocateUnique(baseName, HintSuffix, used) - }; + tables[i] = tables[i] with { HintName = HintNames.AllocateUnique(baseName, HintSuffix, used) }; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/ContainingTypeParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/ContainingTypeParser.cs index fa885b88..94a58a4f 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/ContainingTypeParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/ContainingTypeParser.cs @@ -75,7 +75,7 @@ private static bool IsReadOnly(INamedTypeSymbol type) foreach (SyntaxReference reference in type.DeclaringSyntaxReferences) { if (reference.GetSyntax() is TypeDeclarationSyntax declaration - && declaration.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) + && declaration.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) { return true; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaBindingsDeclaredDiagnosticIds.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaBindingsDeclaredDiagnosticIds.cs index 8d08bae3..ea7f0b3f 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaBindingsDeclaredDiagnosticIds.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaBindingsDeclaredDiagnosticIds.cs @@ -81,24 +81,24 @@ public static string Collect(IMethodSymbol method) } if (string.Equals(attributeClass.Name, "ExperimentalAttribute", StringComparison.Ordinal)) - // [Experimental(string diagnosticId)] + // [Experimental(string diagnosticId)] { return IsNamespace(attributeClass.ContainingNamespace, "System", "Diagnostics", "CodeAnalysis") - && attribute.ConstructorArguments.Length == 1 - && attribute.ConstructorArguments[0] is - { Kind: TypedConstantKind.Primitive, Value: string experimentalId } + && attribute.ConstructorArguments.Length == 1 + && attribute.ConstructorArguments[0] is + { Kind: TypedConstantKind.Primitive, Value: string experimentalId } ? experimentalId : null; } if (string.Equals(attributeClass.Name, "ObsoleteAttribute", StringComparison.Ordinal) - && IsNamespace(attributeClass.ContainingNamespace, "System")) - // [Obsolete(..., DiagnosticId = "ID")] + && IsNamespace(attributeClass.ContainingNamespace, "System")) + // [Obsolete(..., DiagnosticId = "ID")] { foreach (KeyValuePair argument in attribute.NamedArguments) { if (string.Equals(argument.Key, "DiagnosticId", StringComparison.Ordinal) - && argument.Value is { Kind: TypedConstantKind.Primitive, Value: string obsoleteId }) + && argument.Value is { Kind: TypedConstantKind.Primitive, Value: string obsoleteId }) { return obsoleteId; } @@ -130,7 +130,7 @@ private static bool IsNamespace(INamespaceSymbol? @namespace, params string[] na private static bool IsUsableInPragma(string id) { return SyntaxFacts.IsValidIdentifier(id) - && SyntaxFacts.GetKeywordKind(id) == SyntaxKind.None - && SyntaxFacts.GetPreprocessorKeywordKind(id) == SyntaxKind.None; + && SyntaxFacts.GetKeywordKind(id) == SyntaxKind.None + && SyntaxFacts.GetPreprocessorKeywordKind(id) == SyntaxKind.None; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaClassParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaClassParser.cs index 43a5d565..bf4789c0 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaClassParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaClassParser.cs @@ -27,7 +27,7 @@ public static LuaClassModel Parse(GeneratorAttributeSyntaxContext context, Cance string? luaName = LuaBindingSymbols.ReadSdkAttributeName(context.Attributes, compilation, LuaBindingsGenerator.LuaClassAttributeMetadataName); bool isValid = isSdkAttribute && LuaNames.IsValidName(luaName) - && IsBorrowedHandleShape(type, compilation, cancellationToken); + && IsBorrowedHandleShape(type, compilation, cancellationToken); return new LuaClassModel(ContainingTypeParser.Parse(type), luaName ?? string.Empty, isValid); } @@ -71,7 +71,7 @@ internal static bool IsGeneratedHandle(INamedTypeSymbol type, Compilation compil { ImmutableArray attributes = ImmutableArray.Create(attribute); if (LuaBindingSymbols.ContainsSdkAttribute(attributes, compilation, - LuaBindingsGenerator.LuaClassAttributeMetadataName)) + LuaBindingsGenerator.LuaClassAttributeMetadataName)) { return LuaNames.IsValidName(LuaBindingSymbols.ReadSdkAttributeName( attributes, @@ -89,7 +89,7 @@ private static bool IsReadOnlyStruct(INamedTypeSymbol type, CancellationToken ca { cancellationToken.ThrowIfCancellationRequested(); if (reference.GetSyntax(cancellationToken) is StructDeclarationSyntax declaration - && declaration.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) + && declaration.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) { return true; } @@ -103,10 +103,10 @@ private static bool IsReadOnlyStruct(INamedTypeSymbol type, CancellationToken ca private static bool HasGeneratedIdentityCollision(INamedTypeSymbol type, INamedTypeSymbol? ceObject) { return LuaClassGeneratedNames.IsGeneratedType(type.Name) - || HasGeneratedMember(type, ceObject) - || HasMember(type, "op_Equality") - || HasMember(type, "op_Inequality") - || HasCEObjectConstructor(type, ceObject); + || HasGeneratedMember(type, ceObject) + || HasMember(type, "op_Equality") + || HasMember(type, "op_Inequality") + || HasCEObjectConstructor(type, ceObject); } private static bool HasCEObjectConstructor(INamedTypeSymbol type, INamedTypeSymbol? ceObject) @@ -125,7 +125,7 @@ private static bool HasCEObjectConstructor(INamedTypeSymbol type, INamedTypeSymb IParameterSymbol parameter = constructor.Parameters[0]; if (parameter.RefKind == RefKind.None - && SymbolEqualityComparer.Default.Equals(parameter.Type, ceObject)) + && SymbolEqualityComparer.Default.Equals(parameter.Type, ceObject)) { return true; } @@ -139,7 +139,7 @@ private static bool HasGeneratedMember(INamedTypeSymbol type, INamedTypeSymbol? foreach (ISymbol member in type.GetMembers()) { if (LuaClassGeneratedNames.IsGeneratedMember(member.Name) - || LuaClassGeneratedNames.IsGeneratedAccessorCollision(member, ceObject)) + || LuaClassGeneratedNames.IsGeneratedAccessorCollision(member, ceObject)) { return true; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaFunctionParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaFunctionParser.cs index 650f51ab..eb683f80 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaFunctionParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaFunctionParser.cs @@ -66,13 +66,13 @@ private static bool HasGeneratedIdentityCollision(IMethodSymbol method, string? { INamedTypeSymbol type = method.ContainingType; if (type.GetMembers(LuaRegistrationEmitter.RegisterMethodName).Length != 0 - || type.GetMembers(LuaRegistrationEmitter.RegisterLeaseMethodName).Length != 0 - || type.GetMembers(LuaRegistrationEmitter.UnregisterMethodName).Length != 0) + || type.GetMembers(LuaRegistrationEmitter.RegisterLeaseMethodName).Length != 0 + || type.GetMembers(LuaRegistrationEmitter.UnregisterMethodName).Length != 0) { return true; } return LuaNames.IsValidName(luaName) - && type.GetMembers(LuaThunkModel.ThunkNameFor(luaName!)).Length != 0; + && type.GetMembers(LuaThunkModel.ThunkNameFor(luaName!)).Length != 0; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaGlobalParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaGlobalParser.cs index 9e1f92e2..48475c6f 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaGlobalParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaGlobalParser.cs @@ -159,6 +159,6 @@ private static bool HasGeneratedIdentityCollision(IMethodSymbol method, string? } return LuaNames.IsValidName(luaName) - && method.ContainingType.GetMembers(LuaGlobalCallModel.CacheFieldFor(luaName!)).Length != 0; + && method.ContainingType.GetMembers(LuaGlobalCallModel.CacheFieldFor(luaName!)).Length != 0; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs index e72de6bd..2ebd0d2d 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs @@ -38,17 +38,13 @@ public static LuaObjectMethodModel Parse(GeneratorAttributeSyntaxContext context bool described = TryDescribe(method, context.TargetNode as MethodDeclarationSyntax, out LuaObjectMethodModel model); bool valid = isSdkAttribute && LuaNames.IsValidName(luaName) - && LuaClassParser.IsGeneratedHandle(method.ContainingType, compilation, - cancellationToken) - && described; + && LuaClassParser.IsGeneratedHandle(method.ContainingType, compilation, + cancellationToken) + && described; if (valid) { - return model with - { - LuaName = luaName!, - IsValid = true - }; + return model with { LuaName = luaName!, IsValid = true }; } return new LuaObjectMethodModel( @@ -72,11 +68,11 @@ private static bool TryDescribe(IMethodSymbol method, MethodDeclarationSyntax? d ImmutableArray.CreateBuilder(method.Parameters.Length); ImmutableArray.Builder results = ImmutableArray.CreateBuilder(); bool valid = method.MethodKind == MethodKind.Ordinary - && !method.IsStatic - && method.IsPartialDefinition - && method.PartialImplementationPart is null - && !method.IsGenericMethod - && !method.IsAsync; + && !method.IsStatic + && method.IsPartialDefinition + && method.PartialImplementationPart is null + && !method.IsGenericMethod + && !method.IsAsync; valid &= DescribeParameters(method.Parameters, arguments, results); LuaCallForm form = results.Count == 0 ? LuaCallForm.Throwing : LuaCallForm.Try; @@ -107,7 +103,7 @@ private static bool DescribeParameters(ImmutableArray paramete foreach (IParameterSymbol parameter in parameters) { if (IsReserved(parameter.Name) || parameter.IsParams || parameter.IsOptional - || parameter.HasExplicitDefaultValue) + || parameter.HasExplicitDefaultValue) { valid = false; } @@ -116,7 +112,7 @@ private static bool DescribeParameters(ImmutableArray paramete { seenResult = true; if (!LuaValueKindMapper.TryMap(parameter.Type, out LuaValueKind kind, out bool nullable) - || !LuaValueKinds.CanBeResult(kind)) + || !LuaValueKinds.CanBeResult(kind)) { valid = false; } @@ -129,9 +125,9 @@ private static bool DescribeParameters(ImmutableArray paramete } if (parameter.RefKind != RefKind.None || seenResult - || !LuaValueKindMapper.TryMap(parameter.Type, - out LuaValueKind argumentKind, - out bool argumentNullable)) + || !LuaValueKindMapper.TryMap(parameter.Type, + out LuaValueKind argumentKind, + out bool argumentNullable)) { valid = false; } @@ -153,7 +149,7 @@ private static bool TryDescribeReturn(IMethodSymbol method, LuaCallForm form, ou if (form == LuaCallForm.Try) { return method.ReturnType.SpecialType == SpecialType.System_Boolean && !method.ReturnsByRef - && !method.ReturnsByRefReadonly; + && !method.ReturnsByRefReadonly; } if (method.ReturnsVoid) @@ -162,9 +158,9 @@ private static bool TryDescribeReturn(IMethodSymbol method, LuaCallForm form, ou } if (method.ReturnsByRef || method.ReturnsByRefReadonly - || !LuaValueKindMapper.TryMap(method.ReturnType, out LuaValueKind kind, - out returnNullable) - || !LuaValueKinds.CanBeResult(kind)) + || !LuaValueKindMapper.TryMap(method.ReturnType, out LuaValueKind kind, + out returnNullable) + || !LuaValueKinds.CanBeResult(kind)) { return false; } @@ -176,10 +172,10 @@ private static bool TryDescribeReturn(IMethodSymbol method, LuaCallForm form, ou private static bool IsReserved(string name) { return string.Equals(name, StateLocal, StringComparison.Ordinal) - || string.Equals(name, OperationLocal, StringComparison.Ordinal) - || string.Equals(name, TopLocal, StringComparison.Ordinal) - || string.Equals(name, StatusLocal, StringComparison.Ordinal) - || string.Equals(name, ResultLocal, StringComparison.Ordinal); + || string.Equals(name, OperationLocal, StringComparison.Ordinal) + || string.Equals(name, TopLocal, StringComparison.Ordinal) + || string.Equals(name, StatusLocal, StringComparison.Ordinal) + || string.Equals(name, ResultLocal, StringComparison.Ordinal); } private static string Modifiers(MethodDeclarationSyntax? declaration) diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs index 4af51e2a..0ea9598a 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs @@ -29,17 +29,13 @@ public static LuaObjectPropertyModel Parse(GeneratorAttributeSyntaxContext conte LuaBindingsGenerator.LuaPropertyAttributeMetadataName); bool described = TryDescribe(property, declaration, out LuaObjectPropertyModel model); bool valid = isSdkAttribute && LuaNames.IsValidName(luaName) - && LuaClassParser.IsGeneratedHandle(property.ContainingType, compilation, - cancellationToken) - && described; + && LuaClassParser.IsGeneratedHandle(property.ContainingType, compilation, + cancellationToken) + && described; if (valid) { - return model with - { - LuaName = luaName!, - IsValid = true - }; + return model with { LuaName = luaName!, IsValid = true }; } return new LuaObjectPropertyModel( @@ -63,7 +59,7 @@ private static bool TryDescribe(IPropertySymbol property, PropertyDeclarationSyn LuaValueKind kind; bool isNullable; bool typeIsSupported = LuaValueKindMapper.TryMap(property.Type, out kind, out isNullable) - && LuaValueKinds.CanBeResult(kind); + && LuaValueKinds.CanBeResult(kind); string modifiers; bool definitionIsSupported = IsSupportedDefinition(property, declaration, typeIsSupported, out modifiers); @@ -92,15 +88,15 @@ private static bool IsSupportedDefinition(IPropertySymbol property, PropertyDecl { modifiers = string.Empty; return declaration is not null - && !property.IsStatic - && !property.IsIndexer - && property.RefKind == RefKind.None - && declaration.Modifiers.Any(SyntaxKind.PartialKeyword) - && declaration.AccessorList is not null - && declaration.ExplicitInterfaceSpecifier is null - && property.PartialImplementationPart is null - && typeIsSupported - && TryModifiers(declaration, out modifiers); + && !property.IsStatic + && !property.IsIndexer + && property.RefKind == RefKind.None + && declaration.Modifiers.Any(SyntaxKind.PartialKeyword) + && declaration.AccessorList is not null + && declaration.ExplicitInterfaceSpecifier is null + && property.PartialImplementationPart is null + && typeIsSupported + && TryModifiers(declaration, out modifiers); } private static bool TryDescribeAccessors(PropertyDeclarationSyntax? declaration, out bool hasGetter, @@ -118,7 +114,7 @@ private static bool TryDescribeAccessors(PropertyDeclarationSyntax? declaration, foreach (AccessorDeclarationSyntax accessor in accessorList.Accessors) { if (!TryDescribeAccessor(accessor, ref hasGetter, ref getterModifiers, ref hasSetter, - ref setterModifiers)) + ref setterModifiers)) { return false; } @@ -131,7 +127,7 @@ private static bool TryDescribeAccessor(AccessorDeclarationSyntax accessor, ref ref string getterModifiers, ref bool hasSetter, ref string setterModifiers) { if (accessor.Body is not null || accessor.ExpressionBody is not null - || !TryAccessorModifiers(accessor, out string modifiers)) + || !TryAccessorModifiers(accessor, out string modifiers)) { return false; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/README.md b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/README.md index fe493eb5..be2cfeb7 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/README.md +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/README.md @@ -72,15 +72,15 @@ per function. `MyTrainer.Bindings.LuaGlobals.g.cs` holds one cached `LuaRef` per ## Supported shapes -| Lua type | C# types | Allowed as | -|-----------------------------|------------------------------------------------------------|--------------------------------------------------------------------------------| -| integer | `int`, `long`, `nuint` | arguments and results | -| number | `float`, `double` | arguments and results | -| boolean | `bool` | arguments and results | -| string | `string`, `string?` | arguments and results | -| string | `ReadOnlySpan` | arguments, and `[LuaFunction]` results | -| any of the above, or absent | `LuaOptional`, `T` one of the types above except spans | trailing `[LuaGlobal]` and `[LuaFunction]` arguments; trailing `out` results | -| several integers/numbers | `Span values, out int count`, `T` a scalar type above | the last results of an Outcome-form `[LuaGlobal]` | +| Lua type | C# types | Allowed as | +|-----------------------------|-----------------------------------------------------------|------------------------------------------------------------------------------| +| integer | `int`, `long`, `nuint` | arguments and results | +| number | `float`, `double` | arguments and results | +| boolean | `bool` | arguments and results | +| string | `string`, `string?` | arguments and results | +| string | `ReadOnlySpan` | arguments, and `[LuaFunction]` results | +| any of the above, or absent | `LuaOptional`, `T` one of the types above except spans | trailing `[LuaGlobal]` and `[LuaFunction]` arguments; trailing `out` results | +| several integers/numbers | `Span values, out int count`, `T` a scalar type above | the last results of an Outcome-form `[LuaGlobal]` | A `[LuaGlobal]` method has one of three forms: @@ -139,8 +139,8 @@ helper, as above. That keeps the public `int` API from receiving an unsigned val [`CESDK2011`](../../analyzers/docs/CESDK2011.md)). A variadic `Span values, out int count` pair is the last result of an Outcome form, one per method (`CESDK2011`). `LuaOptional` and `LuaOperationStatus` must be the SDK types; a look-alike with the same name is refused ([`CESDK2012`](../../analyzers/docs/CESDK2012.md)). -- `LuaOptional` is not supported on `[LuaMethod]` and `[LuaProperty]` members yet - ([`CESDK2013`](../../analyzers/docs/CESDK2013.md)), nor with `ReadOnlySpan`. +- `LuaOptional` is not supported on `[LuaMethod]` and `[LuaProperty]` members yet ([ + `CESDK2013`](../../analyzers/docs/CESDK2013.md)), nor with `ReadOnlySpan`. - Integer, 64-bit and address values never pass through a `double`: a float at or above 2^53 is refused, not rounded (see the marshaller policy of [`CheatEngine.SDK.Lua`](../../libs/CheatEngine.SDK.Lua/README.md)). - There are no table or object results: a table where a scalar is declared is `InvalidResult`. diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs index 1a4f4cf0..342e21fb 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs @@ -149,7 +149,7 @@ private static void ParseOperation( ref ulong bitmap) { if (!TryReadOperationFields(value, reader, diagnostics, out JsonString idValue, out JsonNumber opcodeValue, - out JsonString? managedConstant)) + out JsonString? managedConstant)) { return; } @@ -162,7 +162,7 @@ private static void ParseOperation( } if (managedConstant is not null && - !string.Equals(managedConstant.Text, idValue.Text + "Operation", StringComparison.Ordinal)) + !string.Equals(managedConstant.Text, idValue.Text + "Operation", StringComparison.Ordinal)) { diagnostics.Add(reader.CreateDiagnostic(managedConstant.Span, "Property 'managed.constant' must be '" + idValue.Text + "Operation' for operation '" + idValue.Text + @@ -170,8 +170,8 @@ private static void ParseOperation( } if (!int.TryParse(opcodeValue.Text, NumberStyles.None, CultureInfo.InvariantCulture, out int opcode) - || opcode < 0 - || opcode > 63) + || opcode < 0 + || opcode > 63) { diagnostics.Add(reader.CreateDiagnostic(opcodeValue.Span, "Operation 'opcode' must be an integer between 0 and 63.")); @@ -446,7 +446,7 @@ private static bool IsPascalIdentifier(string value) for (int i = 1; i < value.Length; i++) { char character = value[i]; - if (character is not ((>= 'A' and <= 'Z') or (>= 'a' and <= 'z') or (>= '0' and <= '9'))) + if (character is not (>= 'A' and <= 'Z' or >= 'a' and <= 'z' or >= '0' and <= '9')) { return false; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/GeneratedCodeText.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/GeneratedCodeText.cs index eb75fc03..a2925b84 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/GeneratedCodeText.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/GeneratedCodeText.cs @@ -76,9 +76,9 @@ public static string CreateGeneratedCodeAttribute(Type generatorType) AssemblyName assembly = generatorType.Assembly.GetName(); string version = (assembly.Version ?? new Version(0, 0, 0, 0)).ToString(); return "[global::System.CodeDom.Compiler.GeneratedCode(" - + CSharpLiteral.ToStringLiteral(assembly.Name ?? string.Empty) - + ", " - + CSharpLiteral.ToStringLiteral(version) - + ")]"; + + CSharpLiteral.ToStringLiteral(assembly.Name ?? string.Empty) + + ", " + + CSharpLiteral.ToStringLiteral(version) + + ")]"; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs index a89502bd..fc7a6c50 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs @@ -103,7 +103,7 @@ public static string AllocateUnique(string typeName, string suffix, HashSet= 'a' and <= 'z') or (>= 'A' and <= 'Z') or (>= '0' and <= '9') or '.' or '_') + if (c is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or >= '0' and <= '9' or '.' or '_') { builder.Append(c); } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/ContainingTypeShape.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/ContainingTypeShape.cs index 22fdeb27..ef0fb3bf 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/ContainingTypeShape.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/ContainingTypeShape.cs @@ -61,7 +61,7 @@ private static bool IsPartial(INamedTypeSymbol type, CancellationToken cancellat foreach (SyntaxReference reference in type.DeclaringSyntaxReferences) { if (reference.GetSyntax(cancellationToken) is TypeDeclarationSyntax declaration - && declaration.Modifiers.Any(SyntaxKind.PartialKeyword)) + && declaration.Modifiers.Any(SyntaxKind.PartialKeyword)) { return true; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/Identifiers.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/Identifiers.cs index 71173812..bd68372a 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/Identifiers.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/Identifiers.cs @@ -12,7 +12,7 @@ internal static class Identifiers public static string Escape(string name) { return SyntaxFacts.GetKeywordKind(name) != SyntaxKind.None || - SyntaxFacts.GetContextualKeywordKind(name) != SyntaxKind.None + SyntaxFacts.GetContextualKeywordKind(name) != SyntaxKind.None ? "@" + name : name; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaClassGeneratedNames.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaClassGeneratedNames.cs index e78f1a1f..9c3397e8 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaClassGeneratedNames.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaClassGeneratedNames.cs @@ -28,12 +28,12 @@ public static bool IsGeneratedAccessorCollision(ISymbol member, INamedTypeSymbol } return method.MethodKind == MethodKind.Ordinary - && ((string.Equals(method.Name, "get_Handle", StringComparison.Ordinal) - && method.Parameters.Length == 0) - || (string.Equals(method.Name, "set_Handle", StringComparison.Ordinal) - && ceObject is not null - && method.Parameters.Length == 1 - && method.Parameters[0].RefKind == RefKind.None - && SymbolEqualityComparer.Default.Equals(method.Parameters[0].Type, ceObject))); + && ((string.Equals(method.Name, "get_Handle", StringComparison.Ordinal) + && method.Parameters.Length == 0) + || (string.Equals(method.Name, "set_Handle", StringComparison.Ordinal) + && ceObject is not null + && method.Parameters.Length == 1 + && method.Parameters[0].RefKind == RefKind.None + && SymbolEqualityComparer.Default.Equals(method.Parameters[0].Type, ceObject))); } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaContractTypes.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaContractTypes.cs index 2a23ffac..1370cd95 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaContractTypes.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaContractTypes.cs @@ -59,8 +59,8 @@ internal static class LuaContractTypes public static bool Is(ITypeSymbol type, INamedTypeSymbol? expected) { return expected is not null - && type is INamedTypeSymbol named - && SymbolEqualityComparer.Default.Equals(named.OriginalDefinition, expected); + && type is INamedTypeSymbol named + && SymbolEqualityComparer.Default.Equals(named.OriginalDefinition, expected); } /// @@ -70,8 +70,8 @@ public static bool Is(ITypeSymbol type, INamedTypeSymbol? expected) public static bool IsLookAlike(ITypeSymbol type, INamedTypeSymbol? expected, string metadataName) { return type is INamedTypeSymbol named - && !Is(type, expected) - && HasMetadataName(named.OriginalDefinition, metadataName); + && !Is(type, expected) + && HasMetadataName(named.OriginalDefinition, metadataName); } /// Whether a top-level has the full metadata name . @@ -114,6 +114,6 @@ public static bool HasMetadataName(INamedTypeSymbol type, string metadataName) private static bool NameEquals(string name, string metadataName, int start, int end) { return name.Length == end - start - && string.CompareOrdinal(name, 0, metadataName, start, name.Length) == 0; + && string.CompareOrdinal(name, 0, metadataName, start, name.Length) == 0; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaFunctionShape.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaFunctionShape.cs index ff76412a..556cf5b3 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaFunctionShape.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaFunctionShape.cs @@ -205,8 +205,8 @@ private static LuaFunctionShapeIssues AddRequiredArgument(Compilation? compilati INamedTypeSymbol? luaMarshallerContract, ImmutableArray.Builder builder) { if (!LuaMarshallerResolver.TryResolve(compilation, method.ContainingType, parameter.Type, - parameter.GetAttributes(), luaMarshallerAttribute, luaMarshallerContract, - out LuaCustomMarshallerModel? customMarshaller, out _)) + parameter.GetAttributes(), luaMarshallerAttribute, luaMarshallerContract, + out LuaCustomMarshallerModel? customMarshaller, out _)) { return LuaFunctionShapeIssues.UnsupportedParameterType; } @@ -255,9 +255,9 @@ private static LuaFunctionShapeIssues InspectReturn(Compilation? compilation, IM } if (!LuaMarshallerResolver.TryResolve(compilation, method.ContainingType, method.ReturnType, - method.GetReturnTypeAttributes(), luaMarshallerAttribute, luaMarshallerContract, - out returnMarshaller, out _) - || (returnMarshaller is not null && method.ReturnType.IsRefLikeType)) + method.GetReturnTypeAttributes(), luaMarshallerAttribute, luaMarshallerContract, + out returnMarshaller, out _) + || (returnMarshaller is not null && method.ReturnType.IsRefLikeType)) { return LuaFunctionShapeIssues.UnsupportedReturnType; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaGlobalShape.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaGlobalShape.cs index 75182c9f..2864efbb 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaGlobalShape.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaGlobalShape.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; @@ -194,7 +193,7 @@ private static LuaGlobalShapeIssues InspectReturn(Compilation? compilation, IMet } if (LuaContractTypes.IsLookAlike(method.ReturnType, contracts.LuaOperationStatus, - LuaContractTypes.LuaOperationStatusMetadataName)) + LuaContractTypes.LuaOperationStatusMetadataName)) { return LuaGlobalShapeIssues.LookAlikeContractType; } @@ -240,9 +239,9 @@ private static LuaGlobalShapeIssues InspectThrowingReturn(Compilation? compilati } if (!LuaMarshallerResolver.TryResolve(compilation, method.ContainingType, method.ReturnType, - method.GetReturnTypeAttributes(), contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, - out returnMarshaller, out _) - || (returnMarshaller is not null && method.ReturnType.IsRefLikeType)) + method.GetReturnTypeAttributes(), contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, + out returnMarshaller, out _) + || (returnMarshaller is not null && method.ReturnType.IsRefLikeType)) { return LuaGlobalShapeIssues.UnsupportedReturnType; } @@ -253,7 +252,7 @@ private static LuaGlobalShapeIssues InspectThrowingReturn(Compilation? compilati } if (!LuaValueKindMapper.TryMap(method.ReturnType, out LuaValueKind kind, out returnIsNullable) || - !LuaValueKinds.CanBeResult(kind)) + !LuaValueKinds.CanBeResult(kind)) { return LuaGlobalShapeIssues.UnsupportedReturnType; } @@ -430,9 +429,9 @@ private LuaGlobalShapeIssues AddOutResult(IParameterSymbol parameter) } if (!LuaMarshallerResolver.TryResolve(compilation, bindingType, parameter.Type, parameter.GetAttributes(), - contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, - out LuaCustomMarshallerModel? customMarshaller, out _) - || (customMarshaller is not null && parameter.Type.IsRefLikeType)) + contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, + out LuaCustomMarshallerModel? customMarshaller, out _) + || (customMarshaller is not null && parameter.Type.IsRefLikeType)) { return issues | LuaGlobalShapeIssues.UnsupportedResultType; } @@ -444,7 +443,7 @@ private LuaGlobalShapeIssues AddOutResult(IParameterSymbol parameter) } if (!LuaValueKindMapper.TryMap(parameter.Type, out LuaValueKind kind, out bool isNullable) || - !LuaValueKinds.CanBeResult(kind)) + !LuaValueKinds.CanBeResult(kind)) { return issues | LuaGlobalShapeIssues.UnsupportedResultType; } @@ -458,8 +457,8 @@ private LuaGlobalShapeIssues AddCopyOutResult(ImmutableArray p { LuaGlobalShapeIssues issues = EnterResult(false); if (index + 1 >= parameters.Length - || parameters[index + 1] is - not { RefKind: RefKind.Out, Type.SpecialType: SpecialType.System_Int32 } written) + || parameters[index + 1] is + not { RefKind: RefKind.Out, Type.SpecialType: SpecialType.System_Int32 } written) { return issues | LuaGlobalShapeIssues.UnsupportedResultType; } @@ -483,8 +482,8 @@ private LuaGlobalShapeIssues AddVariadicResult(ImmutableArray HasVariadicResult = true; if (index + 1 >= parameters.Length - || parameters[index + 1] is - not { RefKind: RefKind.Out, Type.SpecialType: SpecialType.System_Int32 } count) + || parameters[index + 1] is + not { RefKind: RefKind.Out, Type.SpecialType: SpecialType.System_Int32 } count) { return issues | LuaGlobalShapeIssues.UnsupportedResultType; } @@ -492,7 +491,7 @@ private LuaGlobalShapeIssues AddVariadicResult(ImmutableArray IParameterSymbol values = parameters[index]; index++; if (!LuaValueKindMapper.TryMap(element, out LuaValueKind kind, out _) - || !LuaValueKinds.CanBeVariadicElement(kind)) + || !LuaValueKinds.CanBeVariadicElement(kind)) { return issues | LuaGlobalShapeIssues.UnsupportedVariadicElement; } @@ -542,8 +541,8 @@ private LuaGlobalShapeIssues AddArgument(IParameterSymbol parameter, int index) } if (!LuaMarshallerResolver.TryResolve(compilation, bindingType, parameter.Type, parameter.GetAttributes(), - contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, - out LuaCustomMarshallerModel? customMarshaller, out _)) + contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, + out LuaCustomMarshallerModel? customMarshaller, out _)) { return issues | LuaGlobalShapeIssues.UnsupportedParameterType; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaMarshallerResolver.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaMarshallerResolver.cs index b866c2d5..fe7cd52d 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaMarshallerResolver.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaMarshallerResolver.cs @@ -57,7 +57,7 @@ public static bool TryResolve(Compilation? compilation, INamedTypeSymbol binding } if (!Implements(type, marshallerContract, valueType) - || !HasCallableStaticContract(compilation, bindingType, type, marshallerContract, valueType)) + || !HasCallableStaticContract(compilation, bindingType, type, marshallerContract, valueType)) { return false; } @@ -74,7 +74,7 @@ private static bool Implements(INamedTypeSymbol candidate, INamedTypeSymbol cont foreach (INamedTypeSymbol implementation in candidate.AllInterfaces) { if (!SymbolEqualityComparer.Default.Equals(implementation.OriginalDefinition, contract) - || implementation.TypeArguments.Length != 1) + || implementation.TypeArguments.Length != 1) { continue; } @@ -101,7 +101,7 @@ private static bool HasCallableStaticContract(Compilation? compilation, INamedTy INamedTypeSymbol closedContract = contract.Construct(valueType); return HasCallableStaticMethod(compilation, bindingType, candidate, closedContract, "Push") - && HasCallableStaticMethod(compilation, bindingType, candidate, closedContract, "TryRead"); + && HasCallableStaticMethod(compilation, bindingType, candidate, closedContract, "TryRead"); } private static bool HasCallableStaticMethod(Compilation? compilation, INamedTypeSymbol bindingType, @@ -125,12 +125,12 @@ private static bool HasCallableStaticMethod(Compilation? compilation, INamedType foreach (ISymbol member in candidate.GetMembers(name)) { if (member is not IMethodSymbol method - || method.MethodKind != MethodKind.Ordinary - || !method.IsStatic - || method.IsAbstract - || method.Arity != 0 - || (compilation is not null && !compilation.IsSymbolAccessibleWithin(method, bindingType)) - || !HasMatchingSignature(method, required)) + || method.MethodKind != MethodKind.Ordinary + || !method.IsStatic + || method.IsAbstract + || method.Arity != 0 + || (compilation is not null && !compilation.IsSymbolAccessibleWithin(method, bindingType)) + || !HasMatchingSignature(method, required)) { continue; } @@ -144,8 +144,8 @@ private static bool HasCallableStaticMethod(Compilation? compilation, INamedType private static bool HasMatchingSignature(IMethodSymbol candidate, IMethodSymbol required) { if (candidate.ReturnsVoid != required.ReturnsVoid - || !SymbolEqualityComparer.Default.Equals(candidate.ReturnType, required.ReturnType) - || candidate.Parameters.Length != required.Parameters.Length) + || !SymbolEqualityComparer.Default.Equals(candidate.ReturnType, required.ReturnType) + || candidate.Parameters.Length != required.Parameters.Length) { return false; } @@ -155,7 +155,7 @@ private static bool HasMatchingSignature(IMethodSymbol candidate, IMethodSymbol IParameterSymbol actual = candidate.Parameters[i]; IParameterSymbol expected = required.Parameters[i]; if (actual.RefKind != expected.RefKind - || !SymbolEqualityComparer.Default.Equals(actual.Type, expected.Type)) + || !SymbolEqualityComparer.Default.Equals(actual.Type, expected.Type)) { return false; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaValueKindMapper.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaValueKindMapper.cs index 793432c6..d88a1bf1 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaValueKindMapper.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaValueKindMapper.cs @@ -77,7 +77,10 @@ public static bool TryMap(ITypeSymbol type, out LuaValueKind kind, out bool isNu /// an optional, so object members ([LuaMethod], [LuaProperty]) keep refusing it. /// /// The parameter, result or return type. - /// The resolved CheatEngine.SDK.Lua.Marshalling.LuaOptional`1, or . + /// + /// The resolved CheatEngine.SDK.Lua.Marshalling.LuaOptional`1, or + /// . + /// /// The kind of T when the result is . public static LuaOptionalUse ClassifyOptional(ITypeSymbol type, INamedTypeSymbol? luaOptional, out LuaValueKind inner) @@ -99,15 +102,18 @@ public static LuaOptionalUse ClassifyOptional(ITypeSymbol type, INamedTypeSymbol : LuaOptionalUse.Unsupported; } - /// Whether is System.Span<T> for a T other than . + /// + /// Whether is System.Span<T> for a T other than + /// . + /// /// The parameter type. /// The element type when the result is . public static bool IsSpanOfOther(ITypeSymbol type, [NotNullWhen(true)] out ITypeSymbol? element) { if (type is INamedTypeSymbol { Arity: 1, ContainingType: null } named - && string.Equals(named.Name, "Span", StringComparison.Ordinal) - && named.ContainingNamespace is { Name: "System", ContainingNamespace.IsGlobalNamespace: true } - && named.TypeArguments[0].SpecialType != SpecialType.System_Byte) + && string.Equals(named.Name, "Span", StringComparison.Ordinal) + && named.ContainingNamespace is { Name: "System", ContainingNamespace.IsGlobalNamespace: true } + && named.TypeArguments[0].SpecialType != SpecialType.System_Byte) { element = named.TypeArguments[0]; return true; @@ -138,8 +144,8 @@ public static bool IsSpanOfByte(ITypeSymbol type) private static bool IsSystemSpanOfByte(ITypeSymbol type, string name) { return type is INamedTypeSymbol { Arity: 1, ContainingType: null } named - && string.Equals(named.Name, name, StringComparison.Ordinal) - && named.TypeArguments[0].SpecialType == SpecialType.System_Byte - && named.ContainingNamespace is { Name: "System", ContainingNamespace.IsGlobalNamespace: true }; + && string.Equals(named.Name, name, StringComparison.Ordinal) + && named.TypeArguments[0].SpecialType == SpecialType.System_Byte + && named.ContainingNamespace is { Name: "System", ContainingNamespace.IsGlobalNamespace: true }; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaArgumentModel.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaArgumentModel.cs index e8e5ae51..131f9a09 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaArgumentModel.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaArgumentModel.cs @@ -59,12 +59,6 @@ public LuaArgumentModel(string name, LuaValueKind kind, bool isNullable, bool is { } - /// An optional LuaOptional<T> argument of a built-in kind. - public static LuaArgumentModel Optional(string name, LuaValueKind kind) - { - return new LuaArgumentModel(name, kind, false, IsOptional: true); - } - /// Whether this value is pushed directly instead of being supplied by a wrapper parameter. public bool IsFixed => FixedValue is not null; @@ -83,4 +77,10 @@ public static LuaArgumentModel Optional(string name, LuaValueKind kind) /// The Lua-facing expected type in a generated bad-argument message. public string ExpectedArgumentTypeName => CustomMarshaller?.ExpectedTypeName ?? LuaValueKinds.ExpectedArgument(Kind); + + /// An optional LuaOptional<T> argument of a built-in kind. + public static LuaArgumentModel Optional(string name, LuaValueKind kind) + { + return new LuaArgumentModel(name, kind, false, IsOptional: true); + } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallEmitter.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallEmitter.cs index 873f06f4..08bc4200 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallEmitter.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallEmitter.cs @@ -365,7 +365,7 @@ private static void WriteArgumentCount(SourceWriter writer, LuaGlobalCallModel m public static string OmittedBeforePresentMessage(string globalName, string parameterName) { return "The optional argument '" + parameterName + "' of the Lua global '" + globalName + - "' is omitted while a later optional argument is present; Lua cannot receive an argument after an absent one. Pass LuaOptional.Nil() to send nil in its place."; + "' is omitted while a later optional argument is present; Lua cannot receive an argument after an absent one. Pass LuaOptional.Nil() to send nil in its place."; } private static string UnescapedName(string name) @@ -896,7 +896,7 @@ private static void WriteThrowingCall(SourceWriter writer, LuaGlobalCallModel mo private static void WriteThrowingResult(SourceWriter writer, LuaGlobalCallModel model) { if (!model.HasReturn) - // A void call keeps no result: the successful call already left the stack at its recorded top. + // A void call keeps no result: the successful call already left the stack at its recorded top. { return; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallModel.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallModel.cs index 4efdd097..039b5a12 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallModel.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallModel.cs @@ -149,15 +149,15 @@ public int RequiredResultCount /// The concrete static marshaller for the throwing-form return value. public string ReturnMarshallerTypeName => ReturnMarshaller?.MarshallerTypeName ?? - LuaValueKinds.MarshallerTypeName(ReturnKind!.Value); + LuaValueKinds.MarshallerTypeName(ReturnKind!.Value); /// The C# type spelling for the generated return and result local. public string ReturnTypeName => ReturnMarshaller?.ValueTypeName ?? - LuaValueKinds.TypeName(ReturnKind!.Value, ReturnIsNullable); + LuaValueKinds.TypeName(ReturnKind!.Value, ReturnIsNullable); /// The Lua-facing expected type for a throwing-form result failure. public string ExpectedReturnTypeName => ReturnMarshaller?.ExpectedTypeName ?? - LuaValueKinds.ExpectedResult(ReturnKind!.Value); + LuaValueKinds.ExpectedResult(ReturnKind!.Value); /// Whether the body reads the state from rather than from the runtime. public bool TakesState => StateParameterName.Length > 0; diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs index e8da28ef..23ce6c45 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs @@ -61,7 +61,7 @@ public static bool IsReservedWord(string name) private static bool IsIdentifierStart(char c) { - return c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '_'; + return c is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or '_'; } private static bool IsIdentifierPart(char c) diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaResultModel.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaResultModel.cs index a2bf7deb..9368bc61 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaResultModel.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaResultModel.cs @@ -64,7 +64,7 @@ public LuaResultModel(LuaResultShape shape, LuaValueKind kind, string name, bool /// reference type (an optional result is a struct, a copy-out or variadic count is an ). /// public bool IsReferenceType => Shape == LuaResultShape.Value && - (CustomMarshaller?.IsReferenceType ?? LuaValueKinds.IsReferenceType(Kind)); + (CustomMarshaller?.IsReferenceType ?? LuaValueKinds.IsReferenceType(Kind)); /// Whether the protected call must keep every result and read the factual count. public bool IsDynamic => Shape is LuaResultShape.Optional or LuaResultShape.Variadic; diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkEmitter.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkEmitter.cs index ae08b987..22edfd22 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkEmitter.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkEmitter.cs @@ -101,7 +101,7 @@ public static void Emit(SourceWriter writer, LuaThunkModel model) public static string WrongArgumentCountMessage(string luaName, int expected) { return "wrong number of arguments to '" + luaName + "' (" + expected.ToString(CultureInfo.InvariantCulture) + - " expected)"; + " expected)"; } /// diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkModel.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkModel.cs index 1d9a6209..059f36e6 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkModel.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkModel.cs @@ -73,7 +73,7 @@ public int RequiredArgumentCount /// The concrete static marshaller for the return value. public string ReturnMarshallerTypeName => ReturnMarshaller?.MarshallerTypeName ?? - LuaValueKinds.MarshallerTypeName(ReturnKind!.Value); + LuaValueKinds.MarshallerTypeName(ReturnKind!.Value); /// The C# type spelling for the generated result local. public string ReturnTypeName => ReturnMarshaller?.ValueTypeName ?? LuaValueKinds.TypeName(ReturnKind!.Value, true); diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/Shapes/PluginShape.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/Shapes/PluginShape.cs index 1dde5b55..98d6924b 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/Shapes/PluginShape.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/Shapes/PluginShape.cs @@ -124,8 +124,8 @@ public static PluginShapeIssues Inspect( parameterlessConstructor = null; if (type.IsStatic) - // A static class is also abstract and sealed in metadata, has no base class and no instance - // constructor: one message instead of four. + // A static class is also abstract and sealed in metadata, has no base class and no instance + // constructor: one message instead of four. { return issues | PluginShapeIssues.Static; } @@ -229,8 +229,8 @@ private static bool DerivesFromPluginBase(INamedTypeSymbol type, INamedTypeSymbo for (INamedTypeSymbol? current = type.BaseType; current is not null; current = current.BaseType) { if (pluginBase is null - ? IsPluginBaseFallback(current) - : SymbolEqualityComparer.Default.Equals(current, pluginBase)) + ? IsPluginBaseFallback(current) + : SymbolEqualityComparer.Default.Equals(current, pluginBase)) { return true; } @@ -329,7 +329,7 @@ private static bool HasRequiredMembers(INamedTypeSymbol type) for (INamedTypeSymbol? current = type; current is not null; current = current.BaseType) { if (current.GetMembers().Any(static member => - member is IPropertySymbol { IsRequired: true } or IFieldSymbol { IsRequired: true })) + member is IPropertySymbol { IsRequired: true } or IFieldSymbol { IsRequired: true })) { return true; } diff --git a/src/CheatEngine.SDK/CompatibilitySuppressions.xml b/src/CheatEngine.SDK/CompatibilitySuppressions.xml index bbb20b27..081ac12d 100644 --- a/src/CheatEngine.SDK/CompatibilitySuppressions.xml +++ b/src/CheatEngine.SDK/CompatibilitySuppressions.xml @@ -1,67 +1,71 @@ - - - CP0002 - F:CheatEngine.SDK.Abi.Native.AddressListPluginInit.Callback - lib/net10.0/CheatEngine.SDK.Abi.dll - lib/net10.0/CheatEngine.SDK.Abi.dll - true - - - CP0002 - F:CheatEngine.SDK.Abi.Native.DisassemblerContextPluginInit.Callback - lib/net10.0/CheatEngine.SDK.Abi.dll - lib/net10.0/CheatEngine.SDK.Abi.dll - true - - - CP0002 - M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.#ctor(System.Boolean,System.Boolean) - lib/net10.0/CheatEngine.SDK.Engine.dll - lib/net10.0/CheatEngine.SDK.Engine.dll - true - - - CP0002 - M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.Deconstruct(System.Boolean@,System.Boolean@) - lib/net10.0/CheatEngine.SDK.Engine.dll - lib/net10.0/CheatEngine.SDK.Engine.dll - true - - - CP0002 - M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.get_UseHostSymbolTable - lib/net10.0/CheatEngine.SDK.Engine.dll - lib/net10.0/CheatEngine.SDK.Engine.dll - true - - - CP0002 - M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.set_UseHostSymbolTable(System.Boolean) - lib/net10.0/CheatEngine.SDK.Engine.dll - lib/net10.0/CheatEngine.SDK.Engine.dll - true - - - CP0011 - F:CheatEngine.SDK.Engine.Memory.MemoryAccessFailure.DestinationTooSmall - lib/net10.0/CheatEngine.SDK.Engine.dll - lib/net10.0/CheatEngine.SDK.Engine.dll - true - - - CP0011 - F:CheatEngine.SDK.Engine.Memory.MemoryAccessFailure.InvalidResult - lib/net10.0/CheatEngine.SDK.Engine.dll - lib/net10.0/CheatEngine.SDK.Engine.dll - true - - - CP0011 - F:CheatEngine.SDK.Engine.Memory.MemoryAccessFailure.WriteFailed - lib/net10.0/CheatEngine.SDK.Engine.dll - lib/net10.0/CheatEngine.SDK.Engine.dll - true - - \ No newline at end of file + + + CP0002 + F:CheatEngine.SDK.Abi.Native.AddressListPluginInit.Callback + lib/net10.0/CheatEngine.SDK.Abi.dll + lib/net10.0/CheatEngine.SDK.Abi.dll + true + + + CP0002 + F:CheatEngine.SDK.Abi.Native.DisassemblerContextPluginInit.Callback + lib/net10.0/CheatEngine.SDK.Abi.dll + lib/net10.0/CheatEngine.SDK.Abi.dll + true + + + CP0002 + M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.#ctor(System.Boolean,System.Boolean) + + lib/net10.0/CheatEngine.SDK.Engine.dll + lib/net10.0/CheatEngine.SDK.Engine.dll + true + + + CP0002 + + M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.Deconstruct(System.Boolean@,System.Boolean@) + + lib/net10.0/CheatEngine.SDK.Engine.dll + lib/net10.0/CheatEngine.SDK.Engine.dll + true + + + CP0002 + M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.get_UseHostSymbolTable + lib/net10.0/CheatEngine.SDK.Engine.dll + lib/net10.0/CheatEngine.SDK.Engine.dll + true + + + CP0002 + M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.set_UseHostSymbolTable(System.Boolean) + + lib/net10.0/CheatEngine.SDK.Engine.dll + lib/net10.0/CheatEngine.SDK.Engine.dll + true + + + CP0011 + F:CheatEngine.SDK.Engine.Memory.MemoryAccessFailure.DestinationTooSmall + lib/net10.0/CheatEngine.SDK.Engine.dll + lib/net10.0/CheatEngine.SDK.Engine.dll + true + + + CP0011 + F:CheatEngine.SDK.Engine.Memory.MemoryAccessFailure.InvalidResult + lib/net10.0/CheatEngine.SDK.Engine.dll + lib/net10.0/CheatEngine.SDK.Engine.dll + true + + + CP0011 + F:CheatEngine.SDK.Engine.Memory.MemoryAccessFailure.WriteFailed + lib/net10.0/CheatEngine.SDK.Engine.dll + lib/net10.0/CheatEngine.SDK.Engine.dll + true + + diff --git a/src/CheatEngine.SDK/README.md b/src/CheatEngine.SDK/README.md index 6c9f6aeb..04b786a8 100644 --- a/src/CheatEngine.SDK/README.md +++ b/src/CheatEngine.SDK/README.md @@ -128,19 +128,21 @@ graph with Native AOT. A successful probe establishes only the analysed graph an Cheat Engine plugin and says nothing about whether CE can host or unload a Native AOT artifact. **A NativeAOT publish success is never a Cheat Engine load success.** -| Profile | Status | -|---|---| -| Historical CLR route (`MSCorEE.dll` hosting, string entry point) | Documentary only, not supported | -| Managed hostfxr route (`CESDK.CESDK.CEPluginInitialize(IntPtr, int)`) | The only supported profile | -| NativeAOT plugin DLL | Not supported | -| Classic native plugin exporting `CEPlugin_*` | Not provided by the SDK | -| x86 or ARM64 host | Not supported | +| Profile | Status | +|-----------------------------------------------------------------------|---------------------------------| +| Historical CLR route (`MSCorEE.dll` hosting, string entry point) | Documentary only, not supported | +| Managed hostfxr route (`CESDK.CESDK.CEPluginInitialize(IntPtr, int)`) | The only supported profile | +| NativeAOT plugin DLL | Not supported | +| Classic native plugin exporting `CEPlugin_*` | Not provided by the SDK | +| x86 or ARM64 host | Not supported | Cheat Engine's native loader removes a plugin with -`FreeLibrary`, and [Microsoft's Native AOT library guidance](https://learn.microsoft.com/dotnet/core/deploying/native-aot/libraries) +`FreeLibrary`, +and [Microsoft's Native AOT library guidance](https://learn.microsoft.com/dotnet/core/deploying/native-aot/libraries) states that .NET does not support unloading a NativeAOT library that way; only `UnmanagedCallersOnly` methods of the published assembly become native exports, so the package itself can never add classic `CEPlugin_*` exports for a -consumer. See the [full restrictions, evidence and diagnostics](https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/libs/CheatEngine.SDK.Abi/README.md) +consumer. See +the [full restrictions, evidence and diagnostics](https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/libs/CheatEngine.SDK.Abi/README.md) (`CESDK9102`, `CESDK0006`). ## Requirements diff --git a/tests/CheatEngine.SDK.Abi.Tests/AbiBoundaryValueTests.cs b/tests/CheatEngine.SDK.Abi.Tests/AbiBoundaryValueTests.cs index df43b2a7..eaf4a97b 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/AbiBoundaryValueTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/AbiBoundaryValueTests.cs @@ -35,7 +35,8 @@ public void Bool32_results_2_and_0xFFFFFFFF_read_as_true_through_every_lifecycle (delegate* unmanaged[Stdcall]) &RawGetVersion; record.EnablePlugin = (delegate* unmanaged[Stdcall]) (delegate* unmanaged[Stdcall]) &RawEnablePlugin; - record.DisablePlugin = (delegate* unmanaged[Stdcall]) (delegate* unmanaged[Stdcall]) &RawDisablePlugin; + record.DisablePlugin = + (delegate* unmanaged[Stdcall]) (delegate* unmanaged[Stdcall]) &RawDisablePlugin; AssertTrueWithRawBits(record.GetVersion(&version, sizeof(PluginVersion)), raw); AssertTrueWithRawBits(record.EnablePlugin(&managedExports, 7u), raw); @@ -153,7 +154,8 @@ private static int RawDisablePlugin() } [UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])] - private static Bool32 SwapMemoryViewAddresses(nuint* disassemblerAddress, nuint* selectedAddress, nuint* hexViewAddress) + private static Bool32 SwapMemoryViewAddresses(nuint* disassemblerAddress, nuint* selectedAddress, + nuint* hexViewAddress) { _ = selectedAddress; (*disassemblerAddress, *hexViewAddress) = (*hexViewAddress, *disassemblerAddress); diff --git a/tests/CheatEngine.SDK.Abi.Tests/AssemblyConformanceTests.cs b/tests/CheatEngine.SDK.Abi.Tests/AssemblyConformanceTests.cs index fbabec3c..27ec70e6 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/AssemblyConformanceTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/AssemblyConformanceTests.cs @@ -75,7 +75,8 @@ public void Assembly_references_no_other_cheatengine_sdk_assembly() [Fact] public void Every_structure_is_listed_in_the_expected_size_table() { - string[] actual = AbiStructures.All().Select(static type => type.FullName!).Order(StringComparer.Ordinal).ToArray(); + string[] actual = AbiStructures.All().Select(static type => type.FullName!).Order(StringComparer.Ordinal) + .ToArray(); string[] expected = ExpectedSizesOn64Bit.Keys.Order(StringComparer.Ordinal).ToArray(); Assert.Equal(expected, actual); @@ -100,7 +101,8 @@ public void Every_structure_including_internal_and_nested_ones_has_the_expected_ public void Public_structures_are_a_subset_of_the_gated_structures() { Assert.All(PublicStructures(), - static type => Assert.True(ExpectedSizesOn64Bit.ContainsKey(type.FullName!), $"{type.FullName} is not gated.")); + static type => Assert.True(ExpectedSizesOn64Bit.ContainsKey(type.FullName!), + $"{type.FullName} is not gated.")); } [Fact] diff --git a/tests/CheatEngine.SDK.Abi.Tests/FieldLayout/FieldLayoutContractTests.cs b/tests/CheatEngine.SDK.Abi.Tests/FieldLayout/FieldLayoutContractTests.cs index a0646729..f41c44be 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/FieldLayout/FieldLayoutContractTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/FieldLayout/FieldLayoutContractTests.cs @@ -48,7 +48,8 @@ public void Every_instance_field_of_every_abi_structure_has_a_layout_row() [Fact] public void Every_layout_row_names_an_existing_field() { - Dictionary structures = AbiStructures.All().ToDictionary(static type => type.FullName!, StringComparer.Ordinal); + Dictionary structures = + AbiStructures.All().ToDictionary(static type => type.FullName!, StringComparer.Ordinal); List stale = []; HashSet<(string, string)> seen = []; @@ -59,7 +60,7 @@ public void Every_layout_row_names_an_existing_field() stale.Add($"{row.TypeFullName}.{row.FieldName} (duplicate)"); } else if (!structures.TryGetValue(row.TypeFullName, out Type? structure) || - structure.GetField(row.FieldName, FieldLayoutGate.InstanceFields) is null) + structure.GetField(row.FieldName, FieldLayoutGate.InstanceFields) is null) { stale.Add($"{row.TypeFullName}.{row.FieldName}"); } @@ -145,7 +146,8 @@ public void Reflected_offsets_agree_with_address_of_offsets_for_the_packed_init_ PluginInitRecord init = default; AssertSameOffset(nameof(PluginInitRecord.Name), Layout.OffsetOf(&init, &init.Name)); - AssertSameOffset(nameof(PluginInitRecord.GetVersion), Layout.OffsetOf(&init, &init.GetVersion)); + AssertSameOffset(nameof(PluginInitRecord.GetVersion), + Layout.OffsetOf(&init, &init.GetVersion)); AssertSameOffset(nameof(PluginInitRecord.EnablePlugin), Layout.OffsetOf(&init, &init.EnablePlugin)); AssertSameOffset(nameof(PluginInitRecord.DisablePlugin), @@ -169,12 +171,14 @@ public void Reflected_offsets_agree_with_address_of_offsets_for_the_packed_init_ PluginType0Record record = default; AssertSameOffset(nameof(PluginType0Record.InterpretedAddress), Layout.OffsetOf(&record, &record.InterpretedAddress)); - AssertSameOffset(nameof(PluginType0Record.Address), Layout.OffsetOf(&record, &record.Address)); + AssertSameOffset(nameof(PluginType0Record.Address), + Layout.OffsetOf(&record, &record.Address)); AssertSameOffset(nameof(PluginType0Record.IsPointer), Layout.OffsetOf(&record, &record.IsPointer)); AssertSameOffset(nameof(PluginType0Record.CountOffsets), Layout.OffsetOf(&record, &record.CountOffsets)); - AssertSameOffset(nameof(PluginType0Record.Offsets), Layout.OffsetOf(&record, &record.Offsets)); + AssertSameOffset(nameof(PluginType0Record.Offsets), + Layout.OffsetOf(&record, &record.Offsets)); AssertSameOffset(nameof(PluginType0Record.Description), Layout.OffsetOf(&record, &record.Description)); AssertSameOffset(nameof(PluginType0Record.ValueType), @@ -204,7 +208,8 @@ public void Gate_reports_a_missing_row_an_extra_row_a_wrong_offset_and_a_wrong_w Assert.Empty(FieldLayoutGate.FindViolations(typeof(Probe), [first, second, third])); Assert.Contains(FieldLayoutGate.FindViolations(typeof(Probe), [first, second]), - static violation => violation.EndsWith("Probe.Third: missing layout row for this field.", StringComparison.Ordinal)); + static violation => violation.EndsWith("Probe.Third: missing layout row for this field.", + StringComparison.Ordinal)); Assert.Contains(FieldLayoutGate.FindViolations(typeof(Probe), [first, second, third, new FieldLayoutRow(probe, "Fourth", 24, 4, FieldKind.Integer)]), static violation => violation.EndsWith("Probe.Fourth: extra layout row names no field of the structure.", @@ -213,8 +218,10 @@ public void Gate_reports_a_missing_row_an_extra_row_a_wrong_offset_and_a_wrong_w static violation => violation.EndsWith("Probe.Second: offset 8, expected 4.", StringComparison.Ordinal)); Assert.Contains(FieldLayoutGate.FindViolations(typeof(Probe), [first, second with { Width = 4 }, third]), static violation => violation.EndsWith("Probe.Second: width 8, expected 4.", StringComparison.Ordinal)); - Assert.Contains(FieldLayoutGate.FindViolations(typeof(Probe), [first, second, third with { Kind = FieldKind.Pointer }]), - static violation => violation.EndsWith("Probe.Third: kind OpaquePointer, expected Pointer.", StringComparison.Ordinal)); + Assert.Contains( + FieldLayoutGate.FindViolations(typeof(Probe), [first, second, third with { Kind = FieldKind.Pointer }]), + static violation => violation.EndsWith("Probe.Third: kind OpaquePointer, expected Pointer.", + StringComparison.Ordinal)); Assert.Contains(FieldLayoutGate.FindViolations(typeof(Probe), [first, first, second, third]), static violation => violation.EndsWith("Probe.First: duplicate layout row.", StringComparison.Ordinal)); } @@ -233,7 +240,8 @@ public void Gate_catches_a_size_preserving_retype_that_a_size_check_misses() Assert.Equal(Layout.SizeOf(), Layout.SizeOf()); IReadOnlyList violations = FieldLayoutGate.FindViolations(typeof(ShiftedMirror), hostRows); - Assert.Contains(violations, static violation => violation.Contains("ShiftedMirror.Second: offset 4, expected 8.", + Assert.Contains(violations, static violation => violation.Contains( + "ShiftedMirror.Second: offset 4, expected 8.", StringComparison.Ordinal)); Assert.Contains(violations, static violation => violation.Contains("ShiftedMirror.Second: width 4, expected 8.", StringComparison.Ordinal)); @@ -243,14 +251,14 @@ private static FieldInfo Field(FieldLayoutRow row) { Type structure = AbiStructures.AbiAssembly.GetType(row.TypeFullName, true, false)!; return structure.GetField(row.FieldName, FieldLayoutGate.InstanceFields) - ?? throw new InvalidOperationException($"{row.TypeFullName} has no field {row.FieldName}."); + ?? throw new InvalidOperationException($"{row.TypeFullName} has no field {row.FieldName}."); } private static void AssertSameOffset(string fieldName, int addressOfOffset) where T : unmanaged { FieldInfo field = typeof(T).GetField(fieldName, FieldLayoutGate.InstanceFields) - ?? throw new InvalidOperationException($"{typeof(T).Name} has no field {fieldName}."); + ?? throw new InvalidOperationException($"{typeof(T).Name} has no field {fieldName}."); Assert.Equal(addressOfOffset, FieldLayoutGate.OffsetOf(field)); } diff --git a/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureContractTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureContractTests.cs index ee6b1dd6..a9c0ecde 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureContractTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureContractTests.cs @@ -58,8 +58,8 @@ public void Header_derived_classic_records_have_the_fixture_x64_alignments() public void Header_and_pinned_Pascal_popup_contract_conflict_keeps_the_slot_opaque_until_a_live_canary() { FieldInfo popup = typeof(DisassemblerContextPluginInit).GetField( - nameof(DisassemblerContextPluginInit.CallbackOnPopup)) - ?? throw new InvalidOperationException("The popup callback field was not found."); + nameof(DisassemblerContextPluginInit.CallbackOnPopup)) + ?? throw new InvalidOperationException("The popup callback field was not found."); Type fieldType = popup.GetModifiedFieldType().UnderlyingSystemType; diff --git a/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureManagedComparisonTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureManagedComparisonTests.cs index 8a011961..0aa3ee0c 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureManagedComparisonTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureManagedComparisonTests.cs @@ -47,7 +47,7 @@ public void Native_fixture_layout_facts_match_the_managed_x64_measurements_when_ foreach (string record in comparedRecords) { if (nativeKey.StartsWith("offsetof." + record + ".", StringComparison.Ordinal) || - nativeKey.StartsWith("fieldsize." + record + ".", StringComparison.Ordinal)) + nativeKey.StartsWith("fieldsize." + record + ".", StringComparison.Ordinal)) { Assert.True(managedFacts.ContainsKey(nativeKey), $"The native fixture transcribes '{nativeKey}', which has no managed field."); diff --git a/tests/CheatEngine.SDK.Abi.Tests/Managed/PluginInitRecordTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Managed/PluginInitRecordTests.cs index e7230545..65561892 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Managed/PluginInitRecordTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Managed/PluginInitRecordTests.cs @@ -120,7 +120,7 @@ private static Bool32 FakeGetVersion(PluginVersion* version, int size) private static Bool32 FakeEnablePlugin(ManagedExportedFunctions* exports, uint pluginId) { return exports is not null && exports->SizeOfExportedFunctions == sizeof(ManagedExportedFunctions) && - pluginId == 0xFFFF_FFF0u; + pluginId == 0xFFFF_FFF0u; } [UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])] diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicDebugEventDispatcherTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicDebugEventDispatcherTests.cs index 109796ba..b7429f3f 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicDebugEventDispatcherTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicDebugEventDispatcherTests.cs @@ -20,7 +20,8 @@ namespace CheatEngine.SDK.Abi.Tests.Native; /// The Q38 tests call the registered thunk from threads created with Win32 CreateThread, which the CLR did /// not create and has never seen before the call (the situation of a debug event delivered by a host thread). They /// are C1 evidence of the dispatcher's thread contract only: on the managed-hostfxr profile no route reaches the -/// classic RegisterFunction, so Q38 at C3 stays NotApplicable (see libs/CheatEngine.SDK.Abi/README.md). +/// classic RegisterFunction, so Q38 at C3 stays NotApplicable (see +/// libs/CheatEngine.SDK.Abi/README.md). /// /// public sealed unsafe partial class ClassicDebugEventDispatcherTests : IDisposable @@ -484,7 +485,8 @@ public void Function_id_zero_is_a_valid_identifier_passed_back_on_unregister() [InlineData(true, false)] [InlineData(false, true)] [InlineData(false, false)] - public void Missing_register_or_unregister_slot_is_refused_before_any_host_call(bool withRegister, bool withUnregister) + public void Missing_register_or_unregister_slot_is_refused_before_any_host_call(bool withRegister, + bool withUnregister) { Assert.SkipUnless(Layout.Is64BitProcess, Layout.Requires64BitProcess); s_registerCalls = 0; diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsPrefixReaderTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsPrefixReaderTests.cs index a2144537..7f4f02a5 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsPrefixReaderTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsPrefixReaderTests.cs @@ -157,14 +157,14 @@ public void TryCopy_is_all_or_nothing_between_slot_boundaries(int declaredSize) public void Prefix_distinguishes_direct_function_slots_value_cells_and_opaque_null_slots_without_invocation() { FieldInfo showMessage = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.ShowMessage)) - ?? throw new InvalidOperationException("The ShowMessage field was not found."); + ?? throw new InvalidOperationException("The ShowMessage field was not found."); FieldInfo processId = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.OpenedProcessId)) - ?? throw new InvalidOperationException("The OpenedProcessId field was not found."); + ?? throw new InvalidOperationException("The OpenedProcessId field was not found."); FieldInfo processHandle = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.OpenedProcessHandle)) ?? throw new InvalidOperationException("The OpenedProcessHandle field was not found."); FieldInfo fixMemory = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.FixMemory)) - ?? throw new InvalidOperationException("The FixMemory field was not found."); + ?? throw new InvalidOperationException("The FixMemory field was not found."); FieldInfo getAddress = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.GetAddressFromPointer)) ?? throw new InvalidOperationException("The GetAddressFromPointer field was not found."); diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsSlotReaderTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsSlotReaderTests.cs index 70bd6b40..57b4f7b4 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsSlotReaderTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsSlotReaderTests.cs @@ -37,7 +37,8 @@ public void Slot_is_refused_when_the_declared_size_is_one_byte_short(int slot, i byte[] table = Table(minDeclaredSize - 1, ClassicExportedFunctionsSlotReader.TableByteCount); WriteSlot(table, slot, 0x1234_5678_9ABC_DEF0); - Assert.False(ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); + Assert.False( + ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); Assert.Equal(default, observation); } @@ -52,7 +53,8 @@ public void Slot_is_read_when_declared_and_physical_sizes_cover_it_exactly(int s ulong value = 0x0100_0000_0000_0000UL + (ulong) slot; WriteSlot(table, slot, value); - Assert.True(ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); + Assert.True( + ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); Assert.Equal(slot, observation.Slot); Assert.Equal((nint) value, observation.RawValue); Assert.False(observation.IsNull); @@ -74,23 +76,27 @@ public void Oversized_declared_table_is_accepted_for_the_known_slots(int declare for (int slot = 1; slot < ClassicExportedFunctionsSlotReader.SlotCount; slot++) { - Assert.True(ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); - Assert.Equal((nint) (slot * 0x10), observation.RawValue); + Assert.True( + ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); + Assert.Equal(slot * 0x10, observation.RawValue); } // A future suffix is compatible with the known slots, but no slot past the known table is ever read. - Assert.False(ClassicExportedFunctionsSlotReader.TryReadSlot(table, ClassicExportedFunctionsSlotReader.SlotCount, out _)); + Assert.False(ClassicExportedFunctionsSlotReader.TryReadSlot(table, ClassicExportedFunctionsSlotReader.SlotCount, + out _)); } [Theory] [MemberData(nameof(RegistrySlots))] [Trait("Qualification", "Q39")] - public void Physically_truncated_table_is_refused_even_when_the_declared_size_is_large(int slot, int minDeclaredSize) + public void Physically_truncated_table_is_refused_even_when_the_declared_size_is_large(int slot, + int minDeclaredSize) { Assert.SkipUnless(Layout.Is64BitProcess, Layout.Requires64BitProcess); byte[] table = Table(ClassicExportedFunctionsSlotReader.TableByteCount, minDeclaredSize - 1); - Assert.False(ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); + Assert.False( + ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); Assert.Equal(default, observation); } @@ -99,17 +105,23 @@ public void Physically_truncated_table_is_refused_even_when_the_declared_size_is public void Null_slot_is_reported_as_null_and_never_dereferenced() { Assert.SkipUnless(Layout.Is64BitProcess, Layout.Requires64BitProcess); - byte[] table = Table(ClassicExportedFunctionsSlotReader.TableByteCount, ClassicExportedFunctionsSlotReader.TableByteCount); - int[] nilSlots = [.. ClassicSlotRegistry.Slots - .Where(static slot => string.Equals(slot.GetProperty("nullability").GetString(), "NilAssigned", StringComparison.Ordinal)) - .Select(static slot => slot.GetProperty("slot").GetInt32())]; + byte[] table = Table(ClassicExportedFunctionsSlotReader.TableByteCount, + ClassicExportedFunctionsSlotReader.TableByteCount); + int[] nilSlots = + [ + .. ClassicSlotRegistry.Slots + .Where(static slot => string.Equals(slot.GetProperty("nullability").GetString(), "NilAssigned", + StringComparison.Ordinal)) + .Select(static slot => slot.GetProperty("slot").GetInt32()) + ]; // A non-nil but invalid address in a neighbouring slot: reading it must not touch the address either. WriteSlot(table, 15, 0x1); Assert.Equal(11, nilSlots.Length); foreach (int slot in nilSlots) { - Assert.True(ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); + Assert.True( + ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); Assert.True(observation.IsNull); Assert.Equal(0, observation.RawValue); } @@ -127,12 +139,15 @@ public void Cell_contents_changed_between_two_reads_are_two_distinct_observation const int ReadProcessMemorySlot = 18; Assert.Equal("FunctionPointerCell", ClassicSlotRegistry.Slots[ReadProcessMemorySlot].GetProperty("nature").GetString()); - byte[] table = Table(ClassicExportedFunctionsSlotReader.TableByteCount, ClassicExportedFunctionsSlotReader.TableByteCount); + byte[] table = Table(ClassicExportedFunctionsSlotReader.TableByteCount, + ClassicExportedFunctionsSlotReader.TableByteCount); WriteSlot(table, ReadProcessMemorySlot, 0x0000_7FF0_0000_1000); - Assert.True(ClassicExportedFunctionsSlotReader.TryReadSlot(table, ReadProcessMemorySlot, out ClassicSlotObservation first)); + Assert.True(ClassicExportedFunctionsSlotReader.TryReadSlot(table, ReadProcessMemorySlot, + out ClassicSlotObservation first)); WriteSlot(table, ReadProcessMemorySlot, 0x0000_7FF0_0000_2000); - Assert.True(ClassicExportedFunctionsSlotReader.TryReadSlot(table, ReadProcessMemorySlot, out ClassicSlotObservation second)); + Assert.True(ClassicExportedFunctionsSlotReader.TryReadSlot(table, ReadProcessMemorySlot, + out ClassicSlotObservation second)); Assert.Equal(0x0000_7FF0_0000_1000, first.RawValue); Assert.Equal(0x0000_7FF0_0000_2000, second.RawValue); @@ -144,7 +159,8 @@ public void Cell_contents_changed_between_two_reads_are_two_distinct_observation public void Address_above_32_bits_round_trips_through_a_slot() { Assert.SkipUnless(Layout.Is64BitProcess, Layout.Requires64BitProcess); - byte[] table = Table(ClassicExportedFunctionsSlotReader.TableByteCount, ClassicExportedFunctionsSlotReader.TableByteCount); + byte[] table = Table(ClassicExportedFunctionsSlotReader.TableByteCount, + ClassicExportedFunctionsSlotReader.TableByteCount); WriteSlot(table, 158, HighAddress); Assert.True(ClassicExportedFunctionsSlotReader.TryReadSlot(table, 158, out ClassicSlotObservation observation)); @@ -163,7 +179,8 @@ public void Slot_zero_and_out_of_range_indices_are_refused(int slot) { byte[] table = Table(int.MaxValue, ClassicExportedFunctionsSlotReader.TableByteCount + 64); - Assert.False(ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); + Assert.False( + ClassicExportedFunctionsSlotReader.TryReadSlot(table, slot, out ClassicSlotObservation observation)); Assert.Equal(default, observation); } @@ -173,7 +190,8 @@ public void Reader_constants_equal_the_registry_contract() JsonElement contract = ClassicSlotRegistry.Root.GetProperty("contract"); Assert.Equal(ClassicExportedFunctionsSlotReader.SlotCount, contract.GetProperty("fieldCount").GetInt32()); - Assert.Equal(ClassicExportedFunctionsSlotReader.TableByteCount, contract.GetProperty("x64TableSize").GetInt32()); + Assert.Equal(ClassicExportedFunctionsSlotReader.TableByteCount, + contract.GetProperty("x64TableSize").GetInt32()); Assert.Equal(ClassicExportedFunctionsSlotReader.TableByteCount, ClassicSlotRegistry.MinDeclaredSize(158)); } diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicSlotRegistryPrefixTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicSlotRegistryPrefixTests.cs index 3879d9cf..6579726e 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicSlotRegistryPrefixTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicSlotRegistryPrefixTests.cs @@ -34,7 +34,8 @@ public void Prefix_fields_are_registry_slots_0_to_17_in_order_with_offsets_and_w Assert.Equal(entry.GetProperty("width").GetInt32(), FieldLayoutGate.WidthOf(field)); } - Assert.All(slots[18..], static entry => Assert.Equal(JsonValueKind.Null, entry.GetProperty("sdkField").ValueKind)); + Assert.All(slots[18..], + static entry => Assert.Equal(JsonValueKind.Null, entry.GetProperty("sdkField").ValueKind)); } [Fact] @@ -42,11 +43,13 @@ public void Direct_prefix_byte_count_is_the_min_declared_size_of_slot_17() { Assert.SkipUnless(Layout.Is64BitProcess, Layout.Requires64BitProcess); - Assert.Equal(ClassicExportedFunctionsPrefixReader.DirectPrefixByteCount, ClassicSlotRegistry.MinDeclaredSize(17)); + Assert.Equal(ClassicExportedFunctionsPrefixReader.DirectPrefixByteCount, + ClassicSlotRegistry.MinDeclaredSize(17)); Assert.Equal(ClassicSlotRegistry.MinDeclaredSize(17), Layout.SizeOf()); Assert.Equal(ClassicExportedFunctionsPrefixReader.DirectPrefixByteCount, ClassicSlotRegistry.Root.GetProperty("contract").GetProperty("sdkDirectPrefixSize").GetInt32()); - Assert.True(ClassicExportedFunctionsPrefixReader.DirectPrefixByteCount < ClassicSlotRegistry.MinDeclaredSize(18)); + Assert.True( + ClassicExportedFunctionsPrefixReader.DirectPrefixByteCount < ClassicSlotRegistry.MinDeclaredSize(18)); } [Fact] @@ -58,7 +61,8 @@ public void Typed_prefix_slots_are_exactly_the_registry_prefix_typed_slots() { bool opaque = FieldLayoutGate.KindOf(PrefixFields[slot]) == FieldKind.OpaquePointer; string expected = opaque ? "PrefixOpaque" : "PrefixTyped"; - Assert.True(string.Equals(expected, slots[slot].GetProperty("sdkExposure").GetString(), StringComparison.Ordinal), + Assert.True( + string.Equals(expected, slots[slot].GetProperty("sdkExposure").GetString(), StringComparison.Ordinal), $"Slot {slot} ({PrefixFields[slot].Name}) is {expected} in the SDK but {slots[slot].GetProperty("sdkExposure").GetString()} in the registry."); } } @@ -72,7 +76,8 @@ public void Nil_or_divergent_prefix_slots_are_opaque_void_pointers() for (int slot = 0; slot < PrefixFields.Length; slot++) { JsonElement entry = slots[slot]; - bool nil = string.Equals(entry.GetProperty("nullability").GetString(), "NilAssigned", StringComparison.Ordinal); + bool nil = string.Equals(entry.GetProperty("nullability").GetString(), "NilAssigned", + StringComparison.Ordinal); bool divergent = entry.GetProperty("divergenceRefs").GetArrayLength() > 0; if (nil || divergent) { diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs index 4bda49d2..f1c64b40 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs @@ -91,13 +91,13 @@ public void Prefix_stops_before_the_pointer_to_pointer_hook_suffix() public void Historically_null_and_conflicting_slots_stay_opaque() { FieldInfo fixMemory = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.FixMemory), - BindingFlags.Instance | BindingFlags.Public) - ?? throw new InvalidOperationException("The FixMemory field was not found."); + BindingFlags.Instance | BindingFlags.Public) + ?? throw new InvalidOperationException("The FixMemory field was not found."); FieldInfo getAddressFromPointer = typeof(ExportedFunctionsPrefix).GetField( - nameof(ExportedFunctionsPrefix.GetAddressFromPointer), - BindingFlags.Instance | BindingFlags.Public) - ?? throw new InvalidOperationException( - "The GetAddressFromPointer field was not found."); + nameof(ExportedFunctionsPrefix.GetAddressFromPointer), + BindingFlags.Instance | BindingFlags.Public) + ?? throw new InvalidOperationException( + "The GetAddressFromPointer field was not found."); Type fixMemoryType = fixMemory.GetModifiedFieldType().UnderlyingSystemType; Type getAddressFromPointerType = getAddressFromPointer.GetModifiedFieldType().UnderlyingSystemType; diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/PluginType0RecordTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/PluginType0RecordTests.cs index e1d82fd2..c01091e4 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/PluginType0RecordTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/PluginType0RecordTests.cs @@ -58,6 +58,6 @@ public void PluginType0Record_fields_have_the_host_widths() private static Type TypeOf(string fieldName) { return (typeof(PluginType0Record).GetField(fieldName) - ?? throw new InvalidOperationException($"PluginType0Record has no field {fieldName}.")).FieldType; + ?? throw new InvalidOperationException($"PluginType0Record has no field {fieldName}.")).FieldType; } } diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/SelectedRecordOracleTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/SelectedRecordOracleTests.cs index 749e82ee..10cfd23b 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/SelectedRecordOracleTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/SelectedRecordOracleTests.cs @@ -17,7 +17,8 @@ namespace CheatEngine.SDK.Abi.Tests.Native; /// per-field check separates them (audit annex 05, A03-31, AX05-07). /// /// -/// The mirrors are modelled here as nested C# structures, never in CheatEngine.SDK.Abi. The CI-only fixture test +/// The mirrors are modelled here as nested C# structures, never in CheatEngine.SDK.Abi. The CI-only fixture +/// test /// compares the same three layouts as compiled by MSVC from the transcriptions in /// tests/native-abi-fixture/ce77_plugin_abi_contract.h. Nothing here observes the CE 7.7 binary. /// @@ -44,7 +45,8 @@ public void PluginType0Record_matches_the_pinned_host_type_field_by_field() Assert.SkipUnless(Layout.Is64BitProcess, Layout.Requires64BitProcess); Assert.Equal(48, Layout.SizeOf()); - Assert.Empty(FieldLayoutGate.FindViolations(typeof(PluginType0Record), HostRows(HostType, FieldKindsOfSdkRecord()))); + Assert.Empty(FieldLayoutGate.FindViolations(typeof(PluginType0Record), + HostRows(HostType, FieldKindsOfSdkRecord()))); Assert.Equal(HostLayout.Select(static row => row.Field), typeof(PluginType0Record).GetFields(FieldLayoutGate.InstanceFields).Select(static field => field.Name), StringComparer.Ordinal); @@ -93,7 +95,8 @@ public void Size_only_check_cannot_tell_the_host_type_from_either_mirror() Assert.Equal(Layout.SizeOf(), Layout.SizeOf()); // What the per-field gate sees against the host oracle: the SDK record passes, both mirrors fail. - Assert.Empty(FieldLayoutGate.FindViolations(typeof(PluginType0Record), HostRows(HostType, FieldKindsOfSdkRecord()))); + Assert.Empty(FieldLayoutGate.FindViolations(typeof(PluginType0Record), + HostRows(HostType, FieldKindsOfSdkRecord()))); Assert.Contains(FieldLayoutGate.FindViolations(typeof(PascalDwordMirrorSelectedRecord), HostRows(typeof(PascalDwordMirrorSelectedRecord).FullName!, null)), IsOffsetOrWidth); Assert.Contains(FieldLayoutGate.FindViolations(typeof(PascalBooleanMirrorSelectedRecord), @@ -173,7 +176,7 @@ private static FieldKind KindOf(string typeFullName, string fieldName) private static bool IsOffsetOrWidth(string violation) { return violation.Contains(": offset ", StringComparison.Ordinal) || - violation.Contains(": width ", StringComparison.Ordinal); + violation.Contains(": width ", StringComparison.Ordinal); } private static int Offset(string fieldName) @@ -189,7 +192,7 @@ private static int Width(string fieldName) private static FieldInfo FieldOf(string fieldName) { return typeof(T).GetField(fieldName, FieldLayoutGate.InstanceFields) - ?? throw new InvalidOperationException($"{typeof(T).Name} has no field {fieldName}."); + ?? throw new InvalidOperationException($"{typeof(T).Name} has no field {fieldName}."); } private static string Text(int value) diff --git a/tests/CheatEngine.SDK.Abi.Tests/README.md b/tests/CheatEngine.SDK.Abi.Tests/README.md index 0f0c4f75..fc37ae2d 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/README.md +++ b/tests/CheatEngine.SDK.Abi.Tests/README.md @@ -19,15 +19,16 @@ Engine itself. Independent techniques check the layout, so one mistake cannot hide behind another. `Managed/` and `Native/` mirror the `CheatEngine.SDK.Abi` namespaces. `Support/` holds `Layout`, the `AbiShape` gate, the per-field `FieldLayoutGate` -with its literal `FieldLayoutExpectations` table, and their tests. Expected numbers are literals next to the assertion or +with its literal `FieldLayoutExpectations` table, and their tests. Expected numbers are literals next to the assertion +or in that table, never derived from the code under test. -| Technique | What it does | -|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Address-of arithmetic | `Layout.SizeOf()` and `Layout.OffsetOf` measure the size and every field offset. | -| Raw bytes | The packed 36-byte init record is written into a guard-filled buffer at an aligned and an odd address. The 48-byte exports record is built as raw bytes, then read through the struct. | -| Host simulation | `&Method` of a real `[UnmanagedCallersOnly]` `Stdcall` function is stored in every typed function-pointer slot, then called through the field. | -| Per-field gate | `FieldLayout/FieldLayoutContractTests` walks every instance field of every struct (public, internal, nested private, compiler-generated backing fields) and compares its offset (measured with the IL `ldflda` instruction), width and kind with one literal row of `Support/FieldLayoutExpectations.cs`, in both directions. | +| Technique | What it does | +|------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Address-of arithmetic | `Layout.SizeOf()` and `Layout.OffsetOf` measure the size and every field offset. | +| Raw bytes | The packed 36-byte init record is written into a guard-filled buffer at an aligned and an odd address. The 48-byte exports record is built as raw bytes, then read through the struct. | +| Host simulation | `&Method` of a real `[UnmanagedCallersOnly]` `Stdcall` function is stored in every typed function-pointer slot, then called through the field. | +| Per-field gate | `FieldLayout/FieldLayoutContractTests` walks every instance field of every struct (public, internal, nested private, compiler-generated backing fields) and compares its offset (measured with the IL `ldflda` instruction), width and kind with one literal row of `Support/FieldLayoutExpectations.cs`, in both directions. | | Native-fact comparison | The native CI job builds the checked `ce77-native-abi-facts.txt`; the Debug build-test job passes it in and sets the required gate. A compiled managed test measures every fixture-covered layout (C-header records and, since schema 3, the packed managed bootstrap record and the managed exports) and compares its size, alignment, and every field's offset and width to that output. | The test assembly applies `[assembly: DisableRuntimeMarshalling]`, so calls take the path a plugin takes. @@ -36,14 +37,17 @@ for `Bool8`). Every branch of `AbiArchitecture` is tested through its internal o `NativeAbiFixtureManagedComparisonTests` has no local fixture dependency. The Debug build-test CI job downloads the facts the native job built, supplies `CE77_NATIVE_ABI_FACTS_PATH` and sets `CE77_NATIVE_ABI_REQUIRED=true` for its -solution test run, which makes a missing facts path fail the comparison gate. Ordinary managed runs omit the required mode and can omit the facts path; that local opt-out is +solution test run, which makes a missing facts path fail the comparison gate. Ordinary managed runs omit the required +mode and can omit the facts path; that local opt-out is intentional and is not a substitute for an exact-host test. - `AssemblyConformanceTests` compares an expected-size table with every struct of the assembly (public, internal and nested, keyed by full name) in both directions, then runs the `AbiShape` reflection gate over every struct. - `FieldLayoutContractTests` is the per-field gate: a field without a row, a row without a field, or a wrong offset, - width or kind fails the run. `Reflected_offsets_agree_with_address_of_offsets_for_the_packed_init_record_and_the_managed_exports` - proves that the reflected offsets equal the C# address-of arithmetic, and two wrong-on-purpose nested structs prove the + width or kind fails the run. + `Reflected_offsets_agree_with_address_of_offsets_for_the_packed_init_record_and_the_managed_exports` + proves that the reflected offsets equal the C# address-of arithmetic, and two wrong-on-purpose nested structs prove + the gate reports each class of error (including a size-preserving retype that a size check misses). - The gate rejects `bool`, `char`, references, foreign value types, managed or non-`Stdcall` function pointers and by-reference parameters at any depth. It exists because `delegate* unmanaged[Cdecl]` compiles without a @@ -65,7 +69,8 @@ intentional and is not a substitute for an exact-host test. An unpacked mirror is 40 bytes and writes 4 bytes past the host's 36-byte variable. - The type-0 selection record matches the host type of `plugin.pas` field by field, and both same-size Pascal mirrors are told apart by a per-field check (`SelectedRecordOracleTests`). -- The embedded [classic slot registry](../CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json) agrees with `ExportedFunctionsPrefix` +- The embedded [classic slot registry](../CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json) + agrees with `ExportedFunctionsPrefix` on slots 0-17, their offsets, widths and opacity (`ClassicSlotRegistryPrefixTests`). - A classic slot is observed only when the declared and the physical sizes both reach `8 * (slot + 1)` bytes, for every slot and boundary, and the prefix copy is all or nothing between slot boundaries diff --git a/tests/CheatEngine.SDK.Abi.Tests/Support/AbiStructures.cs b/tests/CheatEngine.SDK.Abi.Tests/Support/AbiStructures.cs index ae1aa571..a76076b2 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Support/AbiStructures.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Support/AbiStructures.cs @@ -8,7 +8,8 @@ namespace CheatEngine.SDK.Abi.Tests.Support; /// /// The set of structures the assembly-wide gates inspect: every value type of CheatEngine.SDK.Abi, public, /// internal or nested private alike, minus enumerations and compiler-generated types. Shared by -/// (sizes and shape) and FieldLayout.FieldLayoutContractTests (per-field +/// (sizes and shape) and FieldLayout.FieldLayoutContractTests +/// (per-field /// offsets and widths), so both gates always look at exactly the same structures. /// internal static class AbiStructures diff --git a/tests/CheatEngine.SDK.Abi.Tests/Support/ClassicSlotRegistry.cs b/tests/CheatEngine.SDK.Abi.Tests/Support/ClassicSlotRegistry.cs index c591e2d8..ec4e183c 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Support/ClassicSlotRegistry.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Support/ClassicSlotRegistry.cs @@ -3,7 +3,8 @@ namespace CheatEngine.SDK.Abi.Tests.Support; /// -/// Read access to the committed tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json, embedded in this test assembly. The +/// Read access to the committed tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json, +/// embedded in this test assembly. The /// registry's authority is the pinned host source plugin.pas; the SDK types must agree with it, never the /// other way round. /// @@ -31,7 +32,8 @@ public static int MinDeclaredSize(int slot) private static JsonElement Load() { using Stream stream = typeof(ClassicSlotRegistry).Assembly.GetManifestResourceStream(ResourceName) - ?? throw new InvalidOperationException($"The embedded resource {ResourceName} is missing."); + ?? throw new InvalidOperationException( + $"The embedded resource {ResourceName} is missing."); using JsonDocument document = JsonDocument.Parse(stream); return document.RootElement.Clone(); } diff --git a/tests/CheatEngine.SDK.Abi.Tests/Support/FieldKind.cs b/tests/CheatEngine.SDK.Abi.Tests/Support/FieldKind.cs index 0e12d9e5..dbe0e0f3 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Support/FieldKind.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Support/FieldKind.cs @@ -3,7 +3,10 @@ namespace CheatEngine.SDK.Abi.Tests.Support; /// What a field of an ABI structure is, as far as the layout gate is concerned. internal enum FieldKind { - /// A fixed-width or pointer-sized integer (int, uint, long, byte, nuint, an enumeration). + /// + /// A fixed-width or pointer-sized integer (int, uint, long, byte, nuint, an + /// enumeration). + /// Integer, /// One of the two ABI booleans, or . diff --git a/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutExpectations.cs b/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutExpectations.cs index 22dcafc3..f785933f 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutExpectations.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutExpectations.cs @@ -8,7 +8,8 @@ namespace CheatEngine.SDK.Abi.Tests.Support; /// /// /// Literals only, never derived from the code under test. Adding, removing, moving or retyping a field without -/// editing this table fails FieldLayout.FieldLayoutContractTests in both directions (a field without a row, a row +/// editing this table fails FieldLayout.FieldLayoutContractTests in both directions (a field without a row, +/// a row /// without a field, a wrong offset, width or kind). /// /// @@ -16,7 +17,8 @@ namespace CheatEngine.SDK.Abi.Tests.Support; /// TPluginDotNetInitResult L29-36 packed, TExportedFunctionsDotNetV1 L38-45, /// TPlugin0_SelectedRecord L726-735, TExportedFunctions5 L47-226), the C header /// cepluginsdk.h for the registration records and REGISTERMODIFICATIONINFO, and the x64 natural -/// alignment rule; see libs/CheatEngine.SDK.Abi/README.md. The PluginType0Record rows are identical to the host +/// alignment rule; see libs/CheatEngine.SDK.Abi/README.md. The PluginType0Record rows are identical +/// to the host /// type table of the audit's annex 05 (the oracle of Native.SelectedRecordOracleTests). /// /// diff --git a/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutGate.cs b/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutGate.cs index 35e83986..2cbc14e6 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutGate.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutGate.cs @@ -14,7 +14,8 @@ namespace CheatEngine.SDK.Abi.Tests.Support; /// /// Offset is measured, not computed: a applies the IL instruction /// ldflda for the field to the address of a zeroed native buffer of the structure's size and subtracts the -/// buffer address. That is exactly the arithmetic the JIT performs for &record->Field in a plugin, it +/// buffer address. That is exactly the arithmetic the JIT performs for &record->Field in a plugin, +/// it /// works for private and compiler-generated fields, and it does not go through /// , whose unmanaged view is what CA1421 warns about in an /// assembly with runtime marshalling disabled. The field is never read or written. @@ -93,7 +94,8 @@ public static IReadOnlyList FindViolations(Type structure, IReadOnlyList public static unsafe int OffsetOf(FieldInfo field) { ArgumentNullException.ThrowIfNull(field); - Type declaringType = field.DeclaringType ?? throw new ArgumentException("A field has a declaring type.", nameof(field)); + Type declaringType = field.DeclaringType ?? + throw new ArgumentException("A field has a declaring type.", nameof(field)); if (!declaringType.IsValueType || field.IsStatic) { throw new ArgumentException("Only instance fields of structures have a layout offset.", nameof(field)); diff --git a/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutRow.cs b/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutRow.cs index 7715b140..91e7f73d 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutRow.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutRow.cs @@ -6,4 +6,9 @@ namespace CheatEngine.SDK.Abi.Tests.Support; /// Byte offset of the field on x64. /// Byte width of the field on x64 (a pointer or function pointer is 8). /// What the field is; a retyped void* keeps its width but changes its kind. -internal readonly record struct FieldLayoutRow(string TypeFullName, string FieldName, int Offset, int Width, FieldKind Kind); +internal readonly record struct FieldLayoutRow( + string TypeFullName, + string FieldName, + int Offset, + int Width, + FieldKind Kind); diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Architecture/LuaDirectApiBoundaryGuardTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Architecture/LuaDirectApiBoundaryGuardTests.cs index 99ca6888..f79e04ef 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Architecture/LuaDirectApiBoundaryGuardTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Architecture/LuaDirectApiBoundaryGuardTests.cs @@ -429,12 +429,12 @@ private static void AddViolations(List violations, LuaDirectApiP foreach (SyntaxNode node in root.DescendantNodes()) { if (node is not InvocationExpressionSyntax invocation || - !TryGetLuaApiMemberName(invocation, aliases, hasStaticLuaApiImport, hasLuaApiNamespaceImport, - shadowedNames, out string memberName) || - !policy.TryGet(memberName, out LuaDirectApiPolicyEntry entry) || - !entry.RequiresBridge || - entry.AllowedDirectly || - IsConditionallyAllowed(entry, invocation, path)) + !TryGetLuaApiMemberName(invocation, aliases, hasStaticLuaApiImport, hasLuaApiNamespaceImport, + shadowedNames, out string memberName) || + !policy.TryGet(memberName, out LuaDirectApiPolicyEntry entry) || + !entry.RequiresBridge || + entry.AllowedDirectly || + IsConditionallyAllowed(entry, invocation, path)) { continue; } @@ -450,7 +450,7 @@ private static HashSet CollectLuaApiAliases(CompilationUnitSyntax root) foreach (SyntaxNode node in root.DescendantNodesAndSelf()) { if (node is not UsingDirectiveSyntax directive || directive.Alias is null || directive.Name is null || - !IsExactLuaApiTypeName(directive.Name.ToString())) + !IsExactLuaApiTypeName(directive.Name.ToString())) { continue; } @@ -466,8 +466,8 @@ private static bool HasStaticLuaApiImport(CompilationUnitSyntax root) foreach (SyntaxNode node in root.DescendantNodesAndSelf()) { if (node is UsingDirectiveSyntax { Name: not null } directive && - directive.StaticKeyword.RawKind != 0 && - IsExactLuaApiTypeName(directive.Name.ToString())) + directive.StaticKeyword.RawKind != 0 && + IsExactLuaApiTypeName(directive.Name.ToString())) { return true; } @@ -481,8 +481,8 @@ private static bool HasLuaApiNamespaceImport(CompilationUnitSyntax root) foreach (SyntaxNode node in root.DescendantNodesAndSelf()) { if (node is UsingDirectiveSyntax { Alias: null, Name: not null } directive && - directive.StaticKeyword.RawKind == 0 && - IsLuaApiNamespaceName(directive.Name.ToString())) + directive.StaticKeyword.RawKind == 0 && + IsLuaApiNamespaceName(directive.Name.ToString())) { return true; } @@ -527,14 +527,14 @@ private static bool TryGetLuaApiMemberName(InvocationExpressionSyntax invocation switch (invocation.Expression) { case IdentifierNameSyntax identifier when hasStaticLuaApiImport && - !shadowedNames.Contains(identifier.Identifier.ValueText): + !shadowedNames.Contains(identifier.Identifier.ValueText): memberName = identifier.Identifier.ValueText; return true; case MemberAccessExpressionSyntax { Name: IdentifierNameSyntax name } memberAccess: string typeName = memberAccess.Expression.ToString(); if (IsExactLuaApiTypeName(typeName) || aliases.Contains(typeName) || - (hasLuaApiNamespaceImport && string.Equals(typeName, "LuaApi", StringComparison.Ordinal))) + (hasLuaApiNamespaceImport && string.Equals(typeName, "LuaApi", StringComparison.Ordinal))) { memberName = name.Identifier.ValueText; return true; @@ -551,15 +551,15 @@ private static bool IsConditionallyAllowed(LuaDirectApiPolicyEntry entry, Invoca string path) { if (!entry.ConditionalDirectUse || !entry.ConditionalAllowed || - !string.Equals(entry.MemberName, "lua_pushcclosure", StringComparison.Ordinal) || - !string.Equals(path, LightCFunctionFastPathSourcePath, StringComparison.Ordinal)) + !string.Equals(entry.MemberName, "lua_pushcclosure", StringComparison.Ordinal) || + !string.Equals(path, LightCFunctionFastPathSourcePath, StringComparison.Ordinal)) { return false; } SeparatedSyntaxList arguments = invocation.ArgumentList.Arguments; if (arguments.Count != 3 || !IsIdentifier(arguments[0].Expression, "Pointer") || - !IsIntegerZero(arguments[2].Expression)) + !IsIntegerZero(arguments[2].Expression)) { return false; } @@ -567,8 +567,8 @@ private static bool IsConditionallyAllowed(LuaDirectApiPolicyEntry entry, Invoca ExpressionStatementSyntax? pushStatement = invocation.FirstAncestorOrSelf(); MethodDeclarationSyntax? method = invocation.FirstAncestorOrSelf(); if (pushStatement is null || method is null || - !string.Equals(method.Identifier.ValueText, "PushUncheckedFunction", StringComparison.Ordinal) || - method.Body is null) + !string.Equals(method.Identifier.ValueText, "PushUncheckedFunction", StringComparison.Ordinal) || + method.Body is null) { return false; } @@ -590,20 +590,20 @@ private static bool IsConditionallyAllowed(LuaDirectApiPolicyEntry entry, Invoca private static bool IsImmediateOneSlotCheckStackGuard(StatementSyntax statement) { if (statement is not IfStatementSyntax condition || - !ContainsOnlyThrow(condition.Statement) || - condition.Condition is not BinaryExpressionSyntax equals || - !equals.IsKind(SyntaxKind.EqualsExpression) || - !IsIntegerZero(equals.Right)) + !ContainsOnlyThrow(condition.Statement) || + condition.Condition is not BinaryExpressionSyntax equals || + !equals.IsKind(SyntaxKind.EqualsExpression) || + !IsIntegerZero(equals.Right)) { return false; } if (equals.Left is not InvocationExpressionSyntax - { - Expression: IdentifierNameSyntax { Identifier.ValueText: "lua_checkstack" }, - ArgumentList.Arguments: var arguments - } || arguments.Count != 2 || !IsIdentifier(arguments[0].Expression, "Pointer") || - !IsIntegerOne(arguments[1].Expression)) + { + Expression: IdentifierNameSyntax { Identifier.ValueText: "lua_checkstack" }, + ArgumentList.Arguments: var arguments + } || arguments.Count != 2 || !IsIdentifier(arguments[0].Expression, "Pointer") || + !IsIntegerOne(arguments[1].Expression)) { return false; } @@ -614,7 +614,7 @@ condition.Condition is not BinaryExpressionSyntax equals || private static bool ContainsOnlyThrow(StatementSyntax statement) { return statement is ThrowStatementSyntax || - (statement is BlockSyntax { Statements.Count: 1 } block && block.Statements[0] is ThrowStatementSyntax); + (statement is BlockSyntax { Statements.Count: 1 } block && block.Statements[0] is ThrowStatementSyntax); } private static bool IsIntegerZero(ExpressionSyntax expression) @@ -662,7 +662,7 @@ private static bool IsIntegerOne(ExpressionSyntax expression) private static bool IsIdentifier(ExpressionSyntax expression, string identifier) { return expression is IdentifierNameSyntax name && - string.Equals(name.Identifier.ValueText, identifier, StringComparison.Ordinal); + string.Equals(name.Identifier.ValueText, identifier, StringComparison.Ordinal); } private static string[] ReadProvenance(JsonElement entry) @@ -691,7 +691,7 @@ private static string GetRepositoryPath(string sourcePath) private static bool IsGeneratedPath(string repositoryPath) { return repositoryPath.Contains("/bin/", StringComparison.Ordinal) || - repositoryPath.Contains("/obj/", StringComparison.Ordinal); + repositoryPath.Contains("/obj/", StringComparison.Ordinal); } private static bool IsExactLuaApiTypeName(string typeName) diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Diagnostics/DiagnosticCatalogTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Diagnostics/DiagnosticCatalogTests.cs index a8eec0b5..4783e4bd 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Diagnostics/DiagnosticCatalogTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Diagnostics/DiagnosticCatalogTests.cs @@ -154,9 +154,9 @@ private static bool HasRow(string tracking, DiagnosticDescriptor descriptor) { string[] cells = line.Split('|'); if (cells.Length >= 3 - && string.Equals(cells[0].Trim(), descriptor.Id, StringComparison.Ordinal) - && string.Equals(cells[1].Trim(), descriptor.Category, StringComparison.Ordinal) - && string.Equals(cells[2].Trim(), descriptor.DefaultSeverity.ToString(), StringComparison.Ordinal)) + && string.Equals(cells[0].Trim(), descriptor.Id, StringComparison.Ordinal) + && string.Equals(cells[1].Trim(), descriptor.Category, StringComparison.Ordinal) + && string.Equals(cells[2].Trim(), descriptor.DefaultSeverity.ToString(), StringComparison.Ordinal)) { return true; } diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaBindingAnalyzerTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaBindingAnalyzerTests.cs index fbb07768..f61b2f69 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaBindingAnalyzerTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaBindingAnalyzerTests.cs @@ -39,6 +39,7 @@ public sealed class LuaBindingAnalyzerTests private const string OptionalUsings = "using System;\nusing CheatEngine.SDK.Annotations.Lua;\nusing CheatEngine.SDK.Lua.Calls;\nusing CheatEngine.SDK.Lua.Marshalling;\nnamespace Demo;\n"; + private static readonly CSharpParseOptions ParseOptions = new(LanguageVersion.CSharp14); // The real SDK assemblies the shape checks are written against, taken from the copies loaded in this test @@ -61,32 +62,32 @@ public sealed class LuaBindingAnalyzerTests { { "valid function", ShapeUsings + - "public static partial class Functions { [LuaFunction(\"add\")] public static long Add(long a, long b) => a + b; }", + "public static partial class Functions { [LuaFunction(\"add\")] public static long Add(long a, long b) => a + b; }", true }, { "instance method", ShapeUsings + - "public partial class Functions { [LuaFunction(\"add\")] public long Add(long a, long b) => a + b; }", + "public partial class Functions { [LuaFunction(\"add\")] public long Add(long a, long b) => a + b; }", false }, { "not partial container", ShapeUsings + - "public static class Functions { [LuaFunction(\"add\")] public static long Add(long a, long b) => a + b; }", + "public static class Functions { [LuaFunction(\"add\")] public static long Add(long a, long b) => a + b; }", false }, { "invalid lua name", ShapeUsings + - "public static partial class Functions { [LuaFunction(\"end\")] public static long Add(long a, long b) => a + b; }", + "public static partial class Functions { [LuaFunction(\"end\")] public static long Add(long a, long b) => a + b; }", false }, { "valid global try form", ShapeUsings + - "public static partial class Bindings { [LuaGlobal(\"readInteger\")] public static partial bool TryReadInt32(nuint address, out int value); }", + "public static partial class Bindings { [LuaGlobal(\"readInteger\")] public static partial bool TryReadInt32(nuint address, out int value); }", true }, { "global try form returning int instead of bool", ShapeUsings + - "public static partial class Bindings { [LuaGlobal(\"readInteger\")] public static partial int TryReadInt32(nuint address, out int value); }", + "public static partial class Bindings { [LuaGlobal(\"readInteger\")] public static partial int TryReadInt32(nuint address, out int value); }", false }, { @@ -111,47 +112,47 @@ public static partial class Memory { { "optional arguments of a global", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"load\")] public static partial void Load(string path, LuaOptional merge, LuaOptional flags); }", + "public static partial class Bindings { [LuaGlobal(\"load\")] public static partial void Load(string path, LuaOptional merge, LuaOptional flags); }", true }, { "optional results of a global", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"read\")] public static partial LuaOperationStatus Read(int mode, out long first, out LuaOptional second); }", + "public static partial class Bindings { [LuaGlobal(\"read\")] public static partial LuaOperationStatus Read(int mode, out long first, out LuaOptional second); }", true }, { "variadic outcome of a global", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"seq\")] public static partial LuaOperationStatus Seq(int n, Span values, out int count); }", + "public static partial class Bindings { [LuaGlobal(\"seq\")] public static partial LuaOperationStatus Seq(int n, Span values, out int count); }", true }, { "optional parameter of a function", OptionalUsings + - "public static partial class Functions { [LuaFunction(\"f\")] public static int F(int a, LuaOptional b) => a; }", + "public static partial class Functions { [LuaFunction(\"f\")] public static int F(int a, LuaOptional b) => a; }", true }, { "optional argument before a required one", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a, int b); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a, int b); }", false }, { "required result after an optional one", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(out LuaOptional a, out int b); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(out LuaOptional a, out int b); }", false }, { "variadic pair on the try form", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(Span v, out int c); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(Span v, out int c); }", false }, { "optional nullable string", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a); }", false }, { "optional throwing return", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial LuaOptional G(int a); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial LuaOptional G(int a); }", false } }; @@ -474,10 +475,10 @@ public static class Functions static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaBindingContainingType, StringComparison.Ordinal)); Assert.Contains(diagnostics, static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaFunction, StringComparison.Ordinal) && - d.GetMessage(CultureInfo.InvariantCulture).Contains("reserved word", StringComparison.Ordinal)); + d.GetMessage(CultureInfo.InvariantCulture).Contains("reserved word", StringComparison.Ordinal)); Assert.Contains(diagnostics, static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaFunction, StringComparison.Ordinal) && - d.GetMessage(CultureInfo.InvariantCulture).Contains("default value", StringComparison.Ordinal)); + d.GetMessage(CultureInfo.InvariantCulture).Contains("default value", StringComparison.Ordinal)); } [Fact] @@ -515,11 +516,11 @@ public static partial class Globals ImmutableArray diagnostics = await GetDiagnosticsAsync(compilation); Assert.Contains(diagnostics, static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaFunction, StringComparison.Ordinal) && - d.GetMessage(CultureInfo.InvariantCulture) - .Contains("parameter type", StringComparison.Ordinal)); + d.GetMessage(CultureInfo.InvariantCulture) + .Contains("parameter type", StringComparison.Ordinal)); Assert.Contains(diagnostics, static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaGlobal, StringComparison.Ordinal) && - d.GetMessage(CultureInfo.InvariantCulture).Contains("argument type", StringComparison.Ordinal)); + d.GetMessage(CultureInfo.InvariantCulture).Contains("argument type", StringComparison.Ordinal)); } [Theory] @@ -562,24 +563,35 @@ public static partial class Bindings """, true); Diagnostic[] reported = - [.. diagnostics.Where(static d => string.Equals(d.Id, DiagnosticIds.NonTrailingOptionalLuaArgument, StringComparison.Ordinal))]; + [ + .. diagnostics.Where(static d => + string.Equals(d.Id, DiagnosticIds.NonTrailingOptionalLuaArgument, StringComparison.Ordinal)) + ]; Assert.Equal(2, reported.Length); - Assert.Contains(reported, static d => d.GetMessage(CultureInfo.InvariantCulture).StartsWith("Lua binding 'G' must declare every LuaOptional argument after the required ones", StringComparison.Ordinal)); - Assert.Contains(reported, static d => d.GetMessage(CultureInfo.InvariantCulture).StartsWith("Lua binding 'F' must declare every LuaOptional parameter after the required ones", StringComparison.Ordinal)); - Assert.DoesNotContain(diagnostics, static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaGlobal, StringComparison.Ordinal) - || string.Equals(d.Id, DiagnosticIds.InvalidLuaFunction, StringComparison.Ordinal)); + Assert.Contains(reported, + static d => d.GetMessage(CultureInfo.InvariantCulture).StartsWith( + "Lua binding 'G' must declare every LuaOptional argument after the required ones", + StringComparison.Ordinal)); + Assert.Contains(reported, + static d => d.GetMessage(CultureInfo.InvariantCulture).StartsWith( + "Lua binding 'F' must declare every LuaOptional parameter after the required ones", + StringComparison.Ordinal)); + Assert.DoesNotContain(diagnostics, static d => + string.Equals(d.Id, DiagnosticIds.InvalidLuaGlobal, StringComparison.Ordinal) + || string.Equals(d.Id, DiagnosticIds.InvalidLuaFunction, StringComparison.Ordinal)); } [Fact] public async Task Required_result_after_an_optional_result_reports_CESDK2011() { ImmutableArray diagnostics = await AnalyzeAsync(OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(out LuaOptional a, out int b); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(out LuaOptional a, out int b); }", true); Diagnostic diagnostic = Assert.Single(diagnostics); Assert.Equal(DiagnosticIds.InvalidOptionalOrVariadicLuaResult, diagnostic.Id); - Assert.Contains("after the required results", diagnostic.GetMessage(CultureInfo.InvariantCulture), StringComparison.Ordinal); + Assert.Contains("after the required results", diagnostic.GetMessage(CultureInfo.InvariantCulture), + StringComparison.Ordinal); } [Fact] @@ -602,13 +614,21 @@ public static partial class Bindings string[] messages = [ .. diagnostics - .Where(static d => string.Equals(d.Id, DiagnosticIds.InvalidOptionalOrVariadicLuaResult, StringComparison.Ordinal)) + .Where(static d => string.Equals(d.Id, DiagnosticIds.InvalidOptionalOrVariadicLuaResult, + StringComparison.Ordinal)) .Select(static d => d.GetMessage(CultureInfo.InvariantCulture)) ]; - Assert.Contains(messages, static m => m.StartsWith("Lua global binding 'TryG' must return LuaOperationStatus", StringComparison.Ordinal)); - Assert.Contains(messages, static m => m.StartsWith("Lua global binding 'H' must declare at most one variadic", StringComparison.Ordinal)); - Assert.Contains(messages, static m => m.StartsWith("Lua global binding 'H' must declare the variadic", StringComparison.Ordinal)); - Assert.Contains(messages, static m => m.StartsWith("Lua global binding 'K' must use int, long, float, double, bool or nuint", StringComparison.Ordinal)); + Assert.Contains(messages, + static m => m.StartsWith("Lua global binding 'TryG' must return LuaOperationStatus", + StringComparison.Ordinal)); + Assert.Contains(messages, + static m => m.StartsWith("Lua global binding 'H' must declare at most one variadic", + StringComparison.Ordinal)); + Assert.Contains(messages, + static m => m.StartsWith("Lua global binding 'H' must declare the variadic", StringComparison.Ordinal)); + Assert.Contains(messages, + static m => m.StartsWith("Lua global binding 'K' must use int, long, float, double, bool or nuint", + StringComparison.Ordinal)); } [Fact] @@ -644,14 +664,17 @@ public static partial class Bindings Diagnostic[] reported = [ .. (await GetDiagnosticsAsync(compilation)) - .Where(static d => string.Equals(d.Id, DiagnosticIds.LookAlikeLuaContractType, StringComparison.Ordinal)) + .Where(static d => string.Equals(d.Id, DiagnosticIds.LookAlikeLuaContractType, StringComparison.Ordinal)) ]; Assert.Equal(2, reported.Length); - Assert.All(reported, static d => Assert.Contains("not a same-named type", d.GetMessage(CultureInfo.InvariantCulture), StringComparison.Ordinal)); + Assert.All(reported, + static d => Assert.Contains("not a same-named type", d.GetMessage(CultureInfo.InvariantCulture), + StringComparison.Ordinal)); } [Fact] - public async Task Same_named_LuaOperationStatus_from_source_reports_CESDK2012_instead_of_selecting_the_outcome_form() + public async Task + Same_named_LuaOperationStatus_from_source_reports_CESDK2012_instead_of_selecting_the_outcome_form() { const string Source = """ using CheatEngine.SDK.Annotations.Lua; @@ -680,7 +703,8 @@ public static partial class Bindings ImmutableArray diagnostics = await GetDiagnosticsAsync(compilation); Diagnostic diagnostic = Assert.Single(diagnostics); Assert.Equal(DiagnosticIds.LookAlikeLuaContractType, diagnostic.Id); - Assert.StartsWith("Lua binding 'TryReadInt32' must use the LuaOptional and LuaOperationStatus types of CheatEngine.SDK.Lua", + Assert.StartsWith( + "Lua binding 'TryReadInt32' must use the LuaOptional and LuaOperationStatus types of CheatEngine.SDK.Lua", diagnostic.GetMessage(CultureInfo.InvariantCulture), StringComparison.Ordinal); } @@ -702,8 +726,10 @@ public static partial class Bindings """, true); Assert.Equal(["F", "G", "TryH"], - diagnostics.Where(static d => string.Equals(d.Id, DiagnosticIds.UnsupportedLuaOptionalPosition, StringComparison.Ordinal)) - .Select(static d => d.GetMessage(CultureInfo.InvariantCulture).Split('\'')[1]).Order(StringComparer.Ordinal), + diagnostics.Where(static d => + string.Equals(d.Id, DiagnosticIds.UnsupportedLuaOptionalPosition, StringComparison.Ordinal)) + .Select(static d => d.GetMessage(CultureInfo.InvariantCulture).Split('\'')[1]) + .Order(StringComparer.Ordinal), StringComparer.Ordinal); } @@ -722,10 +748,17 @@ public static partial class Bindings """, true); Diagnostic[] reported = - [.. diagnostics.Where(static d => string.Equals(d.Id, DiagnosticIds.UnsupportedLuaOptionalPosition, StringComparison.Ordinal))]; + [ + .. diagnostics.Where(static d => + string.Equals(d.Id, DiagnosticIds.UnsupportedLuaOptionalPosition, StringComparison.Ordinal)) + ]; Assert.Equal(2, reported.Length); - Assert.Contains(reported, static d => d.GetMessage(CultureInfo.InvariantCulture).Contains("the throwing form cannot return one", StringComparison.Ordinal)); - Assert.Contains(reported, static d => d.GetMessage(CultureInfo.InvariantCulture).Contains("a thunk cannot return one", StringComparison.Ordinal)); + Assert.Contains(reported, + static d => d.GetMessage(CultureInfo.InvariantCulture) + .Contains("the throwing form cannot return one", StringComparison.Ordinal)); + Assert.Contains(reported, + static d => d.GetMessage(CultureInfo.InvariantCulture) + .Contains("a thunk cannot return one", StringComparison.Ordinal)); } [Fact] diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaObjectBindingAnalyzerTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaObjectBindingAnalyzerTests.cs index 0d621edf..92adf2fc 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaObjectBindingAnalyzerTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaObjectBindingAnalyzerTests.cs @@ -4,6 +4,9 @@ using CheatEngine.SDK.Analyzers.Diagnostics; using CheatEngine.SDK.Analyzers.Generation; using CheatEngine.SDK.Analyzers.Tests.Infrastructure; +using CheatEngine.SDK.Annotations.Lua; +using CheatEngine.SDK.Lua.Interop.Api; +using CheatEngine.SDK.Lua.State; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -19,9 +22,9 @@ public sealed class LuaObjectBindingAnalyzerTests // The real SDK assemblies: LuaOptional is recognised only as the type CheatEngine.SDK.Lua defines. private static readonly ImmutableArray RealSdkReferences = [ - MetadataReference.CreateFromFile(typeof(CheatEngine.SDK.Annotations.Lua.LuaFunctionAttribute).Assembly.Location), - MetadataReference.CreateFromFile(typeof(CheatEngine.SDK.Lua.Interop.Api.LuaApi).Assembly.Location), - MetadataReference.CreateFromFile(typeof(CheatEngine.SDK.Lua.State.LuaState).Assembly.Location) + MetadataReference.CreateFromFile(typeof(LuaFunctionAttribute).Assembly.Location), + MetadataReference.CreateFromFile(typeof(LuaApi).Assembly.Location), + MetadataReference.CreateFromFile(typeof(LuaState).Assembly.Location) ]; [Fact] @@ -227,14 +230,19 @@ public readonly partial struct Handle .GetAnalyzerDiagnosticsAsync(TestContext.Current.CancellationToken); Assert.Equal(["Load", "TryRead", "Value"], - diagnostics.Where(static d => string.Equals(d.Id, DiagnosticIds.UnsupportedLuaOptionalPosition, StringComparison.Ordinal)) - .Select(static d => d.GetMessage(CultureInfo.InvariantCulture).Split('\'')[1]).Order(StringComparer.Ordinal), + diagnostics.Where(static d => + string.Equals(d.Id, DiagnosticIds.UnsupportedLuaOptionalPosition, StringComparison.Ordinal)) + .Select(static d => d.GetMessage(CultureInfo.InvariantCulture).Split('\'')[1]) + .Order(StringComparer.Ordinal), StringComparer.Ordinal); - Assert.All(diagnostics.Where(static d => string.Equals(d.Id, DiagnosticIds.UnsupportedLuaOptionalPosition, StringComparison.Ordinal)), + Assert.All( + diagnostics.Where(static d => + string.Equals(d.Id, DiagnosticIds.UnsupportedLuaOptionalPosition, StringComparison.Ordinal)), static d => Assert.Contains("[LuaMethod] and [LuaProperty] members do not support optional values yet", d.GetMessage(CultureInfo.InvariantCulture), StringComparison.Ordinal)); // The optional position is explained once, by CESDK2013, not a second time as an unsupported type (CESDK2006). - Assert.DoesNotContain(diagnostics, static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaAnnotationTarget, StringComparison.Ordinal)); + Assert.DoesNotContain(diagnostics, + static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaAnnotationTarget, StringComparison.Ordinal)); } [Fact] diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/CodeFixVerifier.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/CodeFixVerifier.cs index ab0bfb7e..c0127865 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/CodeFixVerifier.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/CodeFixVerifier.cs @@ -37,8 +37,7 @@ public static Task VerifyAsync( { CheatEngineSdkCodeFixTest test = new() { - CodeActionEquivalenceKey = equivalenceKey, - NumberOfFixAllIterations = fixAllIterations + CodeActionEquivalenceKey = equivalenceKey, NumberOfFixAllIterations = fixAllIterations }; // The default drops fixable ids from the markup of the fixed state, assuming a fix always removes them all. diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferences.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferences.cs index 503606c6..d681851c 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferences.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferences.cs @@ -76,8 +76,8 @@ public static ImmutableArray FromTargetingPack() { string candidate = Path.Combine(pack, "ref", TargetFramework); if (Directory.Exists(candidate) - && TryParsePackVersion(Path.GetFileName(pack), out Version? version) - && (bestVersion is null || version > bestVersion)) + && TryParsePackVersion(Path.GetFileName(pack), out Version? version) + && (bestVersion is null || version > bestVersion)) { best = candidate; bestVersion = version; diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferencesTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferencesTests.cs index d0653902..f3392bd5 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferencesTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferencesTests.cs @@ -42,7 +42,7 @@ public void References_are_existing_local_files_and_include_the_core_facade() foreach (MetadataReference reference in LocalFrameworkReferences.References) { string path = Assert.IsType(reference, false).FilePath - ?? throw new InvalidOperationException("A framework reference without a file path."); + ?? throw new InvalidOperationException("A framework reference without a file path."); Assert.True(File.Exists(path), path); hasSystemRuntime |= string.Equals(Path.GetFileName(path), "System.Runtime.dll", StringComparison.OrdinalIgnoreCase); diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/RepositoryLayout.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/RepositoryLayout.cs index 7262e163..7b8fe539 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/RepositoryLayout.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/RepositoryLayout.cs @@ -20,8 +20,8 @@ public static string PathOf(string relativePath) private static string FindRoot() { for (DirectoryInfo? directory = new(AppContext.BaseDirectory); - directory is not null; - directory = directory.Parent) + directory is not null; + directory = directory.Parent) { if (File.Exists(Path.Combine(directory.FullName, SolutionFileName))) { diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Plugin/ClassicNativeExportAnalyzerTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Plugin/ClassicNativeExportAnalyzerTests.cs index 7acb26a2..88138741 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Plugin/ClassicNativeExportAnalyzerTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Plugin/ClassicNativeExportAnalyzerTests.cs @@ -4,7 +4,6 @@ using CheatEngine.SDK.Analyzers.Tests.Infrastructure; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Testing; using Verifier = CheatEngine.SDK.Analyzers.Tests.Infrastructure.AnalyzerVerifier< CheatEngine.SDK.Analyzers.Plugin.ClassicNativeExportAnalyzer>; @@ -40,22 +39,26 @@ await Verifier.VerifyAsync(Exports($$""" public async Task NativeExportNames_constant_as_entry_point_reports_CESDK0006() { CheatEngineSdkAnalyzerTest test = new(); - test.TestState.AdditionalReferences.Add(MetadataReference.CreateFromFile(typeof(NativeExportNames).Assembly.Location)); + test.TestState.AdditionalReferences.Add( + MetadataReference.CreateFromFile(typeof(NativeExportNames).Assembly.Location)); test.TestState.Sources.Add(("Test0.cs", TestText.Normalize(Exports(""" - [{|#0:UnmanagedCallersOnly(EntryPoint = NativeExportNames.GetVersion)|}] - private static int GetVersion(nint version, int size) => 0; + [{|#0:UnmanagedCallersOnly(EntryPoint = NativeExportNames.GetVersion)|}] + private static int GetVersion(nint version, int size) => 0; - [{|#1:UnmanagedCallersOnly(EntryPoint = NativeExportNames.InitializePlugin)|}] - private static int Initialize(nint exports, int pluginId) => 0; + [{|#1:UnmanagedCallersOnly(EntryPoint = NativeExportNames.InitializePlugin)|}] + private static int Initialize(nint exports, int pluginId) => 0; - [{|#2:UnmanagedCallersOnly(EntryPoint = NativeExportNames.DisablePlugin)|}] - private static int Disable() => 0; - """, "using CheatEngine.SDK.Abi.Native;")))); - test.ExpectedDiagnostics.Add(Verifier.Diagnostic(DiagnosticDescriptors.ClassicNativePluginExport).WithLocation(0) + [{|#2:UnmanagedCallersOnly(EntryPoint = NativeExportNames.DisablePlugin)|}] + private static int Disable() => 0; + """, "using CheatEngine.SDK.Abi.Native;")))); + test.ExpectedDiagnostics.Add(Verifier.Diagnostic(DiagnosticDescriptors.ClassicNativePluginExport) + .WithLocation(0) .WithArguments("GetVersion", NativeExportNames.GetVersion)); - test.ExpectedDiagnostics.Add(Verifier.Diagnostic(DiagnosticDescriptors.ClassicNativePluginExport).WithLocation(1) + test.ExpectedDiagnostics.Add(Verifier.Diagnostic(DiagnosticDescriptors.ClassicNativePluginExport) + .WithLocation(1) .WithArguments("Initialize", NativeExportNames.InitializePlugin)); - test.ExpectedDiagnostics.Add(Verifier.Diagnostic(DiagnosticDescriptors.ClassicNativePluginExport).WithLocation(2) + test.ExpectedDiagnostics.Add(Verifier.Diagnostic(DiagnosticDescriptors.ClassicNativePluginExport) + .WithLocation(2) .WithArguments("Disable", NativeExportNames.DisablePlugin)); await test.RunAsync(TestContext.Current.CancellationToken); @@ -114,10 +117,12 @@ await Verifier.VerifyWithoutCheatEngineSdkAsync(Exports(""" [Fact] public async Task Export_in_generated_code_is_not_analysed() { - await Verifier.VerifyAsync([("Exports.g.cs", "// \n" + Exports(""" - [UnmanagedCallersOnly(EntryPoint = "CEPlugin_GetVersion")] - private static int Export(nint argument) => 0; - """))]); + await Verifier.VerifyAsync([ + ("Exports.g.cs", "// \n" + Exports(""" + [UnmanagedCallersOnly(EntryPoint = "CEPlugin_GetVersion")] + private static int Export(nint argument) => 0; + """)) + ]); } private static string Exports(string members, string extraUsing = "") diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Usage/HostWidthPointerSizeAnalyzerTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Usage/HostWidthPointerSizeAnalyzerTests.cs index acbb02bc..7249ad66 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Usage/HostWidthPointerSizeAnalyzerTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Usage/HostWidthPointerSizeAnalyzerTests.cs @@ -105,7 +105,8 @@ internal static class Widths public static PointerSize Width() => {|#0:new PointerSize(IntPtr.Size)|}; } """, - new DiagnosticResult(DiagnosticDescriptors.HostWidthPointerSize).WithLocation(0).WithArguments("IntPtr.Size")); + new DiagnosticResult(DiagnosticDescriptors.HostWidthPointerSize).WithLocation(0) + .WithArguments("IntPtr.Size")); } [Fact] diff --git a/tests/CheatEngine.SDK.Benchmarks/BenchFunctions.cs b/tests/CheatEngine.SDK.Benchmarks/BenchFunctions.cs index 89f2770b..6a9ad230 100644 --- a/tests/CheatEngine.SDK.Benchmarks/BenchFunctions.cs +++ b/tests/CheatEngine.SDK.Benchmarks/BenchFunctions.cs @@ -6,7 +6,7 @@ namespace CheatEngine.SDK.Benchmarks; /// A generated [LuaFunction] thunk, registered once by and then called /// from a Lua loop many times inside one protected call: register once, call from Lua N times. /// -internal static partial class BenchFunctions +internal static class BenchFunctions { /// Lua: cheatengine_sdk_bench_touch(x). Returns plus one. /// The running value. diff --git a/tests/CheatEngine.SDK.Benchmarks/CallbackBenchmarks.cs b/tests/CheatEngine.SDK.Benchmarks/CallbackBenchmarks.cs index f7068a7c..b5d0e195 100644 --- a/tests/CheatEngine.SDK.Benchmarks/CallbackBenchmarks.cs +++ b/tests/CheatEngine.SDK.Benchmarks/CallbackBenchmarks.cs @@ -64,7 +64,7 @@ public void Setup() if (!defined.IsOk) { throw new InvalidOperationException("Defining cheatengine_sdk_bench_loop failed: " + - LuaError.FromStack(_l, defined)); + LuaError.FromStack(_l, defined)); } } diff --git a/tests/CheatEngine.SDK.Benchmarks/EngineApiIncrementalBenchmarks.cs b/tests/CheatEngine.SDK.Benchmarks/EngineApiIncrementalBenchmarks.cs index a2944adf..dc3560c6 100644 --- a/tests/CheatEngine.SDK.Benchmarks/EngineApiIncrementalBenchmarks.cs +++ b/tests/CheatEngine.SDK.Benchmarks/EngineApiIncrementalBenchmarks.cs @@ -183,7 +183,7 @@ private BenchmarkAdditionalText Second() private BenchmarkAdditionalText EditedFirst() { return _editedFirstSpec ?? - throw new InvalidOperationException("Benchmark setup did not create the edited spec."); + throw new InvalidOperationException("Benchmark setup did not create the edited spec."); } private GeneratorDriver WarmDriver() diff --git a/tests/CheatEngine.SDK.Benchmarks/GlobalCallBenchmarks.cs b/tests/CheatEngine.SDK.Benchmarks/GlobalCallBenchmarks.cs index b239430e..394c262d 100644 --- a/tests/CheatEngine.SDK.Benchmarks/GlobalCallBenchmarks.cs +++ b/tests/CheatEngine.SDK.Benchmarks/GlobalCallBenchmarks.cs @@ -37,7 +37,7 @@ public void Setup() if (!defined.IsOk) { throw new InvalidOperationException("Defining cheatengine_sdk_bench_add failed: " + - LuaError.FromStack(l, defined)); + LuaError.FromStack(l, defined)); } } diff --git a/tests/CheatEngine.SDK.Benchmarks/MemoryScalarBenchmarks.cs b/tests/CheatEngine.SDK.Benchmarks/MemoryScalarBenchmarks.cs index d3c4fedc..815c97b1 100644 --- a/tests/CheatEngine.SDK.Benchmarks/MemoryScalarBenchmarks.cs +++ b/tests/CheatEngine.SDK.Benchmarks/MemoryScalarBenchmarks.cs @@ -81,7 +81,7 @@ public void Setup() if (!defined.IsOk) { throw new InvalidOperationException("Defining scalar-memory fixture globals failed: " + - LuaError.FromStack(state, defined)); + LuaError.FromStack(state, defined)); } if (!TargetMemory.TryWriteInt32(Address32, -42, out _)) @@ -95,15 +95,15 @@ public void Setup() } if (!HostMemory.TryWriteInt32(HostAddress32, -42, out _) || - !HostMemory.TryWriteInt64(HostAddress64, 0x1_0000_0000L, out _)) + !HostMemory.TryWriteInt64(HostAddress64, 0x1_0000_0000L, out _)) { throw new InvalidOperationException("Warming local scalar writes failed."); } if (!TargetMemory.TryReadInt32(Address32, out _, out _) || - !TargetMemory.TryReadInt64(Address64, out _, out _) || - !HostMemory.TryReadInt32(HostAddress32, out _, out _) || - !HostMemory.TryReadInt64(HostAddress64, out _, out _)) + !TargetMemory.TryReadInt64(Address64, out _, out _) || + !HostMemory.TryReadInt32(HostAddress32, out _, out _) || + !HostMemory.TryReadInt64(HostAddress64, out _, out _)) { throw new InvalidOperationException("Warming scalar reads failed."); } diff --git a/tests/CheatEngine.SDK.Benchmarks/Support/FakeHostRuntime.cs b/tests/CheatEngine.SDK.Benchmarks/Support/FakeHostRuntime.cs index 352cea17..71d2a5f9 100644 --- a/tests/CheatEngine.SDK.Benchmarks/Support/FakeHostRuntime.cs +++ b/tests/CheatEngine.SDK.Benchmarks/Support/FakeHostRuntime.cs @@ -72,7 +72,7 @@ private static void InstallMetatable(LuaState state) if (!status.IsOk) { throw new InvalidOperationException("Installing the fake host metatable failed: " + - LuaError.FromStack(state, status)); + LuaError.FromStack(state, status)); } state.RawSetPointer(LuaState.RegistryIndex, s_metatableKey); diff --git a/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListExitTests.cs b/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListExitTests.cs index af98277a..ee5381d5 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListExitTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListExitTests.cs @@ -68,9 +68,9 @@ public void Symbolic_address_expression_stays_distinct_from_the_resolved_current { using AddressListTestHost host = new(); CEObject handle = host.AddRecord(1, extra: """ - o.props.Address = "game.exe+10" - o.getters.getCurrentAddress = function() return function() return 0x140000010 end end - """); + o.props.Address = "game.exe+10" + o.getters.getCurrentAddress = function() return function() return 0x140000010 end end + """); MemoryRecord record = new(handle); Assert.True(record.TryGetAddressExpression(out string? expression)); @@ -124,11 +124,11 @@ public void Mutation_during_a_table_load_is_refused() List mutations = []; List activations = []; using (FakeHost.InstallReentrantHook(host.State, "table_script", () => - { - mutations.Add(AddressListMutations.Delete(new MemoryRecordId(1))); - mutations.Add(AddressListMutations.SetParent(new MemoryRecordId(1), new MemoryRecordId(2))); - activations.Add(AddressListMutations.SetActive(new MemoryRecordId(1), true)); - })) + { + mutations.Add(AddressListMutations.Delete(new MemoryRecordId(1))); + mutations.Add(AddressListMutations.SetParent(new MemoryRecordId(1), new MemoryRecordId(2))); + activations.Add(AddressListMutations.SetActive(new MemoryRecordId(1), true)); + })) { host.Execute("loadTable = function(path, merge) table_script() end"); diff --git a/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListTestHost.cs b/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListTestHost.cs index cd64d577..4ac2e406 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListTestHost.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListTestHost.cs @@ -18,14 +18,13 @@ namespace CheatEngine.SDK.Engine.Tests.AddressList; internal sealed class AddressListTestHost : IDisposable { private readonly NativeLuaState _nativeState; - private readonly HostScope _scope; public AddressListTestHost() { EngineTest.RequireNativeLua(); _nativeState = new NativeLuaState(); - _scope = new HostScope(_nativeState); - State = _scope.State; + Scope = new HostScope(_nativeState); + State = Scope.State; CEObject list = FakeHost.CreateObject(State, "Probe"); FakeHost.SetGlobalObject(State, "list", list); EngineTest.Run(State, """ @@ -43,36 +42,45 @@ public LuaState State get; } - public HostScope Scope => _scope; + public HostScope Scope + { + get; + } + + public void Dispose() + { + Scope.Dispose(); + _nativeState.Dispose(); + } /// Creates a record with , adds it to records and returns its handle. public CEObject AddRecord(int id, string mode = "apply", bool active = false, string extra = "") { string initializer = string.Create(CultureInfo.InvariantCulture, $$""" - o.props.ID = {{id}} - o.props.Active = {{(active ? "true" : "false")}} - o.props.AsyncProcessing = false - o.props.Async = false - o.mode = "{{mode}}" - o.getters.destroy = function(o) - return function() - delete_calls = delete_calls + 1 - if o.gone then error("object already destroyed") end - o.gone = true - records[o.props.ID] = nil - end - end - o.setters.Active = function(o, value) - active_set_calls = active_set_calls + 1 - if o.mode == "refuse" then return end - if o.mode == "retry-request" then retry_requested = retry_requested + 1 return end - o.props.Active = value - if o.mode == "raise" then error("activation raised after it started") end - if o.mode == "async" then o.props.AsyncProcessing = true end - if o.mode == "post-read-fails" then o.getters.Active = function() error("record vanished") end end - end - {{extra}} - """); + o.props.ID = {{id}} + o.props.Active = {{(active ? "true" : "false")}} + o.props.AsyncProcessing = false + o.props.Async = false + o.mode = "{{mode}}" + o.getters.destroy = function(o) + return function() + delete_calls = delete_calls + 1 + if o.gone then error("object already destroyed") end + o.gone = true + records[o.props.ID] = nil + end + end + o.setters.Active = function(o, value) + active_set_calls = active_set_calls + 1 + if o.mode == "refuse" then return end + if o.mode == "retry-request" then retry_requested = retry_requested + 1 return end + o.props.Active = value + if o.mode == "raise" then error("activation raised after it started") end + if o.mode == "async" then o.props.AsyncProcessing = true end + if o.mode == "post-read-fails" then o.getters.Active = function() error("record vanished") end end + end + {{extra}} + """); CEObject record = FakeHost.CreateObject(State, "Probe", initializer); FakeHost.SetGlobalObject(State, "new_record", record); EngineTest.Run(State, Encoding.UTF8.GetBytes( @@ -93,10 +101,4 @@ public long ReadInteger(string name) Assert.True(State.TryGetGlobal(Encoding.UTF8.GetBytes(name)).IsOk); return EngineTest.ReadInteger(State, -1); } - - public void Dispose() - { - _scope.Dispose(); - _nativeState.Dispose(); - } } diff --git a/tests/CheatEngine.SDK.Engine.Tests/AddressList/MemoryRecordActivationTests.cs b/tests/CheatEngine.SDK.Engine.Tests/AddressList/MemoryRecordActivationTests.cs index 7f2fa535..ec0c2fad 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/AddressList/MemoryRecordActivationTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/AddressList/MemoryRecordActivationTests.cs @@ -183,10 +183,10 @@ public void Memory_record_active_script_and_offset_count_reads_restore_the_stack { using AddressListTestHost host = new(); CEObject handle = host.AddRecord(1, active: true, extra: """ - o.props.Script = "[ENABLE]\n[DISABLE]" - o.props.OffsetCount = 2 - o.props.Async = true - """); + o.props.Script = "[ENABLE]\n[DISABLE]" + o.props.OffsetCount = 2 + o.props.Async = true + """); CEObject plain = host.AddRecord(2, extra: "o.props.OffsetCount = 'many'"); MemoryRecord record = new(handle); MemoryRecord other = new(plain); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Allocation/AllocatedRegionTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Allocation/AllocatedRegionTests.cs index e7669a44..1adecf61 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Allocation/AllocatedRegionTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Allocation/AllocatedRegionTests.cs @@ -14,10 +14,7 @@ public sealed class AllocatedRegionTests [Fact] public void Dispose_releases_the_original_target_address_and_size_exactly_once() { - AllocationOperationsFake operations = new() - { - AllocatedAddress = new Address(0x7FF6_3000_0000) - }; + AllocationOperationsFake operations = new() { AllocatedAddress = new Address(0x7FF6_3000_0000) }; AllocatedRegion region = Allocate(operations, 12288); region.Dispose(); @@ -34,10 +31,7 @@ public void Dispose_releases_the_original_target_address_and_size_exactly_once() [Fact] public void Dispose_when_CE_reports_failure_is_no_throw_and_consumes_ownership() { - AllocationOperationsFake operations = new() - { - DeallocationResult = false - }; + AllocationOperationsFake operations = new() { DeallocationResult = false }; AllocatedRegion region = Allocate(operations, 4096); region.Dispose(); @@ -50,10 +44,7 @@ public void Dispose_when_CE_reports_failure_is_no_throw_and_consumes_ownership() [Fact] public void Release_when_CE_reports_failure_throws_the_expected_failure_and_never_retries() { - AllocationOperationsFake operations = new() - { - DeallocationResult = false - }; + AllocationOperationsFake operations = new() { DeallocationResult = false }; AllocatedRegion region = Allocate(operations, 4096); EngineOperationFailedException exception = Assert.Throws(region.Release); @@ -69,10 +60,7 @@ public void Release_when_CE_reports_failure_throws_the_expected_failure_and_neve public void Release_when_the_protected_lua_call_fails_preserves_the_failure_and_consumes_ownership() { EngineLuaException failure = new("TargetMemoryDeallocate", LuaStatus.RuntimeError); - AllocationOperationsFake operations = new() - { - DeallocationException = failure - }; + AllocationOperationsFake operations = new() { DeallocationException = failure }; AllocatedRegion region = Allocate(operations, 4096); EngineLuaException thrown = Assert.Throws(region.Release); @@ -87,10 +75,7 @@ public void Release_when_the_protected_lua_call_fails_preserves_the_failure_and_ public void Release_when_the_required_global_is_unavailable_preserves_the_distinct_failure() { EngineGlobalUnavailableException failure = new("TargetMemoryDeallocate"); - AllocationOperationsFake operations = new() - { - DeallocationException = failure - }; + AllocationOperationsFake operations = new() { DeallocationException = failure }; AllocatedRegion region = Allocate(operations, 4096); EngineGlobalUnavailableException thrown = Assert.Throws(region.Release); @@ -106,10 +91,7 @@ public void Release_when_the_binding_contract_fails_preserves_the_failure_and_co { EngineBindingException failure = new("TargetMemoryDeallocate", "the generated binding returned an incompatible result"); - AllocationOperationsFake operations = new() - { - DeallocationException = failure - }; + AllocationOperationsFake operations = new() { DeallocationException = failure }; AllocatedRegion region = Allocate(operations, 4096); EngineBindingException thrown = Assert.Throws(region.Release); @@ -124,10 +106,7 @@ public void Release_when_the_result_cannot_be_marshalled_preserves_the_failure_a { EngineMarshallingException failure = new("TargetMemoryDeallocate", EngineMarshallingDirection.Result, "a boolean", "a table"); - AllocationOperationsFake operations = new() - { - DeallocationException = failure - }; + AllocationOperationsFake operations = new() { DeallocationException = failure }; AllocatedRegion region = Allocate(operations, 4096); EngineMarshallingException thrown = Assert.Throws(region.Release); @@ -158,10 +137,7 @@ public void Dispose_when_the_binding_fails_is_no_throw_and_consumes_ownership() public void Dispose_when_an_EngineException_occurs_preserves_the_structured_failure_kind_and_consumes_ownership() { EngineException failure = new EngineLuaException("TargetMemoryDeallocate", LuaStatus.RuntimeError); - AllocationOperationsFake operations = new() - { - DeallocationException = failure - }; + AllocationOperationsFake operations = new() { DeallocationException = failure }; AllocatedRegion region = Allocate(operations, 4096); region.Dispose(); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Allocation/LuaTargetMemoryAllocationOperationsTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Allocation/LuaTargetMemoryAllocationOperationsTests.cs index 7b1238b5..af70f6e6 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Allocation/LuaTargetMemoryAllocationOperationsTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Allocation/LuaTargetMemoryAllocationOperationsTests.cs @@ -424,7 +424,7 @@ function deAlloc(address, size) private static void InstallCurrentTarget(LuaState state) { EngineTest.Run(state, Encoding.UTF8.GetBytes("function getOpenedProcessID() return " + - Environment.ProcessId + " end")); + Environment.ProcessId + " end")); EngineTest.Run(state, FakeHost.LocalTargetBackendChunk); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Allocation/TargetMemoryAllocatorTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Allocation/TargetMemoryAllocatorTests.cs index bd647e2a..ef5838ef 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Allocation/TargetMemoryAllocatorTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Allocation/TargetMemoryAllocatorTests.cs @@ -40,10 +40,7 @@ public void Allocate_when_owner_publication_fails_compensates_once_and_exposes_t [Fact] public void Allocate_when_owner_publication_and_compensation_fail_reports_an_unconfirmed_effect_without_retrying() { - AllocationOperationsFake operations = new() - { - DeallocationResult = false - }; + AllocationOperationsFake operations = new() { DeallocationResult = false }; TargetMemoryAllocator allocator = new(operations); EngineResourceHandoffException exception = Assert.Throws(() => @@ -62,10 +59,7 @@ public void Allocate_when_owner_publication_and_compensation_raise_keeps_the_primary_cause_and_marks_the_effect_unknown() { EngineLuaException cleanupFailure = new("TargetMemoryDeallocate", LuaStatus.RuntimeError); - AllocationOperationsFake operations = new() - { - DeallocationException = cleanupFailure - }; + AllocationOperationsFake operations = new() { DeallocationException = cleanupFailure }; TargetMemoryAllocator allocator = new(operations); InvalidOperationException cause = new("injected region publication failure"); @@ -103,10 +97,7 @@ public void Allocate_when_owner_publication_observes_a_replacement_target_refuse [Fact] public void Allocate_on_success_returns_an_owned_region_and_forwards_the_full_request() { - AllocationOperationsFake operations = new() - { - AllocatedAddress = new Address(0x7FF6_1234_0000) - }; + AllocationOperationsFake operations = new() { AllocatedAddress = new Address(0x7FF6_1234_0000) }; TargetMemoryAllocator allocator = new(operations); TargetAllocationRequest request = new(new TargetAllocationSize(8192), new Address(0x7FF6_1200_0000), MemoryProtection.ExecuteReadWrite); @@ -122,11 +113,7 @@ public void Allocate_on_success_returns_an_owned_region_and_forwards_the_full_re [Fact] public void Allocate_when_CE_reports_expected_failure_throws_the_stable_expected_failure() { - AllocationOperationsFake operations = new() - { - AllocationResult = false, - AllocatedAddress = Address.Zero - }; + AllocationOperationsFake operations = new() { AllocationResult = false, AllocatedAddress = Address.Zero }; TargetMemoryAllocator allocator = new(operations); EngineOperationFailedException exception = Assert.Throws(() => @@ -140,10 +127,7 @@ public void Allocate_when_CE_reports_expected_failure_throws_the_stable_expected [Fact] public void Allocate_when_CE_reports_success_without_an_address_preserves_the_unknown_effect_diagnostic() { - AllocationOperationsFake operations = new() - { - AllocatedAddress = Address.Zero - }; + AllocationOperationsFake operations = new() { AllocatedAddress = Address.Zero }; TargetMemoryAllocator allocator = new(operations); EngineResourceHandoffException exception = Assert.Throws(() => @@ -160,11 +144,7 @@ public void Allocate_when_CE_reports_success_without_an_address_preserves_the_un public void Allocate_when_CE_reports_failure_with_an_address_throws_marshalling() { AllocationOperationsFake operations = - new() - { - AllocationResult = false, - AllocatedAddress = new Address(0x1234) - }; + new() { AllocationResult = false, AllocatedAddress = new Address(0x1234) }; TargetMemoryAllocator allocator = new(operations); EngineMarshallingException exception = Assert.Throws(() => @@ -179,10 +159,7 @@ public void Allocate_when_the_binding_fails_preserves_the_binding_exception() { EngineBindingException failure = new("TargetMemoryAllocate", "the generated binding returned an incompatible result"); - AllocationOperationsFake operations = new() - { - AllocationException = failure - }; + AllocationOperationsFake operations = new() { AllocationException = failure }; TargetMemoryAllocator allocator = new(operations); EngineBindingException thrown = Assert.Throws(() => @@ -195,10 +172,7 @@ public void Allocate_when_the_binding_fails_preserves_the_binding_exception() public void Allocate_when_the_required_global_is_unavailable_preserves_that_distinct_failure() { EngineGlobalUnavailableException failure = new("TargetMemoryAllocate"); - AllocationOperationsFake operations = new() - { - AllocationException = failure - }; + AllocationOperationsFake operations = new() { AllocationException = failure }; TargetMemoryAllocator allocator = new(operations); EngineGlobalUnavailableException thrown = Assert.Throws(() => @@ -212,10 +186,7 @@ public void Allocate_when_the_required_global_is_unavailable_preserves_that_dist public void Allocate_when_the_protected_lua_call_fails_preserves_the_EngineLuaException() { EngineLuaException failure = new("TargetMemoryAllocate", LuaStatus.RuntimeError); - AllocationOperationsFake operations = new() - { - AllocationException = failure - }; + AllocationOperationsFake operations = new() { AllocationException = failure }; TargetMemoryAllocator allocator = new(operations); EngineLuaException thrown = Assert.Throws(() => @@ -282,10 +253,7 @@ public void Allocate_with_a_target_bound_boundary_failure_throws_its_stable_publ [Fact] public void ReleaseWithOutcome_adapts_the_legacy_bool_seam_and_consumes_ownership() { - AllocationOperationsFake operations = new() - { - DeallocationResult = false - }; + AllocationOperationsFake operations = new() { DeallocationResult = false }; TargetMemoryAllocator allocator = new(operations); AllocatedRegion region = allocator.Allocate(new TargetAllocationRequest(new TargetAllocationSize(4096))); @@ -339,10 +307,7 @@ method.Name is not (nameof(ITargetMemoryAllocationOperations.TryAllocate) or [Fact] public void TryAllocate_success_returns_an_owner_with_its_incarnation_and_runtime_origin() { - AllocationOperationsFake operations = new() - { - AllocatedAddress = new Address(0x7FF6_1234_0000) - }; + AllocationOperationsFake operations = new() { AllocatedAddress = new Address(0x7FF6_1234_0000) }; TargetMemoryAllocator allocator = new(operations); TargetAllocationRequest request = new(new TargetAllocationSize(8192)); @@ -370,15 +335,12 @@ public void TryAllocate_success_returns_an_owner_with_its_incarnation_and_runtim [Fact] public void TryAllocate_expected_failure_reports_not_applied_without_an_owner() { - AllocationOperationsFake operations = new() - { - AllocationResult = false, - AllocatedAddress = Address.Zero - }; + AllocationOperationsFake operations = new() { AllocationResult = false, AllocatedAddress = Address.Zero }; TargetMemoryAllocator allocator = new(operations); TargetAllocationAcquireOutcome outcome = - allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), out AllocatedRegion? region); + allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), + out AllocatedRegion? region); Assert.Null(region); Assert.False(outcome.HasOwner); @@ -400,7 +362,8 @@ public void TryAllocate_unqualified_target_reports_not_started_before_the_effect TargetMemoryAllocator allocator = new(operations); TargetAllocationAcquireOutcome outcome = - allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), out AllocatedRegion? region); + allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), + out AllocatedRegion? region); Assert.Null(region); Assert.False(outcome.HasOwner); @@ -439,8 +402,7 @@ public void TryAllocate_publication_and_compensation_failure_keeps_the_allocated { AllocationOperationsFake operations = new() { - AllocatedAddress = new Address(0x7FF6_5555_0000), - DeallocationResult = false + AllocatedAddress = new Address(0x7FF6_5555_0000), DeallocationResult = false }; TargetMemoryAllocator allocator = new(operations); @@ -466,7 +428,8 @@ public void TryAllocate_with_only_the_compatibility_seam_refuses_without_an_effe TargetMemoryAllocator allocator = new(operations); TargetAllocationAcquireOutcome outcome = - allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), out AllocatedRegion? region); + allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), + out AllocatedRegion? region); Assert.Null(region); Assert.False(outcome.HasOwner); @@ -481,14 +444,12 @@ public void TryAllocate_with_only_the_compatibility_seam_refuses_without_an_effe [Fact] public void TryAllocate_success_without_an_address_is_a_marshalling_failure_with_unknown_effect() { - AllocationOperationsFake operations = new() - { - AllocatedAddress = Address.Zero - }; + AllocationOperationsFake operations = new() { AllocatedAddress = Address.Zero }; TargetMemoryAllocator allocator = new(operations); TargetAllocationAcquireOutcome outcome = - allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), out AllocatedRegion? region); + allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), + out AllocatedRegion? region); Assert.Null(region); Assert.Equal(EngineEffectState.Unknown, outcome.Effect); @@ -502,13 +463,13 @@ public void TryAllocate_failure_that_still_carries_an_address_keeps_it_and_repor { AllocationOperationsFake operations = new() { - AllocationResult = false, - AllocatedAddress = new Address(0x1234) + AllocationResult = false, AllocatedAddress = new Address(0x1234) }; TargetMemoryAllocator allocator = new(operations); TargetAllocationAcquireOutcome outcome = - allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), out AllocatedRegion? region); + allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), + out AllocatedRegion? region); Assert.Null(region); Assert.Equal(EngineEffectState.Unknown, outcome.Effect); @@ -528,7 +489,8 @@ public void TryAllocate_on_an_unqualified_target_after_the_effect_refuses_compen TargetMemoryAllocator allocator = new(operations); TargetAllocationAcquireOutcome outcome = - allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), out AllocatedRegion? region); + allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), + out AllocatedRegion? region); Assert.Null(region); Assert.False(outcome.HasOwner); @@ -554,19 +516,18 @@ public void TryAllocate_turns_a_binding_exception_into_an_outcome_without_parsin EngineFailureKind.GlobalUnavailable => new EngineGlobalUnavailableException("TargetMemoryAllocate"), EngineFailureKind.TargetIdentityUnavailable => new EngineTargetIdentityException("TargetMemoryAllocate", TargetSelection.CreateUnavailableCheck(TargetSelectionObservation.NoTarget())), - EngineFailureKind.ProtectedLuaFailure => new EngineLuaException("TargetMemoryAllocate", LuaStatus.SyntaxError, + EngineFailureKind.ProtectedLuaFailure => new EngineLuaException("TargetMemoryAllocate", + LuaStatus.SyntaxError, "A deliberately irrelevant localized message."), EngineFailureKind.BindingFailure => new EngineBindingException("TargetMemoryAllocate", "incompatible"), _ => new EngineMarshallingException("TargetMemoryAllocate", EngineMarshallingDirection.Result, "a", "b") }; - AllocationOperationsFake operations = new() - { - AllocationException = failure - }; + AllocationOperationsFake operations = new() { AllocationException = failure }; TargetMemoryAllocator allocator = new(operations); TargetAllocationAcquireOutcome outcome = - allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), out AllocatedRegion? region); + allocator.TryAllocate(new TargetAllocationRequest(new TargetAllocationSize(4096)), + out AllocatedRegion? region); Assert.Null(region); Assert.Equal(expectedEffect, outcome.Effect); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerDisableInfoSnapshotTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerDisableInfoSnapshotTests.cs index 13ea8eec..64dcc917 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerDisableInfoSnapshotTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerDisableInfoSnapshotTests.cs @@ -36,9 +36,11 @@ public void Snapshot_projects_allocations_symbols_exception_ranges_and_registere } """u8); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); - AutoAssemblerDisableInfoSnapshot snapshot = Assert.IsType(outcome.DisableInfo); + AutoAssemblerDisableInfoSnapshot + snapshot = Assert.IsType(outcome.DisableInfo); Assert.Equal(AutoAssemblerDisableInfoSnapshotStatus.Complete, snapshot.Status); Assert.Collection(snapshot.Allocations, static code => @@ -58,7 +60,10 @@ public void Snapshot_projects_allocations_symbols_exception_ranges_and_registere Assert.Equal(["player_base", "ammo"], snapshot.RegisteredSymbols); Assert.Equal([new Address(0x140000010), new Address(0x140000020)], snapshot.ExceptionRanges); Assert.Equal( - [new AutoAssemblerSymbolInfo("newmem", new Address(0x140000000)), new AutoAssemblerSymbolInfo("return_here", new Address(0x140001005))], + [ + new AutoAssemblerSymbolInfo("newmem", new Address(0x140000000)), + new AutoAssemblerSymbolInfo("return_here", new Address(0x140001005)) + ], snapshot.Symbols); Assert.False(snapshot.HasCCodeSymbolList); Assert.IsNotType(snapshot.Allocations); @@ -84,12 +89,14 @@ public void Snapshot_sorts_entries_by_ordinal_name() } """u8); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); AutoAssemblerDisableInfoSnapshot snapshot = outcome.DisableInfo!; Assert.Equal(["B", "_z", "a", "b"], snapshot.Allocations.Select(static allocation => allocation.Name), StringComparer.Ordinal); - Assert.Equal(["B", "_z", "a", "b"], snapshot.Symbols.Select(static symbol => symbol.Name), StringComparer.Ordinal); + Assert.Equal(["B", "_z", "a", "b"], snapshot.Symbols.Select(static symbol => symbol.Name), + StringComparer.Ordinal); patch!.Dispose(); Assert.Equal(0, L.Top); } @@ -110,7 +117,8 @@ public void Snapshot_keeps_addresses_above_2_pow_63_exactly() } """u8); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); AutoAssemblerDisableInfoSnapshot snapshot = outcome.DisableInfo!; Assert.Equal(AutoAssemblerDisableInfoSnapshotStatus.Complete, snapshot.Status); @@ -138,11 +146,7 @@ public void Snapshot_truncates_at_the_entry_and_name_limits() symbols = { short = 1, far_too_long_a_name = 2 }, } """u8); - AutoAssemblerOptions options = new() - { - MaxDisableInfoEntries = 2, - MaxDisableInfoNameBytes = 8 - }; + AutoAssemblerOptions options = new() { MaxDisableInfoEntries = 2, MaxDisableInfoNameBytes = 8 }; AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", options, out AutoAssemblerPatch? patch); @@ -181,7 +185,8 @@ public void Malformed_disable_info_publishes_the_patch_with_a_malformed_snapshot } """u8); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); Assert.Equal(AutoAssemblerApplyOutcomeKind.Applied, outcome.Kind); Assert.Equal(EngineEffectState.Applied, outcome.Effect); @@ -215,7 +220,8 @@ public void Ccode_symbol_list_is_reported_but_never_owned_or_destroyed() EngineTest.Run(L, "aa_disable_info = { ccodesymbols = aa_ccode_symbols }"u8); long destroyed = FakeHost.DestroyedCount(L); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); patch!.Dispose(); Assert.True(outcome.DisableInfo!.HasCCodeSymbolList); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerOutcomeTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerOutcomeTests.cs index 11aa453d..d4f86a44 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerOutcomeTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerOutcomeTests.cs @@ -1,3 +1,5 @@ +using System.Text; + using CheatEngine.SDK.Engine.Assembly; using CheatEngine.SDK.Engine.Objects; using CheatEngine.SDK.Engine.Targets; @@ -30,7 +32,8 @@ public void TryApplyWithOutcome_applied_publishes_the_patch_with_its_origin_and_ LuaState L = scope.State; AutoAssemblerTestHost.Install(L); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); Assert.Equal(AutoAssemblerApplyOutcomeKind.Applied, outcome.Kind); Assert.Equal(EngineEffectState.Applied, outcome.Effect); @@ -38,7 +41,8 @@ public void TryApplyWithOutcome_applied_publishes_the_patch_with_its_origin_and_ Assert.Null(outcome.Compensation); Assert.True(outcome.TargetObservation.IsQualified); Assert.True(outcome.PostEffectTargetCheck.GetValueOrDefault().IsCurrent); - AutoAssemblerDisableInfoSnapshot snapshot = Assert.IsType(outcome.DisableInfo); + AutoAssemblerDisableInfoSnapshot + snapshot = Assert.IsType(outcome.DisableInfo); Assert.Equal(AutoAssemblerDisableInfoSnapshotStatus.Complete, snapshot.Status); AutoAssemblerPatch owner = Assert.IsType(patch); Assert.Same(snapshot, owner.DisableInfo); @@ -64,7 +68,8 @@ public void TryApplyWithOutcome_rejected_reports_unknown_effect_and_no_owner() LuaState L = scope.State; AutoAssemblerTestHost.Install(L); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("apply-false", out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome("apply-false", out AutoAssemblerPatch? patch); Assert.Equal(AutoAssemblerApplyOutcomeKind.Rejected, outcome.Kind); Assert.Equal(EngineEffectState.Unknown, outcome.Effect); @@ -112,7 +117,7 @@ public void TryApplyWithOutcome_diagnostic_is_truncated_at_a_scalar_boundary(str using HostScope scope = new(state); LuaState L = scope.State; AutoAssemblerTestHost.Install(L); - EngineTest.Run(L, System.Text.Encoding.UTF8.GetBytes("aa_long_detail = \"" + luaEscapedDetail + "\"")); + EngineTest.Run(L, Encoding.UTF8.GetBytes("aa_long_detail = \"" + luaEscapedDetail + "\"")); AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("apply-reject-long", new AutoAssemblerOptions { CaptureHostText = true, MaxHostTextBytes = maxBytes }, out _); @@ -210,7 +215,8 @@ public void TryApplyWithOutcome_success_without_warnings_reports_none() LuaState L = scope.State; AutoAssemblerTestHost.Install(L); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", SCapture, out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome("success", SCapture, out AutoAssemblerPatch? patch); Assert.False(outcome.HasHostWarnings); Assert.Null(outcome.HostWarnings); @@ -230,7 +236,8 @@ public void TryApplyWithOutcome_success_without_a_table_is_invalid_result_with_u LuaState L = scope.State; AutoAssemblerTestHost.Install(L); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome(script, out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome(script, out AutoAssemblerPatch? patch); Assert.Equal(AutoAssemblerApplyOutcomeKind.InvalidResult, outcome.Kind); Assert.Equal(EngineEffectState.Unknown, outcome.Effect); @@ -292,7 +299,8 @@ public void TryApplyWithOutcome_publication_failure_reports_one_compensation_and Assert.False(outcome.HasPatch); Assert.IsType(cause); Assert.Equal(TargetReleaseStatus.Released, outcome.Compensation.GetValueOrDefault().Status); - AutoAssemblerDisableInfoSnapshot snapshot = Assert.IsType(outcome.DisableInfo); + AutoAssemblerDisableInfoSnapshot + snapshot = Assert.IsType(outcome.DisableInfo); Assert.Equal("newmem", Assert.Single(snapshot.Symbols).Name); Assert.Equal(1, AutoAssemblerTestHost.ReadCounter(L, "auto_assembler_disable_count")); Assert.True(AutoAssemblerTestHost.ReadBoolean(L, "auto_assembler_disable_received_info")); @@ -308,7 +316,8 @@ public void TryApplyWithOutcome_missing_global_reports_not_started_and_restores_ LuaState L = scope.State; FakeHost.InstallQualifiedLocalTarget(L); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); AutoAssemblerCheckOutcome check = AutoAssemblerPatcher.TryCheck("success", true); Assert.Equal(AutoAssemblerApplyOutcomeKind.GlobalUnavailable, outcome.Kind); @@ -355,7 +364,8 @@ public void TryApplyWithOutcome_unqualified_target_reports_not_started_before_an AutoAssemblerTestHost.Install(L); AutoAssemblerTestHost.SelectTarget(L, 0); - AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); + AutoAssemblerApplyOutcome outcome = + AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); Assert.Equal(AutoAssemblerApplyOutcomeKind.TargetIdentityUnavailable, outcome.Kind); Assert.Equal(EngineEffectState.NotStarted, outcome.Effect); @@ -374,7 +384,8 @@ public void TryApplyWithOutcome_protected_failure_reports_unknown_effect_and_rec LuaState L = scope.State; AutoAssemblerTestHost.Install(L); - AutoAssemblerApplyOutcome failed = AutoAssemblerPatcher.TryApplyWithOutcome("apply-raise", out AutoAssemblerPatch? none); + AutoAssemblerApplyOutcome failed = + AutoAssemblerPatcher.TryApplyWithOutcome("apply-raise", out AutoAssemblerPatch? none); Assert.Equal(0, L.Top); AutoAssemblerApplyOutcome recovered = AutoAssemblerPatcher.TryApplyWithOutcome("success", out AutoAssemblerPatch? patch); @@ -398,7 +409,8 @@ public void TryApplyWithOutcome_localized_error_text_never_changes_the_category( AutoAssemblerTestHost.Install(L); AutoAssemblerApplyOutcome english = AutoAssemblerPatcher.TryApplyWithOutcome("apply-false", SCapture, out _); - AutoAssemblerApplyOutcome french = AutoAssemblerPatcher.TryApplyWithOutcome("apply-reject-french", SCapture, out _); + AutoAssemblerApplyOutcome french = + AutoAssemblerPatcher.TryApplyWithOutcome("apply-reject-french", SCapture, out _); Assert.Equal(english.Kind, french.Kind); Assert.Equal(english.Effect, french.Effect); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerPatcherTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerPatcherTests.cs index e68c3c3b..0dd1c134 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerPatcherTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerPatcherTests.cs @@ -189,7 +189,8 @@ public void ReleaseWithTargetOutcome_when_the_current_target_differs_refuses_wit LuaRef disableInfo = scope.State.CreateRef(); int originalTargetId = Environment.ProcessId == 1 ? 2 : 1; AutoAssemblerPatch patch = new("success", disableInfo, - new EngineResourceOrigin(LuaRuntime.CurrentStateIdentity, new TargetProcessIncarnation(originalTargetId, 1)), + new EngineResourceOrigin(LuaRuntime.CurrentStateIdentity, + new TargetProcessIncarnation(originalTargetId, 1)), snapshot, null); TargetReleaseOutcome outcome = patch.ReleaseWithTargetOutcome(); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Assembly/InstructionOperationsTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Assembly/InstructionOperationsTests.cs index 6500303b..57332b70 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Assembly/InstructionOperationsTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Assembly/InstructionOperationsTests.cs @@ -103,7 +103,8 @@ public void observe_current_rejects_a_target_reported_in_neither_family(bool is6 [Fact] [Trait("Qualification", "Q32")] - public void observe_current_without_a_selected_target_reports_target_not_selected_although_the_probes_look_like_x64() + public void + observe_current_without_a_selected_target_reports_target_not_selected_although_the_probes_look_like_x64() { EngineTest.RequireNativeLua(); using NativeLuaState state = new(); @@ -204,7 +205,8 @@ function targetIsArm() InstructionOperationStatus failed = InstructionProfiles.TryObserveCurrent(out _); Assert.Equal(0, scope.State.Top); EngineTest.Run(scope.State, "raise_isa_probe = false"u8); - InstructionOperationStatus recovered = InstructionProfiles.TryObserveCurrent(out InstructionTargetProfile profile); + InstructionOperationStatus recovered = + InstructionProfiles.TryObserveCurrent(out InstructionTargetProfile profile); Assert.Equal(InstructionOperationStatus.LuaFailure, failed); Assert.Equal(InstructionOperationStatus.Success, recovered); @@ -418,7 +420,9 @@ public void assemble_reports_a_target_change_after_the_effect_without_copying_by InstallInstructionGlobals(scope.State); InstructionTargetProfile targetProfile = Observe(scope.State); EngineTest.Run(scope.State, Encoding.UTF8.GetBytes("instruction_assemble_behavior = \"target-change\"\n" + - "instruction_assemble_next_process_id = " + selectionAfterEffect.ToString(CultureInfo.InvariantCulture))); + "instruction_assemble_next_process_id = " + + selectionAfterEffect.ToString(CultureInfo + .InvariantCulture))); Span destination = stackalloc byte[1]; destination[0] = 0xA5; diff --git a/tests/CheatEngine.SDK.Engine.Tests/Inspection/EngineInspectionTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Inspection/EngineInspectionTests.cs index df4752eb..9985a1d8 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Inspection/EngineInspectionTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Inspection/EngineInspectionTests.cs @@ -245,14 +245,8 @@ public void ResolveAddress_reports_an_unavailable_global_without_entering_lua() [Fact] public void AddressResolutionOptions_supports_init_and_with() { - AddressResolutionOptions options = new() - { - Shallow = true - }; - AddressResolutionOptions updated = options with - { - Shallow = false - }; + AddressResolutionOptions options = new() { Shallow = true }; + AddressResolutionOptions updated = options with { Shallow = false }; Assert.True(options.Shallow); Assert.False(updated.Shallow); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolLeaseReplacementTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolLeaseReplacementTests.cs index 0e4622b3..fe6326a1 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolLeaseReplacementTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolLeaseReplacementTests.cs @@ -1,3 +1,5 @@ +using System.Text; + using CheatEngine.SDK.Engine.Inspection; using CheatEngine.SDK.Engine.Tests.Support; using CheatEngine.SDK.Engine.Values; @@ -246,15 +248,15 @@ public LuaState State get; } - public void Execute(string source) - { - EngineTest.Run(State, System.Text.Encoding.UTF8.GetBytes(source)); - } - public void Dispose() { _scope.Dispose(); _nativeState.Dispose(); } + + public void Execute(string source) + { + EngineTest.Run(State, Encoding.UTF8.GetBytes(source)); + } } } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolListTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolListTests.cs index a4258a39..c3bf4aa6 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolListTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolListTests.cs @@ -1,4 +1,5 @@ using System.Reflection; +using System.Text; using CheatEngine.SDK.Annotations.Lifetime; using CheatEngine.SDK.Engine.Inspection; @@ -120,7 +121,7 @@ public void Symbol_lookup_distinguishes_not_found_from_a_malformed_symbol_table( LuaOperationStatus badProcessId = list.TryGetProcessId(out _); Assert.Equal(LuaOperationStatusKind.NilResult, notFound.Kind); - Assert.Equal(default(SymbolInfo), none); + Assert.Equal(default, none); Assert.Equal(LuaOperationStatusKind.NilResult, noName.Kind); Assert.Null(name); Assert.True(processId.IsSuccess); @@ -361,13 +362,13 @@ public void Main_symbol_list_is_borrowed_only() foreach (Type type in typeof(SymbolList).Assembly.GetExportedTypes()) { foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | - BindingFlags.Static | BindingFlags.DeclaredOnly)) + BindingFlags.Static | BindingFlags.DeclaredOnly)) { bool takesBorrowedList = (type == typeof(SymbolList) && !method.IsStatic) || - Array.Exists(method.GetParameters(), - static parameter => parameter.ParameterType == typeof(SymbolList)); + Array.Exists(method.GetParameters(), + static parameter => parameter.ParameterType == typeof(SymbolList)); bool lifecycleName = method.Name.Contains("register", StringComparison.OrdinalIgnoreCase) || - method.Name.Contains("destroy", StringComparison.OrdinalIgnoreCase); + method.Name.Contains("destroy", StringComparison.OrdinalIgnoreCase); if (takesBorrowedList && lifecycleName) { offenders.Add(type.Name + "." + method.Name); @@ -376,7 +377,8 @@ public void Main_symbol_list_is_borrowed_only() } Assert.True(offenders.Count == 0, - "A public method registers, unregisters or destroys a borrowed SymbolList: " + string.Join(", ", offenders)); + "A public method registers, unregisters or destroys a borrowed SymbolList: " + + string.Join(", ", offenders)); } [Fact] @@ -422,6 +424,12 @@ public LuaState State public LuaHostBinding Binding => _scope.Binding; + public void Dispose() + { + _scope.Dispose(); + _nativeState.Dispose(); + } + /// Creates a list that the next createSymbolList() call returns. public CEObject StageCreatedList(string initializer = "") { @@ -433,13 +441,7 @@ public CEObject StageCreatedList(string initializer = "") public void Execute(string source) { - EngineTest.Run(State, System.Text.Encoding.UTF8.GetBytes(source)); - } - - public void Dispose() - { - _scope.Dispose(); - _nativeState.Dispose(); + EngineTest.Run(State, Encoding.UTF8.GetBytes(source)); } } } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolRegistryTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolRegistryTests.cs index 02242162..3a879839 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolRegistryTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolRegistryTests.cs @@ -17,21 +17,21 @@ public sealed class SymbolRegistryTests { /// A symbol handler double: registration, removal and name lookup share one table. internal static ReadOnlySpan SymbolHandler => """ - registered_symbols = {} - registrations = 0 - removals = 0 - registerSymbol = function(name, address, doNotSave) - registrations = registrations + 1 - registered_symbols[name] = address - end - unregisterSymbol = function(name) - removals = removals + 1 - registered_symbols[name] = nil - end - getAddressSafe = function(name, isLocal, shallow) - return registered_symbols[name] - end - """u8; + registered_symbols = {} + registrations = 0 + removals = 0 + registerSymbol = function(name, address, doNotSave) + registrations = registrations + 1 + registered_symbols[name] = address + end + unregisterSymbol = function(name) + removals = removals + 1 + registered_symbols[name] = nil + end + getAddressSafe = function(name, isLocal, shallow) + return registered_symbols[name] + end + """u8; [Fact] public void TryGetName_forwards_only_the_source_mapped_address() @@ -224,7 +224,8 @@ public void Owned_registration_publish_failure_compensates_once_and_preserves_th SymbolRegistrationHandoffException exception = Assert.Throws(() => SymbolRegistry.TryRegisterOwnedCore(new SymbolName("Player.Health"), 0x140001000UL, default, - static (name, address, options, identity) => new SymbolRegistrationLease(name, address, options, identity), + static (name, address, options, identity) => + new SymbolRegistrationLease(name, address, options, identity), (_, _) => throw cause)); Assert.Same(cause, exception.InnerException); @@ -283,7 +284,8 @@ public void Owned_registration_publication_failure_with_unavailable_unregister_p SymbolRegistrationHandoffException exception = Assert.Throws(() => SymbolRegistry.TryRegisterOwnedCore(new SymbolName("Player.Health"), 0x140001000UL, default, - static (name, address, options, identity) => new SymbolRegistrationLease(name, address, options, identity), + static (name, address, options, identity) => + new SymbolRegistrationLease(name, address, options, identity), (_, _) => throw cause)); Assert.Same(cause, exception.InnerException); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Memory/AddressTypeSeparationTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Memory/AddressTypeSeparationTests.cs index 18ae454d..d289f6c6 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Memory/AddressTypeSeparationTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Memory/AddressTypeSeparationTests.cs @@ -29,7 +29,7 @@ public void Address_types_expose_no_conversion_to_each_other_or_to_double() string[] conversions = [ .. types.SelectMany(static type => type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.DeclaredOnly)) + BindingFlags.Static | BindingFlags.DeclaredOnly)) .Where(static method => method.Name is "op_Implicit" or "op_Explicit") .Select(Describe) .Order(StringComparer.Ordinal) diff --git a/tests/CheatEngine.SDK.Engine.Tests/Memory/MemoryScalarsFidelityTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Memory/MemoryScalarsFidelityTests.cs index f7fbc3cf..9834e73e 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Memory/MemoryScalarsFidelityTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Memory/MemoryScalarsFidelityTests.cs @@ -1,7 +1,6 @@ using System.Globalization; using System.Text; -using CheatEngine.SDK.Engine.Generated; using CheatEngine.SDK.Engine.Tests.Support; using CheatEngine.SDK.Engine.Values; using CheatEngine.SDK.Tests.Shared.NativeLua; diff --git a/tests/CheatEngine.SDK.Engine.Tests/Objects/OwnershipSurfaceTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Objects/OwnershipSurfaceTests.cs index 377e057e..576714b0 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Objects/OwnershipSurfaceTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Objects/OwnershipSurfaceTests.cs @@ -56,7 +56,7 @@ public void No_public_property_or_get_method_returns_an_owner() foreach (MethodInfo method in type.GetMethods(PublicMembers)) { if (!method.IsSpecialName && method.Name.StartsWith("Get", StringComparison.Ordinal) && - IsOwner(method.ReturnType)) + IsOwner(method.ReturnType)) { offenders.Add(type.Name + "." + method.Name); } @@ -84,7 +84,7 @@ public void Memory_records_are_never_wrapped_in_an_owner() foreach (MethodInfo method in type.GetMethods(PublicMembers)) { if (method.ReturnType == ownedRecord || Array.Exists(method.GetParameters(), - parameter => UnderlyingType(parameter.ParameterType) == ownedRecord)) + parameter => UnderlyingType(parameter.ParameterType) == ownedRecord)) { offenders.Add(type.Name + "." + method.Name); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Processes/ProcessOperationStatusTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Processes/ProcessOperationStatusTests.cs index a56eba41..07ae2e10 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Processes/ProcessOperationStatusTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Processes/ProcessOperationStatusTests.cs @@ -39,7 +39,8 @@ public void named_statuses_carry_their_kind_and_only_success_reports_success() Assert.Equal(kind == ProcessOperationStatusKind.Success, status.IsSuccess); } - Assert.Equal(LuaStatus.RuntimeError, ProcessOperationStatus.ProtectedLuaFailure(LuaStatus.RuntimeError).LuaStatus); + Assert.Equal(LuaStatus.RuntimeError, + ProcessOperationStatus.ProtectedLuaFailure(LuaStatus.RuntimeError).LuaStatus); Assert.Throws(() => ProcessOperationStatus.ProtectedLuaFailure(LuaStatus.Ok)); } } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Processes/RuntimeProcessOperationsTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Processes/RuntimeProcessOperationsTests.cs index 4c8ae58b..fbde4027 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Processes/RuntimeProcessOperationsTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Processes/RuntimeProcessOperationsTests.cs @@ -574,7 +574,8 @@ public void observe_target_architecture_reports_the_file_as_process_sentinel_wit } [Theory] - [InlineData("isConnectedToCEServer", "error('fixture probe failure')", ProcessOperationStatusKind.ProtectedLuaFailure)] + [InlineData("isConnectedToCEServer", "error('fixture probe failure')", + ProcessOperationStatusKind.ProtectedLuaFailure)] [InlineData("isConnectedToCEServer", "return nil", ProcessOperationStatusKind.InvalidResult)] [InlineData("isConnectedToCEServer", "return 'false'", ProcessOperationStatusKind.InvalidResult)] [InlineData("targetIsX86", "error('fixture probe failure')", ProcessOperationStatusKind.ProtectedLuaFailure)] @@ -712,7 +713,8 @@ public void configured_pointer_size_is_not_read_without_a_selected_target() using HostScope scope = new(state); // With no target CE 7.7 still answers getPointerSize() == 8 (spike C3 D2); the SDK must not report it. FakeHost.InstallCe77X64TargetFacts(scope.State, 0); - EngineTest.Run(scope.State, "function getPointerSize() error('getPointerSize must not be read without a target') end"u8); + EngineTest.Run(scope.State, + "function getPointerSize() error('getPointerSize must not be read without a target') end"u8); ProcessOperationStatus status = RuntimeProcessOperations.TryGetConfiguredPointerSize(out int rawBytes, out PointerSize pointerSize); @@ -769,7 +771,8 @@ public void configured_pointer_size_reads_only_the_pid_and_get_pointer_size(stri [InlineData("getPointerSize = nil", ProcessOperationStatusKind.GlobalUnavailable)] [InlineData("rt_process_id = 4294967295", ProcessOperationStatusKind.FileAsProcessTarget)] [InlineData("function getPointerSize() rt_process_id = 77 return 8 end", ProcessOperationStatusKind.TargetChanged)] - [InlineData("function getPointerSize() error('fixture failure') end", ProcessOperationStatusKind.ProtectedLuaFailure)] + [InlineData("function getPointerSize() error('fixture failure') end", + ProcessOperationStatusKind.ProtectedLuaFailure)] public void configured_pointer_size_keeps_availability_backend_change_and_lua_failures_distinct(string fixture, ProcessOperationStatusKind expected) { @@ -848,7 +851,7 @@ local function forbidden(name) private static void InstallCurrentProcessGlobals(LuaState state, int processId, bool is64Bit) { string source = "function getOpenedProcessID() return " + processId + " end\n" + - "function targetIs64Bit() return " + LuaBoolean(is64Bit) + " end"; + "function targetIs64Bit() return " + LuaBoolean(is64Bit) + " end"; EngineTest.Run(state, Encoding.UTF8.GetBytes(source)); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/README.md b/tests/CheatEngine.SDK.Engine.Tests/README.md index 545158ba..11a6b421 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/README.md +++ b/tests/CheatEngine.SDK.Engine.Tests/README.md @@ -46,8 +46,8 @@ behavior. - A typed operation acquires the state once and pushes the object once (`HostCallCountTests`). - `Owned` destroys the object exactly once. After the plugin is disabled, `Dispose` throws and leaves the object alive; after a re-enable or a controlled state replacement, every release path consumes the owner without a call and - reports `RefusedRuntimeChanged`. `ReleaseWithOutcome` never throws, and a transfer keeps the origin - (`OwnedTests`, `EngineResourceOriginTests`, `OwnershipSurfaceTests`). + reports `RefusedRuntimeChanged`. `ReleaseWithOutcome` never throws, and a transfer keeps the origin (`OwnedTests`, + `EngineResourceOriginTests`, `OwnershipSurfaceTests`). - Enum values and Cheat Engine names are pinned by literals. - `RuntimeInfo`/`RuntimeCapabilities` retain explicit unknown facts. `TargetMemory` and `HostMemory` keep their address types separate, preserve byte ordering through span calls, and distinguish expected read/write failures. diff --git a/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeCapabilityProbesTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeCapabilityProbesTests.cs index 36c6567b..206bb99a 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeCapabilityProbesTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeCapabilityProbesTests.cs @@ -1,6 +1,5 @@ using System.Text; -using CheatEngine.SDK.Engine.Generated; using CheatEngine.SDK.Engine.Processes; using CheatEngine.SDK.Engine.Runtime; using CheatEngine.SDK.Engine.Tests.Support; diff --git a/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeContractsTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeContractsTests.cs index 9242b80c..2396aab3 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeContractsTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeContractsTests.cs @@ -280,10 +280,7 @@ public void cheat_engine_host_observation_keeps_each_fact_separate() { CheatEngineHostObservation host = new(null, CheatEngineArchitecture.X64, null, CheatEngineOperatingSystem.Unknown); - CheatEngineHostObservation reported = host with - { - CheatEngineIs64Bit = false - }; + CheatEngineHostObservation reported = host with { CheatEngineIs64Bit = false }; Assert.Null(host.FileVersion); Assert.Null(host.CheatEngineIs64Bit); @@ -431,10 +428,7 @@ public void runtime_info_created_from_observations_uses_the_configured_pointer_s RuntimeInfo info = new(host, narrowed, RuntimeCapabilities.Empty); RuntimeInfo widenedInfo = new(host, widened, RuntimeCapabilities.Empty); - RuntimeInfo withoutTarget = new(host with - { - FileVersion = null - }, null, RuntimeCapabilities.Empty); + RuntimeInfo withoutTarget = new(host with { FileVersion = null }, null, RuntimeCapabilities.Empty); RuntimeInfo unknown = new(host, unknownFamilies, RuntimeCapabilities.Empty); Assert.Equal(host, info.Host); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeObservationsTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeObservationsTests.cs index 18bbc5ab..7b75e2c3 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeObservationsTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeObservationsTests.cs @@ -77,7 +77,8 @@ public void try_observe_runtime_info_with_the_spike_x64_facts_produces_a_complet [Fact] [Trait("Qualification", "Q31.a")] - public void try_observe_runtime_info_with_a_configured_pointer_size_of_four_on_x64_reports_it_as_the_pointer_size_and_keeps_bitness() + public void + try_observe_runtime_info_with_a_configured_pointer_size_of_four_on_x64_reports_it_as_the_pointer_size_and_keeps_bitness() { EngineTest.RequireNativeLua(); using NativeLuaState state = new(); @@ -296,7 +297,8 @@ public void try_observe_runtime_info_on_a_detached_runtime_retains_the_lifecycle Assert.Throws(() => RuntimeObservations.TryObserveRuntimeInfo(out _)); Assert.Throws(() => RuntimeHostOperations.ObserveHost(out _)); Assert.Throws(() => RuntimeProcessOperations.ObserveTargetArchitecture(out _)); - Assert.Throws(() => RuntimeProcessOperations.TryGetConfiguredPointerSize(out _, out _)); + Assert.Throws(() => + RuntimeProcessOperations.TryGetConfiguredPointerSize(out _, out _)); } private static RuntimeCapabilityContract Contract(RuntimeInfo info, RuntimeCapabilityId capability) diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobBoundedScanTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobBoundedScanTests.cs index ee432f99..b94c2df0 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobBoundedScanTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobBoundedScanTests.cs @@ -75,7 +75,7 @@ public void TryScanWithinBounds_refuses_invalid_bounds_before_any_CE_call() LuaState L = scope.State; _ = MemScanTestHost.Install(L); MemScanTestHost.ClearTrace(L); - Address[] destination = [new Address(0xA11CE)]; + Address[] destination = [new(0xA11CE)]; AobBoundedScanResult result = Scan(default, destination); @@ -112,7 +112,8 @@ public void TryScanWithinBounds_rejects_a_null_pattern_and_an_empty_destination_ [Fact] [Trait("Qualification", "Q28")] - public void TryScanWithinBounds_passes_the_bounds_verbatim_as_integers_and_disables_only_one_result_before_the_first_scan() + public void + TryScanWithinBounds_passes_the_bounds_verbatim_as_integers_and_disables_only_one_result_before_the_first_scan() { EngineTest.RequireNativeLua(); using NativeLuaState state = new(); @@ -130,7 +131,8 @@ public void TryScanWithinBounds_passes_the_bounds_verbatim_as_integers_and_disab MemScanTestHost.AssertLua(L, "first_scan_args[4] == '55 48 89 E5' and first_scan_args[5] == ''"); MemScanTestHost.AssertLua(L, "first_scan_start_type == 'integer' and first_scan_args[6] == 0x100000000"); MemScanTestHost.AssertLua(L, "first_scan_stop_type == 'integer' and first_scan_args[7] == math.mininteger"); - MemScanTestHost.AssertLua(L, "first_scan_args[8] == '' and first_scan_args[9] == 0 and first_scan_args[10] == ''"); + MemScanTestHost.AssertLua(L, + "first_scan_args[8] == '' and first_scan_args[9] == 0 and first_scan_args[10] == ''"); MemScanTestHost.AssertLua(L, "first_scan_args[11] == true and first_scan_args[12] == false"); MemScanTestHost.AssertLua(L, "first_scan_args[13] == false and first_scan_args[14] == false"); Assert.Equal(0L, MemScanTestHost.ReadInteger(L, "create_mem_scan_argument_count")); @@ -147,7 +149,8 @@ public void TryScanWithinBounds_passes_explicit_protection_and_alignment_options LuaState L = scope.State; _ = MemScanTestHost.Install(L); - _ = AobScanner.TryScanWithinBounds(Pattern, ModuleBounds, new AobScanOptions("+X-C-W", FastScanMethod.Aligned, "4"), + _ = AobScanner.TryScanWithinBounds(Pattern, ModuleBounds, + new AobScanOptions("+X-C-W", FastScanMethod.Aligned, "4"), new Address[1], TestContext.Current.CancellationToken); MemScanTestHost.AssertLua(L, "first_scan_args[8] == '+X-C-W' and first_scan_args[9] == 1"); @@ -187,7 +190,7 @@ public void TryScanWithinBounds_zero_found_rows_with_an_empty_error_string_is_no using HostScope scope = new(state); LuaState L = scope.State; _ = MemScanTestHost.Install(L); - Address[] destination = [new Address(0xA11CE)]; + Address[] destination = [new(0xA11CE)]; AobBoundedScanResult result = Scan(ModuleBounds, destination); @@ -212,7 +215,7 @@ public void TryScanWithinBounds_zero_found_rows_with_a_host_error_string_is_host LuaState L = scope.State; _ = MemScanTestHost.Install(L); MemScanTestHost.Run(L, "scan_error_string = 'No readable memory found'"); - Address[] destination = [new Address(0xA11CE)]; + Address[] destination = [new(0xA11CE)]; AobBoundedScanResult result = Scan(ModuleBounds, destination); @@ -353,7 +356,7 @@ public void TryScanWithinBounds_publishes_nothing_when_cancelled_during_the_copy using CancellationTokenSource cancellation = new(); using FakeHost.PCallProbe probe = FakeHost.ReplaceFoundListGetAddressWithPCallProbe(L, objects.FoundList, cancellation.Cancel); - Address[] destination = [new Address(0xA11CE), new Address(0xA11CE), new Address(0xA11CE)]; + Address[] destination = [new(0xA11CE), new(0xA11CE), new(0xA11CE)]; AobBoundedScanResult result = ScanWithToken(Bounds(0, 0x10000), destination, cancellation.Token); @@ -490,7 +493,7 @@ public void TryScanWithinBounds_staging_allocation_failure_releases_the_created_ SetAddresses(L, "100000000"); InsufficientMemoryException injected = new("injected staging allocation failure"); StagingPool pool = new(injected); - Address[] destination = [new Address(0xA11CE)]; + Address[] destination = [new(0xA11CE)]; InsufficientMemoryException thrown = Assert.Throws(() => AobBoundedScan.Run(Pattern, ModuleBounds, AobScanOptions.Default, null, destination, pool, @@ -546,7 +549,7 @@ public void TryScanWithinBounds_malformed_count_or_address_is_invalid_result_and LuaState L = scope.State; _ = MemScanTestHost.Install(L); MemScanTestHost.Run(L, mode); - Address[] destination = [new Address(0xA11CE), new Address(0xA11CE)]; + Address[] destination = [new(0xA11CE), new(0xA11CE)]; AobBoundedScanResult result = Scan(ModuleBounds, destination); @@ -570,9 +573,9 @@ public void TryScanWithinBounds_target_change_during_the_scan_is_target_changed_ MemScanTestHost.HostObjects objects = MemScanTestHost.Install(L); SetAddresses(L, "100000000"); MemScanTestHost.Run(L, "scan_first_hook = function() opened_process_id = " + - MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture) + - " end"); - Address[] destination = [new Address(0xA11CE)]; + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture) + + " end"); + Address[] destination = [new(0xA11CE)]; AobBoundedScanResult result = Scan(ModuleBounds, destination); @@ -707,7 +710,7 @@ public void TryScanWithinBounds_with_an_expired_deadline_terminates_cooperativel _ = MemScanTestHost.Install(L); SetAddresses(L, "100000000"); MemScanTestHost.Run(L, "scan_wait_modes = { 'false', 'true' }"); - Address[] destination = [new Address(0xA11CE)]; + Address[] destination = [new(0xA11CE)]; AobBoundedScanResult result = AobScanner.TryScanWithinBounds(Pattern, ModuleBounds, AobScanOptions.Default, TimeSpan.FromMilliseconds(100), destination, TestContext.Current.CancellationToken); @@ -847,8 +850,8 @@ private static int Occurrences(string text, string value) { int count = 0; for (int index = text.IndexOf(value, StringComparison.Ordinal); - index >= 0; - index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) + index >= 0; + index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) { count++; } @@ -869,22 +872,26 @@ public StagingPool(Exception? rentFailure) public int RentCount { - get; private set; + get; + private set; } public int ReturnCount { - get; private set; + get; + private set; } public Address[]? LastRented { - get; private set; + get; + private set; } public Address[]? LastReturned { - get; private set; + get; + private set; } public override Address[] Rent(int minimumLength) diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobFirstFoundScanTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobFirstFoundScanTests.cs index b6558f0b..51dd2478 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobFirstFoundScanTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobFirstFoundScanTests.cs @@ -106,7 +106,8 @@ public void TryFindFirstFoundWithinBounds_address_below_start_is_indeterminate_f using HostScope scope = new(state); LuaState L = scope.State; _ = MemScanTestHost.Install(L); - MemScanTestHost.Run(L, "only_result_mode = 'value'; only_result_value = " + reported.ToString(CultureInfo.InvariantCulture)); + MemScanTestHost.Run(L, + "only_result_mode = 'value'; only_result_value = " + reported.ToString(CultureInfo.InvariantCulture)); AobFirstFoundResult result = Find(Bounds(0x1_0000_1000, 0x1_0036_7000)); @@ -163,7 +164,8 @@ public void TryFindFirstFoundWithinBounds_keeps_the_64_bit_pattern_of_high_addre [InlineData("not-found", AobFirstFoundOutcomeKind.NotFound, "scan.getOnlyResult,list.destroy,scan.destroy")] [InlineData("invalid", AobFirstFoundOutcomeKind.InvalidResult, "scan.getOnlyResult,list.destroy,scan.destroy")] [InlineData("get-raises", AobFirstFoundOutcomeKind.ScanFailed, "scan.getOnlyResult,list.destroy,scan.destroy")] - [InlineData("set-raises", AobFirstFoundOutcomeKind.ScanFailed, "scan.setOnlyOneResult:true,list.destroy,scan.destroy")] + [InlineData("set-raises", AobFirstFoundOutcomeKind.ScanFailed, + "scan.setOnlyOneResult:true,list.destroy,scan.destroy")] [InlineData("first-raises", AobFirstFoundOutcomeKind.ScanFailed, "scan.first:14,scan.terminate:false,scan.wait:5000,list.destroy,scan.destroy")] [InlineData("wait-raises", AobFirstFoundOutcomeKind.ScanFailed, @@ -261,8 +263,9 @@ public void TryFindFirstFoundWithinBounds_target_change_during_the_scan_reports_ LuaState L = scope.State; _ = MemScanTestHost.Install(L); MemScanTestHost.Run(L, "only_result_mode = 'value'; only_result_value = 0x100000000; " + - "scan_first_hook = function() opened_process_id = " + - MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture) + " end"); + "scan_first_hook = function() opened_process_id = " + + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture) + + " end"); AobFirstFoundResult result = Find(ModuleBounds); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobScannerPublicationTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobScannerPublicationTests.cs index 485d3127..8bb73cdb 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobScannerPublicationTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobScannerPublicationTests.cs @@ -23,7 +23,7 @@ public void TryScanOutcome_publication_failure_destroys_the_raw_list_once_and_re using NativeLuaState state = new(); using HostScope scope = new(state); LuaState L = scope.State; - CEObject handle = CreateTracedList(L, "Probe", destroyRaises: false); + CEObject handle = CreateTracedList(L, "Probe", false); AobStringListTestHost.InstallAobScan(L, handle); InvalidOperationException injected = new("injected publication failure"); Owned? results = null; @@ -46,7 +46,7 @@ public void TryScanDetailed_publication_failure_destroys_the_raw_list_once_and_r using NativeLuaState state = new(); using HostScope scope = new(state); LuaState L = scope.State; - CEObject handle = CreateTracedList(L, "Probe", destroyRaises: false); + CEObject handle = CreateTracedList(L, "Probe", false); AobStringListTestHost.InstallAobScan(L, handle); InvalidOperationException injected = new("injected owner allocation failure"); Owned? results = null; @@ -63,13 +63,14 @@ public void TryScanDetailed_publication_failure_destroys_the_raw_list_once_and_r [Fact] [Trait("Qualification", "Q27")] - public void TryScanOutcome_publication_failure_with_a_refusing_destroy_rethrows_the_original_failure_without_retrying() + public void + TryScanOutcome_publication_failure_with_a_refusing_destroy_rethrows_the_original_failure_without_retrying() { EngineTest.RequireNativeLua(); using NativeLuaState state = new(); using HostScope scope = new(state); LuaState L = scope.State; - CEObject handle = CreateTracedList(L, "Stubborn", destroyRaises: true); + CEObject handle = CreateTracedList(L, "Stubborn", true); AobStringListTestHost.InstallAobScan(L, handle); InvalidOperationException injected = new("injected publication failure"); Owned? results = null; @@ -91,7 +92,7 @@ public void TryScanOutcome_publication_failure_with_a_lua_exception_is_rethrown_ using NativeLuaState state = new(); using HostScope scope = new(state); LuaState L = scope.State; - CEObject handle = CreateTracedList(L, "Probe", destroyRaises: false); + CEObject handle = CreateTracedList(L, "Probe", false); AobStringListTestHost.InstallAobScan(L, handle); LuaException injected = new("injected publication failure"); Owned? results = null; diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemScanTestHost.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemScanTestHost.cs index 8243d81c..3b0d23a7 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemScanTestHost.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemScanTestHost.cs @@ -24,7 +24,8 @@ namespace CheatEngine.SDK.Engine.Tests.Scanning; /// factory.scan, factory.list: the two CE factories. /// /// scan.setOnlyOneResult:<v>, scan.first:<argument count>, -/// scan.next:<argument count>, scan.wait (no argument) or scan.wait:<timeout>, +/// scan.next:<argument count>, scan.wait (no argument) or scan.wait:<timeout> +/// , /// scan.terminate:<force>, scan.new, scan.getOnlyResult, scan.ErrorString (a /// property read), scan.set.<property>:<v> (a write to OnlyOneResult, /// IsUnique, OnGuiUpdate, OnScanDone or OnScanStart), scan.destroy. @@ -297,14 +298,15 @@ public static int FindOtherQualifiedProcessId() } } catch (Exception exception) when (exception is InvalidOperationException or Win32Exception - or NotSupportedException) + or NotSupportedException) { // Not readable by this user (protected or already exited): not a qualifiable target. } } } - Assert.True(selected != 0, "No other process with a readable start time exists; a target change cannot be modelled."); + Assert.True(selected != 0, + "No other process with a readable start time exists; a target change cannot be modelled."); return selected; } @@ -316,8 +318,8 @@ public static int FindOtherQualifiedProcessId() public static void ReplaceCapturedTarget(MemoryScanSession session, TargetProcessIncarnation incarnation) { FieldInfo field = typeof(MemoryScanSession).GetField("_targetObservation", - BindingFlags.Instance | BindingFlags.NonPublic) - ?? throw new InvalidOperationException("The session's captured target field was not found."); + BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException("The session's captured target field was not found."); field.SetValue(session, TargetSelectionObservation.Qualified(incarnation)); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionFactoryTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionFactoryTests.cs index 1135b1ba..23e8185c 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionFactoryTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionFactoryTests.cs @@ -330,7 +330,8 @@ public void TryCreateWithOutcome_refuses_an_unqualified_target_before_either_fac [Fact] [Trait("Qualification", "Q25")] - public void TryCreate_when_adoption_fails_and_the_child_rollback_raises_still_destroys_the_parent_once_and_rethrows_the_adoption_failure() + public void + TryCreate_when_adoption_fails_and_the_child_rollback_raises_still_destroys_the_parent_once_and_rethrows_the_adoption_failure() { EngineTest.RequireNativeLua(); using NativeLuaState state = new(); @@ -359,7 +360,8 @@ public void TryCreate_when_adoption_fails_and_the_child_rollback_raises_still_de [Fact] [Trait("Qualification", "Q25")] - public void TryCreate_when_the_parent_rollback_raises_after_a_child_failure_reports_rollback_unconfirmed_without_retrying() + public void + TryCreate_when_the_parent_rollback_raises_after_a_child_failure_reports_rollback_unconfirmed_without_retrying() { EngineTest.RequireNativeLua(); using NativeLuaState state = new(); @@ -446,8 +448,8 @@ function getOpenedProcessID() private static void InstallCurrentTarget(LuaState state) { EngineTest.Run(state, Encoding.UTF8.GetBytes("function getOpenedProcessID() return " + - Environment.ProcessId.ToString(CultureInfo.InvariantCulture) + - " end")); + Environment.ProcessId.ToString(CultureInfo.InvariantCulture) + + " end")); EngineTest.Run(state, FakeHost.LocalTargetBackendChunk); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionTests.cs index 650aebed..c2f1ec25 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionTests.cs @@ -871,8 +871,8 @@ private static MemoryScanSession CreateSession(LuaState state, bool firstScanRai private static void InstallCurrentTarget(LuaState state) { EngineTest.Run(state, Encoding.UTF8.GetBytes("opened_process_id = " + - Environment.ProcessId.ToString(CultureInfo.InvariantCulture) + - "; function getOpenedProcessID() return opened_process_id end")); + Environment.ProcessId.ToString(CultureInfo.InvariantCulture) + + "; function getOpenedProcessID() return opened_process_id end")); EngineTest.Run(state, FakeHost.LocalTargetBackendChunk); } @@ -895,14 +895,14 @@ private static string FoundListInitializer(bool invalidAddress = false, string r string firstAddress = invalidAddress ? "'not-an-address'" : "'00001234'"; string destroyFailure = destroyRaises ? "; error('found-list destroy rejected')" : string.Empty; return "o.props.initialize = function() table.insert(trace, 'list.initialize') end\n" + - "o.props.deinitialize = function() table.insert(trace, 'list.deinitialize') end\n" + - "o.props.Count = " + resultCountLiteral + "\n" + - "o.props.getCount = function() table.insert(trace, 'results.getCount'); return o.props.Count end\n" + - "o.props.getAddress = function(index) table.insert(trace, 'results.getAddress:' .. index); if index == 0 then return " + - firstAddress + " end; return 'FFFFFFFFFFFFFFFF' end\n" + - "o.props.getValue = function(index) table.insert(trace, 'results.getValue:' .. index); return '100' end\n" + - "o.getters.destroy = function(o) return function() o.destroyed = true; table.insert(trace, 'list.destroy')" + - destroyFailure + " end end"; + "o.props.deinitialize = function() table.insert(trace, 'list.deinitialize') end\n" + + "o.props.Count = " + resultCountLiteral + "\n" + + "o.props.getCount = function() table.insert(trace, 'results.getCount'); return o.props.Count end\n" + + "o.props.getAddress = function(index) table.insert(trace, 'results.getAddress:' .. index); if index == 0 then return " + + firstAddress + " end; return 'FFFFFFFFFFFFFFFF' end\n" + + "o.props.getValue = function(index) table.insert(trace, 'results.getValue:' .. index); return '100' end\n" + + "o.getters.destroy = function(o) return function() o.destroyed = true; table.insert(trace, 'list.destroy')" + + destroyFailure + " end end"; } private static string ReadTrace(LuaState state) diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/ScanExperimentalApiTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/ScanExperimentalApiTests.cs index a4e8bb45..be857a39 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/ScanExperimentalApiTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/ScanExperimentalApiTests.cs @@ -14,7 +14,8 @@ namespace CheatEngine.SDK.Engine.Tests.Scanning; /// public sealed class ScanExperimentalApiTests { - private const string UrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md"; + private const string UrlFormat = + "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md"; [Fact] public void Scanning_experimental_members_are_exactly_the_documented_gates() @@ -42,7 +43,7 @@ public void Scanning_experimental_members_are_exactly_the_documented_gates() foreach (Type type in typeof(AobScanner).Assembly.GetExportedTypes()) { if (type.Namespace is null || - !type.Namespace.StartsWith("CheatEngine.SDK.Engine.Scanning", StringComparison.Ordinal)) + !type.Namespace.StartsWith("CheatEngine.SDK.Engine.Scanning", StringComparison.Ordinal)) { continue; } @@ -53,7 +54,7 @@ public void Scanning_experimental_members_are_exactly_the_documented_gates() } foreach (MemberInfo member in type.GetMembers(BindingFlags.Public | BindingFlags.Instance | - BindingFlags.Static | BindingFlags.DeclaredOnly)) + BindingFlags.Static | BindingFlags.DeclaredOnly)) { if (member.GetCustomAttribute() is { } attribute) { diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionBatteryTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionBatteryTests.cs index 2a45b2a7..bbcec89b 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionBatteryTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionBatteryTests.cs @@ -32,7 +32,9 @@ public void Wait_after_the_target_was_replaced_invalidates_as_target_changed_wit using HostScope scope = new(state); LuaState L = scope.State; MemoryScanSession session = StartScanning(L); - MemScanTestHost.Run(L, "opened_process_id = " + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); + MemScanTestHost.Run(L, + "opened_process_id = " + + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); MemoryScanException failure = Assert.Throws(session.WaitForCompletion); @@ -188,7 +190,8 @@ public void Scan_sessions_never_install_progress_or_completion_callbacks() Assert.DoesNotContain("setOnlyOneResult", trace, StringComparison.Ordinal); Assert.Equal(0L, MemScanTestHost.ReadInteger(L, "create_mem_scan_argument_count")); Assert.Equal(1L, MemScanTestHost.ReadInteger(L, "create_found_list_argument_count")); - Assert.EndsWith("scan.terminate:false,scan.wait:5000,list.destroy,scan.destroy", trace, StringComparison.Ordinal); + Assert.EndsWith("scan.terminate:false,scan.wait:5000,list.destroy,scan.destroy", trace, + StringComparison.Ordinal); Assert.Equal(0, L.Top); } @@ -214,7 +217,8 @@ public void First_scan_failure_category_does_not_depend_on_the_lua_error_text(st Assert.Equal(MemoryScanFailureKind.LuaError, failure.FailureKind); Assert.Equal("MemoryScan.FirstScan", failure.Operation); - Assert.Equal("The protected Lua call for memory scan operation 'MemoryScan.FirstScan' failed.", failure.Message); + Assert.Equal("The protected Lua call for memory scan operation 'MemoryScan.FirstScan' failed.", + failure.Message); Assert.Equal(MemoryScanState.Invalidated, session.State); Assert.Equal(MemoryScanInvalidationReason.ProtectedLuaFailure, session.InvalidationReason); Assert.Equal(0, L.Top); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionDeadlineTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionDeadlineTests.cs index d34add8b..5bed132a 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionDeadlineTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionDeadlineTests.cs @@ -187,7 +187,8 @@ public void TryWaitForCompletion_lua_error_is_lua_failure_and_invalidates() [Fact] [Trait("Qualification", "Q26")] - public void TryWaitForCompletion_initialize_failure_after_completion_is_initialization_failed_and_never_exposes_results() + public void + TryWaitForCompletion_initialize_failure_after_completion_is_initialization_failed_and_never_exposes_results() { EngineTest.RequireNativeLua(); using NativeLuaState state = new(); @@ -215,7 +216,9 @@ public void TryWaitForCompletion_after_a_target_replacement_reports_the_mismatch using HostScope scope = new(state); LuaState L = scope.State; MemoryScanSession session = StartScanning(L); - MemScanTestHost.Run(L, "opened_process_id = " + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); + MemScanTestHost.Run(L, + "opened_process_id = " + + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); MemoryScanWaitStatus status = session.TryWaitForCompletion(Deadline); @@ -341,7 +344,7 @@ public void TryTerminateScan_unconfirmed_stop_is_kept_by_a_refused_release_witho MemScanTestHost.Run(L, "scan_wait_mode = 'false'"); Assert.Equal(MemoryScanTerminationStatus.WaitTimedOut, session.TryTerminateScan(Deadline)); MemScanTestHost.Run(L, "opened_process_id = " + - MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); MemScanTestHost.ClearTrace(L); MemoryScanReleaseOutcome outcome = session.ReleaseWithOutcome(); @@ -388,7 +391,9 @@ public void TryTerminateScan_with_a_replaced_target_is_not_invoked_and_makes_no_ using HostScope scope = new(state); LuaState L = scope.State; MemoryScanSession session = StartScanning(L); - MemScanTestHost.Run(L, "opened_process_id = " + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); + MemScanTestHost.Run(L, + "opened_process_id = " + + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); MemoryScanTerminationStatus status = session.TryTerminateScan(Deadline); @@ -499,7 +504,7 @@ public void TryGetHostErrorText_with_a_replaced_target_returns_false_without_a_s LuaState L = scope.State; MemoryScanSession session = StartScanning(L); MemScanTestHost.Run(L, "scan_error_string = 'unread'; opened_process_id = " + - MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); bool read = session.TryGetHostErrorText(out string? text, out bool truncated); @@ -545,7 +550,8 @@ public void TryWaitForCompletion_disposed_from_inside_the_wait_releases_once_aft LuaState L = scope.State; MemoryScanSession session = StartScanning(L); MemoryScanReleaseOutcome? inner = null; - using FakeHost.ManagedHookScope hook = FakeHost.InstallManagedHook(L, () => inner = session.ReleaseWithOutcome()); + using FakeHost.ManagedHookScope hook = + FakeHost.InstallManagedHook(L, () => inner = session.ReleaseWithOutcome()); InstallWaitHook(L); Assert.Throws(() => session.TryWaitForCompletion(Deadline)); @@ -571,7 +577,8 @@ public void TryWaitForCompletion_disposed_from_inside_a_timed_out_wait_stops_the LuaState L = scope.State; MemoryScanSession session = StartScanning(L); List inner = []; - using FakeHost.ManagedHookScope hook = FakeHost.InstallManagedHook(L, () => inner.Add(session.ReleaseWithOutcome())); + using FakeHost.ManagedHookScope hook = + FakeHost.InstallManagedHook(L, () => inner.Add(session.ReleaseWithOutcome())); InstallWaitHook(L); MemScanTestHost.Run(L, "scan_wait_modes = { 'false', 'true' }"); @@ -626,7 +633,8 @@ public void TryTerminateScan_disposed_from_inside_the_settle_wait_releases_once_ // Every wait runs the managed hook (CE pumping queued main-thread work), then records that the hook returned. private static void InstallWaitHook(LuaState state) { - MemScanTestHost.Run(state, "scan_wait_hook = function() managed_hook(); table.insert(trace, 'hook.returned') end"); + MemScanTestHost.Run(state, + "scan_wait_hook = function() managed_hook(); table.insert(trace, 'hook.returned') end"); } private static MemoryScanSession StartScanning(LuaState state) diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionReleaseTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionReleaseTests.cs index d474aafb..3df906a2 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionReleaseTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionReleaseTests.cs @@ -264,7 +264,9 @@ public void Release_on_a_replaced_target_while_scanning_refuses_every_CE_call_an using HostScope scope = new(state); LuaState L = scope.State; MemoryScanSession session = StartScanning(L); - MemScanTestHost.Run(L, "opened_process_id = " + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); + MemScanTestHost.Run(L, + "opened_process_id = " + + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); MemoryScanReleaseOutcome outcome = session.ReleaseWithOutcome(); @@ -312,7 +314,8 @@ public void Dispose_from_inside_the_release_settle_wait_makes_no_CE_call_and_the [Fact] [Trait("Qualification", "Q26")] - public void Dispose_from_inside_WaitForCompletion_releases_once_after_the_wait_returned_without_initializing_results() + public void + Dispose_from_inside_WaitForCompletion_releases_once_after_the_wait_returned_without_initializing_results() { EngineTest.RequireNativeLua(); using NativeLuaState state = new(); @@ -425,7 +428,8 @@ private static void AssertReentrantRefusal(Exception? refusal, string operation) // Every wait runs the managed hook (CE pumping queued main-thread work), then records that the hook returned. private static void InstallWaitHook(LuaState state) { - MemScanTestHost.Run(state, "scan_wait_hook = function() managed_hook(); table.insert(trace, 'hook.returned') end"); + MemScanTestHost.Run(state, + "scan_wait_hook = function() managed_hook(); table.insert(trace, 'hook.returned') end"); } private static MemoryScanSession StartScanning(LuaState state) diff --git a/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.Rt.cs b/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.Rt.cs index 709b6509..00b68f35 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.Rt.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.Rt.cs @@ -173,7 +173,7 @@ private static List ReadStringSequence(LuaState state, ReadOnlySpan) &RunManagedHook)); + L.PushUncheckedFunction( + new LuaNativeFunction((nint) (delegate* unmanaged[Cdecl]) &RunManagedHook)); Assert.True(L.TrySetGlobal("managed_hook"u8).IsOk); ManagedHookScope scope = new(hook); s_activeManagedHook = scope; diff --git a/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.cs b/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.cs index 94e8ad65..0a7d7fcb 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.cs @@ -327,15 +327,15 @@ internal PCallProbe(Action? afterWaitTillDone, Action? afterGetAddress = null) } FieldInfo tableField = typeof(LuaApi).GetField("s_table", BindingFlags.Static | BindingFlags.NonPublic) - ?? throw new InvalidOperationException( - "The Lua API table was not available for probing."); + ?? throw new InvalidOperationException( + "The Lua API table was not available for probing."); _table = tableField.GetValue(null) - ?? throw new InvalidOperationException("The Lua API table was not initialized for probing."); + ?? throw new InvalidOperationException("The Lua API table was not initialized for probing."); _pcallField = _table.GetType().GetField("lua_pcallk", BindingFlags.Instance | BindingFlags.NonPublic) - ?? throw new InvalidOperationException( - "The Lua protected-call slot was not available for probing."); + ?? throw new InvalidOperationException( + "The Lua protected-call slot was not available for probing."); s_forwardedPCall = (nint) (_pcallField.GetValue(_table) - ?? throw new InvalidOperationException("The Lua protected-call slot was null.")); + ?? throw new InvalidOperationException("The Lua protected-call slot was null.")); _pcallField.SetValue(_table, (nint) (delegate* unmanaged[Cdecl]) &ObservePCall); tableField.SetValue(null, _table); @@ -411,8 +411,8 @@ private static int ObservePCall(lua_State* state, int argumentCount, int resultC { PCallProbe? probe = s_activePCallProbe; if (probe is not null && - (nint) lua_tocfunction(state, -argumentCount - 1) == - (nint) (delegate* unmanaged[Cdecl]) &WaitTillDone) + (nint) lua_tocfunction(state, -argumentCount - 1) == + (nint) (delegate* unmanaged[Cdecl]) &WaitTillDone) { probe.Observe(argumentCount, resultCount); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Tables/CheatTableFilesTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Tables/CheatTableFilesTests.cs index a8990cda..5ad10af1 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Tables/CheatTableFilesTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Tables/CheatTableFilesTests.cs @@ -101,10 +101,10 @@ public void TryLoad_marks_address_list_mutations_as_refused_while_it_runs() List observed = []; MemoryRecordMutationOutcome refused = default; using (FakeHost.InstallReentrantHook(L, "table_script", () => - { - observed.Add(CheatTableFiles.IsLoadInProgressOnCurrentThread); - refused = AddressListMutations.Delete(new MemoryRecordId(1)); - })) + { + observed.Add(CheatTableFiles.IsLoadInProgressOnCurrentThread); + refused = AddressListMutations.Delete(new MemoryRecordId(1)); + })) { EngineTest.Run(L, "loadTable = function(path, merge) table_script() end"u8); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Targets/TargetSelectionTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Targets/TargetSelectionTests.cs index 8deffef0..cbd23cb4 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Targets/TargetSelectionTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Targets/TargetSelectionTests.cs @@ -27,8 +27,9 @@ public void ObserveCurrent_with_the_current_process_id_returns_a_qualified_incar Assert.True(observation.IsQualified); Assert.True(observation.Incarnation.HasValue); Assert.Equal(Environment.ProcessId, observation.Incarnation.Value.ProcessId); - Assert.Equal(TargetIdentityEvidence.CheatEngineSelectedProcessId | TargetIdentityEvidence.LocalBackendConfirmed | - TargetIdentityEvidence.LocalProcessStartTime, observation.Evidence); + Assert.Equal(TargetIdentityEvidence.CheatEngineSelectedProcessId | + TargetIdentityEvidence.LocalBackendConfirmed | + TargetIdentityEvidence.LocalProcessStartTime, observation.Evidence); Assert.Equal(TargetBackend.LocalProcess, observation.Backend); Assert.True(TargetSelection.ValidateCurrent(observation.Incarnation.Value).IsCurrent); Assert.Equal(0, scope.State.Top); diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/CoexistencePluginLayout.cs b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/CoexistencePluginLayout.cs index d08813fe..a1f5554e 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/CoexistencePluginLayout.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/CoexistencePluginLayout.cs @@ -29,7 +29,8 @@ internal static class CoexistencePluginLayout private static string BinRoot => RequireMetadata("CoexistencePluginBinRoot"); - private static string LowercaseConfiguration => RequireMetadata("CoexistencePluginConfiguration").ToLowerInvariant(); + private static string LowercaseConfiguration => + RequireMetadata("CoexistencePluginConfiguration").ToLowerInvariant(); /// /// Builds the shared-layout scenario: copies both plugin output directories into one folder. Fails loudly, per @@ -41,8 +42,8 @@ internal static class CoexistencePluginLayout internal static string CreateSharedLayout(string destinationDirectory) { Directory.CreateDirectory(destinationDirectory); - CopyDirectoryInto(PluginADirectory, destinationDirectory, compareExisting: false); - CopyDirectoryInto(PluginBDirectory, destinationDirectory, compareExisting: true); + CopyDirectoryInto(PluginADirectory, destinationDirectory, false); + CopyDirectoryInto(PluginBDirectory, destinationDirectory, true); return destinationDirectory; } @@ -74,7 +75,8 @@ private static void CopyDirectoryInto(string sourceDirectory, string destination private static string RequireMetadata(string key) { - foreach (AssemblyMetadataAttribute attribute in typeof(CoexistencePluginLayout).Assembly.GetCustomAttributes()) + foreach (AssemblyMetadataAttribute attribute in typeof(CoexistencePluginLayout).Assembly + .GetCustomAttributes()) { if (string.Equals(attribute.Key, key, StringComparison.Ordinal) && !string.IsNullOrEmpty(attribute.Value)) { diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorAlcRoute.cs b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorAlcRoute.cs index 2647c895..779f48f4 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorAlcRoute.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorAlcRoute.cs @@ -7,5 +7,5 @@ internal enum NativeHostEmulatorAlcRoute Component, /// The undocumented hdt_load_assembly + hdt_get_function_pointer route into the default ALC. - Default, + Default } diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorRunner.cs b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorRunner.cs index d875062d..556cfdcf 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorRunner.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorRunner.cs @@ -23,7 +23,8 @@ internal static NativeHostEmulatorResult Run( string exePath = Path.Combine(emulatorDirectory, "ce-host-emulator.exe"); if (!File.Exists(exePath)) { - throw new FileNotFoundException($"'{exePath}' does not exist: run tests/native-host-emulator/build.ps1 first.", exePath); + throw new FileNotFoundException( + $"'{exePath}' does not exist: run tests/native-host-emulator/build.ps1 first.", exePath); } string runtimeConfigPath = Path.Combine(emulatorDirectory, "ce-like.runtimeconfig.json"); @@ -34,7 +35,7 @@ internal static NativeHostEmulatorResult Run( UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, - CreateNoWindow = true, + CreateNoWindow = true }; AddArgument(startInfo, "--lua", luaPath); @@ -47,17 +48,14 @@ internal static NativeHostEmulatorResult Run( AddArgument(startInfo, "--alc", route == NativeHostEmulatorAlcRoute.Default ? "default" : "component"); AddArgument(startInfo, "--facts", factsPath); - using Process process = new() - { - StartInfo = startInfo, - }; + using Process process = new() { StartInfo = startInfo }; process.Start(); string standardOutput = process.StandardOutput.ReadToEnd(); string standardError = process.StandardError.ReadToEnd(); bool exited = process.WaitForExit((int) ProcessTimeout.TotalMilliseconds); if (!exited) { - process.Kill(entireProcessTree: true); + process.Kill(true); throw new TimeoutException($"'{exePath}' did not exit within {ProcessTimeout}."); } @@ -89,7 +87,8 @@ private static string ResolveDotNetRoot() DirectoryInfo? root = new DirectoryInfo(runtimeDirectory).Parent?.Parent?.Parent; if (root is null) { - throw new InvalidOperationException($"Could not derive a .NET root three levels above '{runtimeDirectory}'."); + throw new InvalidOperationException( + $"Could not derive a .NET root three levels above '{runtimeDirectory}'."); } return root.FullName; diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorTests.cs b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorTests.cs index 354ccd85..bcce66e7 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorTests.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorTests.cs @@ -19,8 +19,9 @@ public sealed unsafe partial class NativeHostEmulatorTests [Fact] public void Required_mode_rejects_an_absent_emulator_directory() { - InvalidOperationException exception = Assert.Throws( - () => NativeHostEmulatorEnvironment.ResolveDirectory(null, "true")); + InvalidOperationException exception = + Assert.Throws(() => + NativeHostEmulatorEnvironment.ResolveDirectory(null, "true")); Assert.Equal( $"'{NativeHostEmulatorEnvironment.RequiredEnvironmentVariable}=true' requires '{NativeHostEmulatorEnvironment.DirectoryEnvironmentVariable}' to name a built native host emulator directory.", @@ -36,13 +37,15 @@ public void Emulator_is_optional_when_required_mode_is_off() [Fact] public void Emulator_abi_header_declares_the_managed_record_sizes() { - string headerPath = Path.Combine(CoexistencePluginLayout.RepoRoot, "tests", "native-host-emulator", "ce_host_emulator_abi.h"); + string headerPath = Path.Combine(CoexistencePluginLayout.RepoRoot, "tests", "native-host-emulator", + "ce_host_emulator_abi.h"); string headerText = File.ReadAllText(headerPath); Dictionary declaredSizes = new(StringComparer.Ordinal); foreach (Match match in StaticAssertSizeOf().Matches(headerText)) { - declaredSizes[match.Groups["type"].Value] = int.Parse(match.Groups["size"].Value, CultureInfo.InvariantCulture); + declaredSizes[match.Groups["type"].Value] = + int.Parse(match.Groups["size"].Value, CultureInfo.InvariantCulture); } Assert.Equal(36, declaredSizes["CePluginInitRecord"]); @@ -79,7 +82,8 @@ public void Separate_folders_measure_distinct_hosting_instances_and_disabling_A_ Assert.Equal("nil", result.Facts["after_disable_a.a_identity_type"]); Assert.Equal("nil", result.Facts["after_disable_a.a_ping_type"]); Assert.Equal("ok", result.Facts["after_disable_a.b_identity_call"]); - Assert.True(TryParseInt(result.Facts["after_disable_a.b_ping"], out int pingAfterDisableA) && pingAfterDisableA > 0, + Assert.True( + TryParseInt(result.Facts["after_disable_a.b_ping"], out int pingAfterDisableA) && pingAfterDisableA > 0, DescribeFailure("Q09.b", result, factsPath)); } @@ -94,7 +98,8 @@ public void Shared_folder_under_the_component_route_is_measured_and_disabling_A_ return; } - string sharedDirectory = Path.Combine(Path.GetTempPath(), "cesdk-native-host-emulator-" + Guid.NewGuid().ToString("N")); + string sharedDirectory = + Path.Combine(Path.GetTempPath(), "cesdk-native-host-emulator-" + Guid.NewGuid().ToString("N")); try { CoexistencePluginLayout.CreateSharedLayout(sharedDirectory); @@ -134,7 +139,8 @@ public void Default_context_loading_rejects_the_second_plugin_deterministically( return; } - string sharedDirectory = Path.Combine(Path.GetTempPath(), "cesdk-native-host-emulator-" + Guid.NewGuid().ToString("N")); + string sharedDirectory = + Path.Combine(Path.GetTempPath(), "cesdk-native-host-emulator-" + Guid.NewGuid().ToString("N")); try { CoexistencePluginLayout.CreateSharedLayout(sharedDirectory); @@ -199,7 +205,8 @@ public void Reenabling_A_answers_with_a_new_epoch() Assert.True(0 == result.ExitCode, DescribeFailure("Q05", result, factsPath)); Assert.Equal("ok", result.Facts["a.enable.2"]); - Assert.True(TryParseInt(result.Facts["a.identity.epoch"], out int firstEpoch), DescribeFailure("Q05", result, factsPath)); + Assert.True(TryParseInt(result.Facts["a.identity.epoch"], out int firstEpoch), + DescribeFailure("Q05", result, factsPath)); Assert.True(TryParseInt(result.Facts["a.identity.epoch_after_reenable"], out int reenabledEpoch), DescribeFailure("Q05", result, factsPath)); Assert.True(reenabledEpoch > firstEpoch, DescribeFailure("Q05", result, factsPath)); @@ -235,12 +242,17 @@ private static NativeHostEmulatorResult RunSeparateComponentScenario(string emul factsPath); } - private static void AssertBootstrapAndEnableSucceeded(NativeHostEmulatorResult result, string label, string factsPath) + private static void AssertBootstrapAndEnableSucceeded(NativeHostEmulatorResult result, string label, + string factsPath) { - Assert.True(string.Equals("ok", result.Facts[$"{label}.bootstrap.first"], StringComparison.Ordinal), DescribeFailure(label, result, factsPath)); - Assert.True(string.Equals("ok", result.Facts[$"{label}.bootstrap.second"], StringComparison.Ordinal), DescribeFailure(label, result, factsPath)); - Assert.True(string.Equals("ok", result.Facts[$"{label}.getversion"], StringComparison.Ordinal), DescribeFailure(label, result, factsPath)); - Assert.True(string.Equals("ok", result.Facts[$"{label}.enable.1"], StringComparison.Ordinal), DescribeFailure(label, result, factsPath)); + Assert.True(string.Equals("ok", result.Facts[$"{label}.bootstrap.first"], StringComparison.Ordinal), + DescribeFailure(label, result, factsPath)); + Assert.True(string.Equals("ok", result.Facts[$"{label}.bootstrap.second"], StringComparison.Ordinal), + DescribeFailure(label, result, factsPath)); + Assert.True(string.Equals("ok", result.Facts[$"{label}.getversion"], StringComparison.Ordinal), + DescribeFailure(label, result, factsPath)); + Assert.True(string.Equals("ok", result.Facts[$"{label}.enable.1"], StringComparison.Ordinal), + DescribeFailure(label, result, factsPath)); } private static bool TryParseInt(string text, out int value) @@ -266,7 +278,7 @@ private static void TryDeleteDirectory(string path) { if (Directory.Exists(path)) { - Directory.Delete(path, recursive: true); + Directory.Delete(path, true); } } catch (IOException) @@ -279,9 +291,10 @@ private static void TryDeleteDirectory(string path) } } - [GeneratedRegex(@"static_assert\(sizeof\((?\w+)\)\s*==\s*(?\d+)", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"static_assert\(sizeof\((?\w+)\)\s*==\s*(?\d+)", RegexOptions.CultureInvariant, 1000)] private static partial Regex StaticAssertSizeOf(); - [GeneratedRegex(@"[A-Za-z]:[\\/]|\\\\[A-Za-z0-9._-]+\\", RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"[A-Za-z]:[\\/]|\\\\[A-Za-z0-9._-]+\\", + RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture, 1000)] private static partial Regex AbsolutePathPattern(); } diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/HostLogContainmentTests.cs b/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/HostLogContainmentTests.cs index 8405ae9a..b122b048 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/HostLogContainmentTests.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/HostLogContainmentTests.cs @@ -11,7 +11,7 @@ namespace CheatEngine.SDK.Hosting.Tests.Diagnostics; /// ABI callback. It cannot recurse into , cannot re-enter a lifecycle transition, and /// cannot acquire Lua while a transition owns admission; none of that waits for the sink. /// -public sealed unsafe class HostLogContainmentTests : IDisposable +public sealed class HostLogContainmentTests : IDisposable { public HostLogContainmentTests() { @@ -120,7 +120,7 @@ public void A_sink_that_acquires_a_Lua_operation_during_a_lifecycle_transition_i HostLog.Sink = new CallbackLogSink(message => { if (string.Equals(message, "RecordingPlugin.OnDisable observed", StringComparison.Ordinal) - && acquiredDuringOnDisable is null) + && acquiredDuringOnDisable is null) { // OnDisable still runs on the captured main thread while the runtime is attached (operation // admission itself does not close until after OnDisable returns): the acquisition succeeds and diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/LoadIdentificationTests.cs b/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/LoadIdentificationTests.cs index 71e50026..0d8d9b53 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/LoadIdentificationTests.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/LoadIdentificationTests.cs @@ -19,13 +19,6 @@ public sealed unsafe partial class LoadIdentificationTests { private const string Prefix = "CheatEngineSdkIdentification: "; - [GeneratedRegex(@"lua\.module=(?[^;]*); lua\.sha256=(?[0-9a-f]{64}|unavailable)", - RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture, matchTimeoutMilliseconds: 1000)] - private static partial Regex LuaModuleFieldsPattern(); - - [GeneratedRegex("^[A-Za-z]:", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] - private static partial Regex DriveRootPattern(); - private static readonly string[] SExpectedKeys = [ "sdk.version", "sdk.commit", "sdk.consistent", "hosting.mvid", "hosting.alc", "plugin.id", "plugin.assembly", @@ -33,6 +26,13 @@ public sealed unsafe partial class LoadIdentificationTests "ce.fileVersion", "runtime", "arch" ]; + [GeneratedRegex(@"lua\.module=(?[^;]*); lua\.sha256=(?[0-9a-f]{64}|unavailable)", + RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture, 1000)] + private static partial Regex LuaModuleFieldsPattern(); + + [GeneratedRegex("^[A-Za-z]:", RegexOptions.CultureInvariant, 1000)] + private static partial Regex DriveRootPattern(); + [Fact] public void Identification_is_not_emitted_unless_opted_in() { @@ -83,7 +83,8 @@ public void Identification_contains_the_sdk_version_and_a_40_hex_commit_or_unkno { string line = EnableWithIdentification(); - Assert.Matches(@"sdk\.version=[^;]*; sdk\.commit=(?:[0-9a-f]{40}|unknown); sdk\.consistent=(?:true|false)(?:; |$)", + Assert.Matches( + @"sdk\.version=[^;]*; sdk\.commit=(?:[0-9a-f]{40}|unknown); sdk\.consistent=(?:true|false)(?:; |$)", line); } @@ -102,7 +103,7 @@ public void Identification_contains_the_bridge_fingerprint_or_unavailable() public void Identification_contains_the_lua_module_file_name_and_sha256_without_a_directory() { HostingTest.RequireNativeLua(); - string line = EnableWithIdentification(useNativeLuaModule: true); + string line = EnableWithIdentification(true); Match match = LuaModuleFieldsPattern().Match(line); Assert.True(match.Success, "lua.module/lua.sha256 not found in: " + line); @@ -119,7 +120,7 @@ public void Identification_contains_the_lua_module_file_name_and_sha256_without_ public void Identification_never_contains_a_directory_separator_drive_root_or_user_name() { HostingTest.RequireNativeLua(); - string line = EnableWithIdentification(useNativeLuaModule: true); + string line = EnableWithIdentification(true); foreach ((string _, string value) in ParsePairs(line)) { diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Lifecycle/DisablePluginTests.cs b/tests/CheatEngine.SDK.Hosting.Tests/Lifecycle/DisablePluginTests.cs index 92b7bb2a..09303a73 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Lifecycle/DisablePluginTests.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Lifecycle/DisablePluginTests.cs @@ -261,106 +261,6 @@ public void Disable_while_a_worker_waits_in_a_Lua_synchronize_dispatch_pumps_it_ .GetResult(); } - // A native `synchronize` stand-in that genuinely hops to the real calling (main) thread, unlike - // MainThreadDispatcher.DispatchOverrideForTests: the worker blocks inside an actual Lua call while Disable's - // CheckSynchronize drain busy-polls TryPumpQueuedCall from the main thread until the queued call has been - // pushed, run exactly once, and released (A08-28). A call before anything is queued, or after the one queued - // call already ran, is a harmless no-op: the drain loop calls it repeatedly while it spins. - private sealed unsafe class RealSynchronizeStandIn : IDisposable - { - private static ManualResetEventSlim? s_queued; - private static ManualResetEventSlim? s_completed; - private static LuaRef? s_pendingRef; - private static LuaStatus s_pumpedCallStatus; - private static int s_pumped; - - private RealSynchronizeStandIn() - { - } - - public static bool Pumped => Volatile.Read(ref s_pumped) != 0; - - /// Waits until the worker's synchronize call has actually queued a pending call. - public static bool WaitUntilQueued(TimeSpan timeout) - { - return s_queued!.Wait(timeout); - } - - public static RealSynchronizeStandIn Install(LuaState main) - { - s_queued = new ManualResetEventSlim(false); - s_completed = new ManualResetEventSlim(false); - s_pendingRef = null; - s_pumped = 0; - Assert.True(main.TryPushFunction(new LuaNativeFunction(&SynchronizeThunk)).IsOk); - Assert.True(main.TrySetGlobal("synchronize"u8).IsOk); - return new RealSynchronizeStandIn(); - } - - public static void TryPumpQueuedCall() - { - if (!s_queued!.Wait(0)) - { - return; - } - - LuaRef? pendingRef = Interlocked.Exchange(ref s_pendingRef, null); - if (pendingRef is null) - { - return; - } - - using LuaRuntimeOperation operation = LuaRuntime.AcquireOperation(); - LuaState state = operation.State; - Assert.True(state.TryPushRef(pendingRef)); - s_pumpedCallStatus = state.TryCall(0, 0); - pendingRef.Release(state); - Interlocked.Exchange(ref s_pumped, 1); - s_completed!.Set(); - } - - public void Dispose() - { - if (Pumped) - { - Assert.True(s_pumpedCallStatus.IsOk, "The pumped call failed."); - } - - s_queued?.Dispose(); - s_completed?.Dispose(); - s_queued = null; - s_completed = null; - s_pendingRef = null; - } - - [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] - private static int SynchronizeThunk(nint pointer) - { - LuaState state = new(pointer); - try - { - if (!state.IsFunction(1)) - { - return LuaThunk.Fail(state, "the real stand-in expects a function argument"u8); - } - - state.PushValue(1); - s_pendingRef = state.CreateRef(); - s_queued!.Set(); - if (!s_completed!.Wait(TimeSpan.FromSeconds(5))) - { - return LuaThunk.Fail(state, "the main-thread drain never ran the queued call"u8); - } - - return 0; - } - catch (Exception exception) - { - return LuaThunk.Fail(state, exception); - } - } - } - [Fact] public void Disabling_while_disabled_is_a_no_op_reported_as_TRUE_with_a_warning() { @@ -575,4 +475,104 @@ private static int NoOpThunk(nint handle) { return 0; } + + // A native `synchronize` stand-in that genuinely hops to the real calling (main) thread, unlike + // MainThreadDispatcher.DispatchOverrideForTests: the worker blocks inside an actual Lua call while Disable's + // CheckSynchronize drain busy-polls TryPumpQueuedCall from the main thread until the queued call has been + // pushed, run exactly once, and released (A08-28). A call before anything is queued, or after the one queued + // call already ran, is a harmless no-op: the drain loop calls it repeatedly while it spins. + private sealed class RealSynchronizeStandIn : IDisposable + { + private static ManualResetEventSlim? s_queued; + private static ManualResetEventSlim? s_completed; + private static LuaRef? s_pendingRef; + private static LuaStatus s_pumpedCallStatus; + private static int s_pumped; + + private RealSynchronizeStandIn() + { + } + + public static bool Pumped => Volatile.Read(ref s_pumped) != 0; + + public void Dispose() + { + if (Pumped) + { + Assert.True(s_pumpedCallStatus.IsOk, "The pumped call failed."); + } + + s_queued?.Dispose(); + s_completed?.Dispose(); + s_queued = null; + s_completed = null; + s_pendingRef = null; + } + + /// Waits until the worker's synchronize call has actually queued a pending call. + public static bool WaitUntilQueued(TimeSpan timeout) + { + return s_queued!.Wait(timeout); + } + + public static RealSynchronizeStandIn Install(LuaState main) + { + s_queued = new ManualResetEventSlim(false); + s_completed = new ManualResetEventSlim(false); + s_pendingRef = null; + s_pumped = 0; + Assert.True(main.TryPushFunction(new LuaNativeFunction(&SynchronizeThunk)).IsOk); + Assert.True(main.TrySetGlobal("synchronize"u8).IsOk); + return new RealSynchronizeStandIn(); + } + + public static void TryPumpQueuedCall() + { + if (!s_queued!.Wait(0)) + { + return; + } + + LuaRef? pendingRef = Interlocked.Exchange(ref s_pendingRef, null); + if (pendingRef is null) + { + return; + } + + using LuaRuntimeOperation operation = LuaRuntime.AcquireOperation(); + LuaState state = operation.State; + Assert.True(state.TryPushRef(pendingRef)); + s_pumpedCallStatus = state.TryCall(0, 0); + pendingRef.Release(state); + Interlocked.Exchange(ref s_pumped, 1); + s_completed!.Set(); + } + + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] + private static int SynchronizeThunk(nint pointer) + { + LuaState state = new(pointer); + try + { + if (!state.IsFunction(1)) + { + return LuaThunk.Fail(state, "the real stand-in expects a function argument"u8); + } + + state.PushValue(1); + s_pendingRef = state.CreateRef(); + s_queued!.Set(); + if (!s_completed!.Wait(TimeSpan.FromSeconds(5))) + { + return LuaThunk.Fail(state, "the main-thread drain never ran the queued call"u8); + } + + return 0; + } + catch (Exception exception) + { + return LuaThunk.Fail(state, exception); + } + } + } } diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Support/RecordingPlugin.cs b/tests/CheatEngine.SDK.Hosting.Tests/Support/RecordingPlugin.cs index 8ae7aea4..05c7ba75 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Support/RecordingPlugin.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Support/RecordingPlugin.cs @@ -269,15 +269,15 @@ protected internal override void OnEnable() if (CreateCallbacksInOnEnable) { if (!LuaCallback.TryCreate(L, new LuaNativeFunction(&NoOpThunk), new object(), - out LuaCallback? first).IsOk - || first is null) + out LuaCallback? first).IsOk + || first is null) { throw new InvalidOperationException("first callback creation failed"); } if (!LuaCallback.TryCreate(L, new LuaNativeFunction(&NoOpThunk), new object(), - out LuaCallback? second).IsOk - || second is null) + out LuaCallback? second).IsOk + || second is null) { throw new InvalidOperationException("second callback creation failed"); } diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Threading/MainThreadTests.cs b/tests/CheatEngine.SDK.Hosting.Tests/Threading/MainThreadTests.cs index 3256d9c6..7027423e 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Threading/MainThreadTests.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Threading/MainThreadTests.cs @@ -278,11 +278,58 @@ public void Invoke_from_a_worker_works_under_the_default_admission_policy() .GetResult(); } + private static void InstallSynchronizeStandIn(NativeLuaState state) + { + LuaState L = LuaRuntime.AcquireState(); + using LuaFrame frame = new(L); + LuaStatus status = L.TryExecute( + "synchronize_calls = 0; function synchronize(f, ...) synchronize_calls = synchronize_calls + 1; return f(...) end"u8, + 0); + Assert.True(status.IsOk, "stand-in install failed: " + LuaError.FromStack(L, status).Message); + Assert.Equal(0, LuaApi.lua_gettop(state.L)); + } + + private static long ReadGlobalInteger(NativeLuaState state, ReadOnlySpan name) + { + LuaState L = new(state.Pointer); + using LuaFrame frame = new(L); + Assert.True(L.TryGetGlobal(name).IsOk); + Assert.True(L.TryReadInteger(-1, out long value)); + return value; + } + + private static T RunOnWorker(Func work) + { + // Boxes, not captured locals: static analysis (S2583) does not see a lambda's write to a captured local. + // Join publishes the worker's writes to this thread. + StrongBox result = new(); + StrongBox crash = new(); + Thread worker = new(() => + { + try + { + result.Value = work(); + } + catch (Exception exception) + { + crash.Value = exception; + } + }); + worker.Start(); + worker.Join(); + if (crash.Value is { } failure) + { + throw new InvalidOperationException("The worker crashed.", failure); + } + + return result.Value!; + } + // A native `synchronize` stand-in that genuinely hops to the real calling (main) thread instead of running the // pushed closure inline: it hands the closure to PumpQueuedCall (run on this test's true main thread) and blocks // the worker until that pump has actually invoked it, so the test observes MainThread.Invoke's full round trip // rather than only the rejection path the other stand-in tests prove. - private sealed unsafe class HoppingSynchronizeStandIn : IDisposable + private sealed class HoppingSynchronizeStandIn : IDisposable { private static ManualResetEventSlim? s_queued; private static ManualResetEventSlim? s_completed; @@ -293,6 +340,17 @@ private HoppingSynchronizeStandIn() { } + public void Dispose() + { + Assert.True(s_pumpedCallStatus.IsOk, + s_pumpedCallStatus.IsOk ? string.Empty : "The pumped call failed."); + s_queued?.Dispose(); + s_completed?.Dispose(); + s_queued = null; + s_completed = null; + s_pendingRef = null; + } + public static HoppingSynchronizeStandIn Install(LuaState main) { s_queued = new ManualResetEventSlim(false); @@ -321,17 +379,6 @@ public static bool PumpQueuedCall(TimeSpan timeout) return true; } - public void Dispose() - { - Assert.True(s_pumpedCallStatus.IsOk, - s_pumpedCallStatus.IsOk ? string.Empty : "The pumped call failed."); - s_queued?.Dispose(); - s_completed?.Dispose(); - s_queued = null; - s_completed = null; - s_pendingRef = null; - } - [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] private static int SynchronizeThunk(nint pointer) { @@ -359,51 +406,4 @@ private static int SynchronizeThunk(nint pointer) } } } - - private static void InstallSynchronizeStandIn(NativeLuaState state) - { - LuaState L = LuaRuntime.AcquireState(); - using LuaFrame frame = new(L); - LuaStatus status = L.TryExecute( - "synchronize_calls = 0; function synchronize(f, ...) synchronize_calls = synchronize_calls + 1; return f(...) end"u8, - 0); - Assert.True(status.IsOk, "stand-in install failed: " + LuaError.FromStack(L, status).Message); - Assert.Equal(0, LuaApi.lua_gettop(state.L)); - } - - private static long ReadGlobalInteger(NativeLuaState state, ReadOnlySpan name) - { - LuaState L = new(state.Pointer); - using LuaFrame frame = new(L); - Assert.True(L.TryGetGlobal(name).IsOk); - Assert.True(L.TryReadInteger(-1, out long value)); - return value; - } - - private static T RunOnWorker(Func work) - { - // Boxes, not captured locals: static analysis (S2583) does not see a lambda's write to a captured local. - // Join publishes the worker's writes to this thread. - StrongBox result = new(); - StrongBox crash = new(); - Thread worker = new(() => - { - try - { - result.Value = work(); - } - catch (Exception exception) - { - crash.Value = exception; - } - }); - worker.Start(); - worker.Join(); - if (crash.Value is { } failure) - { - throw new InvalidOperationException("The worker crashed.", failure); - } - - return result.Value!; - } } diff --git a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/CoexistencePluginAFunctions.cs b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/CoexistencePluginAFunctions.cs index df5cb67a..df5e6a69 100644 --- a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/CoexistencePluginAFunctions.cs +++ b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/CoexistencePluginAFunctions.cs @@ -2,7 +2,7 @@ namespace LivePlugin.Coexistence.PluginA; -internal static partial class CoexistencePluginAFunctions +internal static class CoexistencePluginAFunctions { private static long s_pingCount; diff --git a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/CoexistencePluginBFunctions.cs b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/CoexistencePluginBFunctions.cs index ee848e91..fd2ffe6c 100644 --- a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/CoexistencePluginBFunctions.cs +++ b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/CoexistencePluginBFunctions.cs @@ -2,7 +2,7 @@ namespace LivePlugin.Coexistence.PluginB; -internal static partial class CoexistencePluginBFunctions +internal static class CoexistencePluginBFunctions { private static long s_pingCount; diff --git a/tests/CheatEngine.SDK.LivePlugin/LiveFunctions.cs b/tests/CheatEngine.SDK.LivePlugin/LiveFunctions.cs index b929bf00..804f9d15 100644 --- a/tests/CheatEngine.SDK.LivePlugin/LiveFunctions.cs +++ b/tests/CheatEngine.SDK.LivePlugin/LiveFunctions.cs @@ -11,7 +11,7 @@ namespace LivePlugin; /// ; /// unregisters them through UnregisterLuaFunctions. /// -internal static partial class LiveFunctions +internal static class LiveFunctions { private static long s_pingCount; diff --git a/tests/CheatEngine.SDK.LivePlugin/README.md b/tests/CheatEngine.SDK.LivePlugin/README.md index ae087a73..1d410a92 100644 --- a/tests/CheatEngine.SDK.LivePlugin/README.md +++ b/tests/CheatEngine.SDK.LivePlugin/README.md @@ -55,10 +55,10 @@ land in `artifacts/obj/CheatEngine.SDK.LivePlugin/generated//`. Prerequisites: -| Need | Detail | -|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Platform | Windows x64 with the pinned CE `7.7.0.10621` host (verify SHA-256 `9727076DA50924E4A097B49A02155E4B34759269C3017FF31375364B8826EB4D`) and Sysinternals [DebugView](https://learn.microsoft.com/sysinternals/downloads/debugview) | -| SDK | .NET SDK 10.0.401 exactly, the version `global.json` pins with `rollForward: disable` | +| Need | Detail | +|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Platform | Windows x64 with the pinned CE `7.7.0.10621` host (verify SHA-256 `9727076DA50924E4A097B49A02155E4B34759269C3017FF31375364B8826EB4D`) and Sysinternals [DebugView](https://learn.microsoft.com/sysinternals/downloads/debugview) | +| SDK | .NET SDK 10.0.401 exactly, the version `global.json` pins with `rollForward: disable` | | Runtime policy | The inspected CE binary uses the `nethost`/`hostfxr` route. The workspace's .NET 10 `ce.runtimeconfig.json` is a local modification, not an installer baseline. Preserve the controlled host's existing policy and record it with the transcript, including its observed hash; do not treat this guide as permission to edit an installed CE runtime configuration. Microsoft documents `nethost`/`hostfxr` for framework-dependent components. | 1. Build the plugin with `dotnet build tests/CheatEngine.SDK.LivePlugin/CheatEngine.SDK.LivePlugin.csproj -c Release`. diff --git a/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStateTests.cs b/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStateTests.cs index ce265b8b..72aae196 100644 --- a/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStateTests.cs +++ b/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStateTests.cs @@ -8,6 +8,7 @@ public sealed class LiveProbeStateTests public void CaptureHostProfile_when_authorization_expires_after_enable_returns_fresh_denial() { int evaluationCount = 0; + AuthorizationDecision evaluateAuthorization() { evaluationCount++; @@ -15,6 +16,7 @@ AuthorizationDecision evaluateAuthorization() ? AllowedAuthorization() : AuthorizationDecision.Denied("The authorization manifest has expired."); } + LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => 401); bool wasCaptured = false; @@ -36,6 +38,7 @@ AuthorizationDecision evaluateAuthorization() public void CaptureHostProfile_when_target_image_changes_after_enable_returns_fresh_denial() { int evaluationCount = 0; + AuthorizationDecision evaluateAuthorization() { evaluationCount++; @@ -43,6 +46,7 @@ AuthorizationDecision evaluateAuthorization() ? AllowedAuthorization() : AuthorizationDecision.Denied("The declared target SHA-256 differs from its live process image."); } + LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => 401); bool wasCaptured = false; @@ -64,11 +68,13 @@ AuthorizationDecision evaluateAuthorization() public void CaptureHostProfile_when_ce_target_pid_changes_after_enable_returns_denial() { int evaluationCount = 0; + AuthorizationDecision evaluateAuthorization() { evaluationCount++; return AllowedAuthorization(); } + LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => 401); bool wasCaptured = false; @@ -90,6 +96,7 @@ AuthorizationDecision evaluateAuthorization() public void CaptureHostProfile_when_fresh_authorization_and_pid_match_passes_fresh_decision_to_capture() { int evaluationCount = 0; + AuthorizationDecision evaluateAuthorization() { evaluationCount++; @@ -97,6 +104,7 @@ AuthorizationDecision evaluateAuthorization() ? AuthorizationDecision.Denied("The manifest was not present during enable.") : AllowedAuthorization(); } + LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => throw new InvalidOperationException("The denied enable state must not read CE's PID.")); @@ -113,6 +121,7 @@ AuthorizationDecision evaluateAuthorization() public void TryRequireRuntimeAuthorization_when_manifest_expires_after_enable_rechecks_and_denies() { int evaluationCount = 0; + AuthorizationDecision evaluateAuthorization() { evaluationCount++; @@ -120,6 +129,7 @@ AuthorizationDecision evaluateAuthorization() ? AllowedAuthorization() : AuthorizationDecision.Denied("The authorization manifest has expired."); } + LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => 401); bool isAllowed = LiveProbeState.TryRequireRuntimeAuthorization(evaluateAuthorization, @@ -137,11 +147,13 @@ AuthorizationDecision evaluateAuthorization() public void TryRequireRuntimeAuthorization_when_ce_target_pid_changes_after_enable_rechecks_and_denies() { int evaluationCount = 0; + AuthorizationDecision evaluateAuthorization() { evaluationCount++; return AllowedAuthorization(); } + LiveProbeState.ValidateAfterEnable(evaluateAuthorization, static () => 401); bool isAllowed = LiveProbeState.TryRequireRuntimeAuthorization(evaluateAuthorization, static () => 402, diff --git a/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStatusTests.cs b/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStatusTests.cs index 21d943ab..45918a73 100644 --- a/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStatusTests.cs +++ b/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStatusTests.cs @@ -53,11 +53,7 @@ public void Status_reports_the_exports_size_and_the_raw_second_bootstrap_integer [Fact] public void Status_without_an_enabled_context_reports_none_instead_of_zero_values() { - LiveProbeHostFacts host = Facts(0, 0, 0, 0) with - { - HasContext = false, - Phase = "Registered" - }; + LiveProbeHostFacts host = Facts(0, 0, 0, 0) with { HasContext = false, Phase = "Registered" }; string text = LiveProbeState.GetStatus(host); using JsonDocument json = JsonDocument.Parse(LiveProbeState.GetStatusJson(host)); diff --git a/tests/CheatEngine.SDK.LiveProbe.Tests/ProbeHostGlobals.cs b/tests/CheatEngine.SDK.LiveProbe.Tests/ProbeHostGlobals.cs index bc916c33..73e3ee53 100644 --- a/tests/CheatEngine.SDK.LiveProbe.Tests/ProbeHostGlobals.cs +++ b/tests/CheatEngine.SDK.LiveProbe.Tests/ProbeHostGlobals.cs @@ -1,4 +1,4 @@ -namespace LiveProbe; +namespace CheatEngine.SDK.LiveProbe.Tests; // The source-linked LiveProbe sources call ProbeHostGlobals.GetOpenedProcessId, which the plugin project generates from // [LuaGlobal("getOpenedProcessID")]. The tests inject the PID reader and never call it; this stub keeps the same diff --git a/tests/CheatEngine.SDK.LiveProbe.Tests/README.md b/tests/CheatEngine.SDK.LiveProbe.Tests/README.md index c8e03c22..999125ef 100644 --- a/tests/CheatEngine.SDK.LiveProbe.Tests/README.md +++ b/tests/CheatEngine.SDK.LiveProbe.Tests/README.md @@ -23,12 +23,12 @@ namespace, so it neither loads the plugin nor runs its Lua source generator. Tes CE's opened PID, the fault-switch file reader and the `PluginHost` facts. `AssemblyInfo.cs` disables parallelization because the harness keeps process-wide static state. -| Test class | Covers | -|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------| -| `LiveProbeStateTests` | Fresh authorization and target-PID checks before host-profile capture and every protected command. | -| `LiveProbeStatusTests` | Text and JSON status (plugin id, epoch, exports size, raw second bootstrap integer), the exception hook and the pump hook. | -| `LiveProbeFaultInjectionTests` | The `liveprobe.fault.json` switch: never read without authorization, exact stage selection, ignored and reported failures. | -| `HostProfileObservationTests` | Typed outcomes for missing, locked, vanishing or protected identity files; the bridge record names the loaded module only. | +| Test class | Covers | +|--------------------------------|----------------------------------------------------------------------------------------------------------------------------| +| `LiveProbeStateTests` | Fresh authorization and target-PID checks before host-profile capture and every protected command. | +| `LiveProbeStatusTests` | Text and JSON status (plugin id, epoch, exports size, raw second bootstrap integer), the exception hook and the pump hook. | +| `LiveProbeFaultInjectionTests` | The `liveprobe.fault.json` switch: never read without authorization, exact stage selection, ignored and reported failures. | +| `HostProfileObservationTests` | Typed outcomes for missing, locked, vanishing or protected identity files; the bridge record names the loaded module only. | ## Promise diff --git a/tests/CheatEngine.SDK.LiveProbe/CE77LiveProbeBootstrap.cs b/tests/CheatEngine.SDK.LiveProbe/CE77LiveProbeBootstrap.cs index e3543f50..2e3bfc2d 100644 --- a/tests/CheatEngine.SDK.LiveProbe/CE77LiveProbeBootstrap.cs +++ b/tests/CheatEngine.SDK.LiveProbe/CE77LiveProbeBootstrap.cs @@ -2,9 +2,7 @@ using CheatEngine.SDK.Hosting.Bootstrap; using CheatEngine.SDK.Hosting.Diagnostics; -using LiveProbe; - -namespace CESDK; +namespace LiveProbe; /// /// The intentionally hand-written CE managed bootstrap used only by the CE 7.7 live-probe plugin. @@ -16,7 +14,7 @@ namespace CESDK; /// #pragma warning disable MA0048 // The file identifies the CE 7.7 probe; the host fixes the public bootstrap type name. #pragma warning disable MA0049 // CE's host requires CESDK.CESDK exactly. -public static unsafe class CESDK +public static class CESDK { /// /// CE's fixed managed component entry point. The second argument is recorded raw and deliberately has no @@ -34,7 +32,7 @@ public static int CEPluginInitialize(nint initRecord, int opaqueHostArgument) int result = PluginHost.InitializeManaged(initRecord, opaqueHostArgument); #else - int result = PluginHost.InitializeManaged(initRecord, opaqueHostArgument); + int result = PluginHost.InitializeManaged(initRecord, opaqueHostArgument); #endif LiveProbeState.TryWriteTailCanaryAfterPackedRecord(initRecord, result); return result; diff --git a/tests/CheatEngine.SDK.LiveProbe/Ce77LiveProbePlugin.cs b/tests/CheatEngine.SDK.LiveProbe/Ce77LiveProbePlugin.cs index b3e0f750..1f622949 100644 --- a/tests/CheatEngine.SDK.LiveProbe/Ce77LiveProbePlugin.cs +++ b/tests/CheatEngine.SDK.LiveProbe/Ce77LiveProbePlugin.cs @@ -3,6 +3,7 @@ using CheatEngine.SDK.Hosting.Diagnostics; using CheatEngine.SDK.Hosting.Plugin; using CheatEngine.SDK.Lua.Calls; +using CheatEngine.SDK.Lua.Runtime; using CheatEngine.SDK.Lua.State; namespace LiveProbe; @@ -20,7 +21,7 @@ internal sealed class Ce77LiveProbePlugin : CheatEnginePlugin /// protected override void OnEnable() { - LuaState state = CheatEngine.SDK.Lua.Runtime.LuaRuntime.AcquireState(); + LuaState state = LuaRuntime.AcquireState(); LuaStatus registration = ProbeConsole.RegisterLuaFunctions(state); HostLog.Write(registration.IsOk ? HostLogLevel.Information : HostLogLevel.Error, string.Create(CultureInfo.InvariantCulture, @@ -37,7 +38,7 @@ protected override void OnEnable() /// protected override void OnDisable() { - LuaState state = CheatEngine.SDK.Lua.Runtime.LuaRuntime.AcquireState(); + LuaState state = LuaRuntime.AcquireState(); LuaStatus registration = ProbeConsole.UnregisterLuaFunctions(state); HostLog.Write(registration.IsOk ? HostLogLevel.Information : HostLogLevel.Error, string.Create(CultureInfo.InvariantCulture, diff --git a/tests/CheatEngine.SDK.LiveProbe/HostProfileObservation.cs b/tests/CheatEngine.SDK.LiveProbe/HostProfileObservation.cs index d3fe445d..9997fdba 100644 --- a/tests/CheatEngine.SDK.LiveProbe/HostProfileObservation.cs +++ b/tests/CheatEngine.SDK.LiveProbe/HostProfileObservation.cs @@ -85,7 +85,7 @@ private static void WriteFileIdentityFields(Utf8JsonWriter writer, string? path, writer.WriteString("machine", reader.PEHeaders.CoffHeader.Machine.ToString()); } catch (Exception exception) when (exception is BadImageFormatException or IOException - or UnauthorizedAccessException) + or UnauthorizedAccessException) { writer.WriteString("machine", "unavailable: " + exception.GetType().Name); } @@ -132,7 +132,7 @@ internal static string ObserveFileVersion(string path, Func get return getFileVersion(path) ?? "not-present"; } catch (Exception exception) when (exception is ArgumentException or Win32Exception - or IOException or UnauthorizedAccessException) + or IOException or UnauthorizedAccessException) { return "unavailable: " + exception.GetType().Name; } @@ -152,7 +152,7 @@ internal static string ObserveFileVersion(string path, Func get } } catch (Exception exception) when (exception is InvalidOperationException or NotSupportedException - or Win32Exception) + or Win32Exception) { HostLog.Write(HostLogLevel.Warning, "CE 7.7 host-profile probe could not enumerate loaded modules.", exception); diff --git a/tests/CheatEngine.SDK.LiveProbe/LiveProbeAuthorization.cs b/tests/CheatEngine.SDK.LiveProbe/LiveProbeAuthorization.cs index e85be096..d10b460b 100644 --- a/tests/CheatEngine.SDK.LiveProbe/LiveProbeAuthorization.cs +++ b/tests/CheatEngine.SDK.LiveProbe/LiveProbeAuthorization.cs @@ -189,17 +189,17 @@ private static bool TryReadManifest(string path, out AuthorizationManifest manif using JsonDocument document = JsonDocument.Parse(stream); JsonElement root = document.RootElement; if (root.ValueKind != JsonValueKind.Object || !TryString(root, "schema", out string schema) || - !string.Equals(schema, "ce77-live-probe-v1", StringComparison.Ordinal) || - !TryString(root, "acknowledgement", out string acknowledgement) || - !TryString(root, "hostSha256", out string hostSha256) || - !TryString(root, "targetSha256", out string targetSha256) || - !TryString(root, "expiresUtc", out string expiresText) || - !root.TryGetProperty("targetProcessId", out JsonElement pid) || - !pid.TryGetInt32(out int targetProcessId) || - !root.TryGetProperty("disposable", out JsonElement disposable) || - disposable.ValueKind is not JsonValueKind.True and not JsonValueKind.False || - !DateTimeOffset.TryParse(expiresText, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, - out DateTimeOffset expiresUtc)) + !string.Equals(schema, "ce77-live-probe-v1", StringComparison.Ordinal) || + !TryString(root, "acknowledgement", out string acknowledgement) || + !TryString(root, "hostSha256", out string hostSha256) || + !TryString(root, "targetSha256", out string targetSha256) || + !TryString(root, "expiresUtc", out string expiresText) || + !root.TryGetProperty("targetProcessId", out JsonElement pid) || + !pid.TryGetInt32(out int targetProcessId) || + !root.TryGetProperty("disposable", out JsonElement disposable) || + disposable.ValueKind is not JsonValueKind.True and not JsonValueKind.False || + !DateTimeOffset.TryParse(expiresText, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, + out DateTimeOffset expiresUtc)) { failure = "The authorization manifest is missing a required ce77-live-probe-v1 field."; return false; @@ -210,7 +210,7 @@ disposable.ValueKind is not JsonValueKind.True and not JsonValueKind.False || return true; } catch (Exception exception) when (exception is IOException or UnauthorizedAccessException or JsonException - or ArgumentException) + or ArgumentException) { failure = exception.GetType().Name + ": " + exception.Message; return false; @@ -246,7 +246,7 @@ private static bool TryGetProcessImage(int processId, out string path, out strin return true; } catch (Exception exception) when (exception is ArgumentException or InvalidOperationException - or NotSupportedException or Win32Exception) + or NotSupportedException or Win32Exception) { failure = exception.GetType().Name + ": " + exception.Message; return false; @@ -275,7 +275,7 @@ private static bool IsAmd64Pe(string path, out string failure) return false; } catch (Exception exception) when (exception is BadImageFormatException or IOException - or UnauthorizedAccessException) + or UnauthorizedAccessException) { failure = exception.GetType().Name + ": " + exception.Message; return false; diff --git a/tests/CheatEngine.SDK.LiveProbe/LiveProbeFaultInjection.cs b/tests/CheatEngine.SDK.LiveProbe/LiveProbeFaultInjection.cs index 2b458941..427127a9 100644 --- a/tests/CheatEngine.SDK.LiveProbe/LiveProbeFaultInjection.cs +++ b/tests/CheatEngine.SDK.LiveProbe/LiveProbeFaultInjection.cs @@ -79,7 +79,7 @@ internal static LiveProbeFaultDecision Evaluate(Func eval text = readFile(path); } catch (Exception exception) when (exception is IOException or UnauthorizedAccessException - or ArgumentException or NotSupportedException) + or ArgumentException or NotSupportedException) { return new LiveProbeFaultDecision(LiveProbeFaultStage.None, "Fault switch ignored: " + FileName + " could not be read (" + exception.GetType().Name + ").", true); @@ -147,7 +147,7 @@ internal static void EnterOnDisable() private static LiveProbeFaultDecision EvaluateForEnable() { string pluginDirectory = Path.GetDirectoryName(typeof(LiveProbeFaultInjection).Assembly.Location) ?? - AppContext.BaseDirectory; + AppContext.BaseDirectory; LiveProbeFaultDecision decision = Evaluate(LiveProbeAuthorization.Evaluate, pluginDirectory, ReadIfPresent); int sequence; lock (Gate) @@ -184,7 +184,7 @@ private static LiveProbeFaultDecision Parse(string text) using JsonDocument document = JsonDocument.Parse(text); JsonElement root = document.RootElement; if (root.ValueKind != JsonValueKind.Object || - !root.TryGetProperty("schema", out JsonElement schema) || schema.ValueKind != JsonValueKind.String) + !root.TryGetProperty("schema", out JsonElement schema) || schema.ValueKind != JsonValueKind.String) { return Ignored("it has no schema string"); } @@ -234,7 +234,7 @@ private static LiveProbeFaultDecision Ignored(string why) if (file.Length > MaximumFileBytes) { throw new IOException("The fault switch is larger than " + - MaximumFileBytes.ToString(CultureInfo.InvariantCulture) + " bytes."); + MaximumFileBytes.ToString(CultureInfo.InvariantCulture) + " bytes."); } return File.ReadAllText(path); diff --git a/tests/CheatEngine.SDK.LiveProbe/LiveProbeState.cs b/tests/CheatEngine.SDK.LiveProbe/LiveProbeState.cs index fc1bf1f3..a7ef57d5 100644 --- a/tests/CheatEngine.SDK.LiveProbe/LiveProbeState.cs +++ b/tests/CheatEngine.SDK.LiveProbe/LiveProbeState.cs @@ -97,10 +97,7 @@ internal static void TryWriteTailCanaryAfterPackedRecord(nint initRecord, int bo { lock (Gate) { - s_bootstrap = s_bootstrap with - { - TailFailure = Describe(exception) - }; + s_bootstrap = s_bootstrap with { TailFailure = Describe(exception) }; } HostLog.Write(HostLogLevel.Error, "CE 7.7 live-probe tail canary failed.", exception); @@ -373,8 +370,7 @@ internal static string BeginSynchronizeProbe() Thread thread = new(RunSynchronizeProbe) { - IsBackground = true, - Name = "CheatEngine.SDK CE77 synchronize probe" + IsBackground = true, Name = "CheatEngine.SDK CE77 synchronize probe" }; thread.Start(); return "Synchronize probe started. Do not block the CE GUI thread; poll ce77_live_probe_synchronize_status()."; @@ -420,11 +416,7 @@ internal static string BeginLuaThreadProbe() // The delayed worker starts only after this Lua callback has returned its string to CE. It is still a live, // opt-in observation against CE's per-thread state contract, never a general concurrency guarantee for Lua. - Thread thread = new(RunLuaThreadProbe) - { - IsBackground = true, - Name = "CheatEngine.SDK CE77 Lua thread probe" - }; + Thread thread = new(RunLuaThreadProbe) { IsBackground = true, Name = "CheatEngine.SDK CE77 Lua thread probe" }; thread.Start(); return "Lua thread/registry probe started. Do not run other Lua code for one second; poll ce77_live_probe_lua_threads_status()."; @@ -643,34 +635,21 @@ private static void RunSynchronizeProbe() { MainThread.Invoke( static _ => throw new InvalidOperationException("CE77-live-probe expected dispatch failure."), 0); - observation = observation with - { - ExceptionResult = "unexpectedly returned" - }; + observation = observation with { ExceptionResult = "unexpectedly returned" }; } catch (InvalidOperationException exception) { - observation = observation with - { - ExceptionResult = "re-thrown: " + exception.Message - }; + observation = observation with { ExceptionResult = "re-thrown: " + exception.Message }; } } catch (Exception exception) { - observation = observation with - { - Completion = "failed", - Failure = Describe(exception) - }; + observation = observation with { Completion = "failed", Failure = Describe(exception) }; } lock (Gate) { - s_synchronize = observation with - { - IsRunning = false - }; + s_synchronize = observation with { IsRunning = false }; } } @@ -707,19 +686,12 @@ private static void RunLuaThreadProbe() } catch (Exception exception) { - observation = observation with - { - Completion = "failed", - Failure = Describe(exception) - }; + observation = observation with { Completion = "failed", Failure = Describe(exception) }; } lock (Gate) { - s_luaThread = observation with - { - IsRunning = false - }; + s_luaThread = observation with { IsRunning = false }; } } diff --git a/tests/CheatEngine.SDK.LiveProbe/LiveProbeStatusReport.cs b/tests/CheatEngine.SDK.LiveProbe/LiveProbeStatusReport.cs index 96cfbfea..fe943173 100644 --- a/tests/CheatEngine.SDK.LiveProbe/LiveProbeStatusReport.cs +++ b/tests/CheatEngine.SDK.LiveProbe/LiveProbeStatusReport.cs @@ -58,7 +58,8 @@ private static void WriteBootstrap(Utf8JsonWriter writer, in LiveProbeStatusSnap writer.WriteNumber("tailWrites", snapshot.TailWrites); if (snapshot.TailCanaryWritten) { - writer.WriteString("tailBeforeHex", snapshot.TailReadBeforeWrite.ToString("X8", CultureInfo.InvariantCulture)); + writer.WriteString("tailBeforeHex", + snapshot.TailReadBeforeWrite.ToString("X8", CultureInfo.InvariantCulture)); } else { diff --git a/tests/CheatEngine.SDK.LiveProbe/ProbeConsole.cs b/tests/CheatEngine.SDK.LiveProbe/ProbeConsole.cs index 76a0b596..7da402ba 100644 --- a/tests/CheatEngine.SDK.LiveProbe/ProbeConsole.cs +++ b/tests/CheatEngine.SDK.LiveProbe/ProbeConsole.cs @@ -6,7 +6,7 @@ namespace LiveProbe; /// Lua-console commands for the CE 7.7 live-probe plugin. Every command returns a self-contained status record; /// commands that initiate a probe first require the exact host and disposable-target authorization gate. /// -internal static partial class ProbeConsole +internal static class ProbeConsole { /// Returns the gate decision and all observations accumulated in this process. [LuaFunction("ce77_live_probe_status")] diff --git a/tests/CheatEngine.SDK.LiveProbe/README.md b/tests/CheatEngine.SDK.LiveProbe/README.md index b926acb5..1cde4a78 100644 --- a/tests/CheatEngine.SDK.LiveProbe/README.md +++ b/tests/CheatEngine.SDK.LiveProbe/README.md @@ -3,7 +3,8 @@ `CheatEngine.SDK.LiveProbe` is a manually loaded **evidence harness**, not a unit-test project, sample plugin, package asset, or normal CI input. It records CE 7.7 behaviours that fixture tests cannot establish: the raw managed bootstrap argument, the disputed packed-record tail, `synchronize`, per-thread Lua states and registry sharing, external -`resetLuaState`, CE userdata, callback cleanup on plugin disable, and the Checkpoint B hooks of the qualification runner. +`resetLuaState`, CE userdata, callback cleanup on plugin disable, and the Checkpoint B hooks of the qualification +runner. ## Objective @@ -17,7 +18,8 @@ non-ASCII plugin name (Q05.a) and where the SDK assemblies were loaded from (Q40 Only a real Cheat Engine host can show these behaviours, and C1/C2 success is never host evidence. The harness keeps every probe opt-in and fail-closed, so -loading it by mistake observes nothing and changes nothing. The solution compiles it, so a compile break is caught by CI; +loading it by mistake observes nothing and changes nothing. The solution compiles it, so a compile break is caught by +CI; CI never loads or runs it. ## Safety boundary @@ -46,17 +48,17 @@ containing sensitive paths, or captured process memory in source control. ## How it works -| File | Content | -|-----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `CE77LiveProbeBootstrap.cs` | The hand-written `CESDK.CESDK.CEPluginInitialize(nint, int)`. It records the second integer raw, then forwards to `PluginHost.InitializeManaged`. With `LIVEPROBE_NON_ASCII_NAME` it selects the non-ASCII factory. | -| `ProbePluginFactory.cs`, `ProbePluginFactoryNonAscii.cs` | The factories. `Create` first evaluates the fault switch. The non-ASCII factory exists only in the `-p:LiveProbeNonAsciiName=true` build. | -| `Ce77LiveProbePlugin.cs` | `OnEnable` registers the console commands, re-checks the gates and applies the `OnEnable` fault; `OnDisable` unregisters them and applies the `OnDisable` fault. | -| `ProbeConsole.cs`, `ProbeHostGlobals.cs` | The `[LuaFunction]` console commands below and the one `[LuaGlobal("getOpenedProcessID")]` binding. | -| `LiveProbeAuthorization.cs`, `AuthorizationDecision.cs` | The fail-closed gate: exact host hash and version, operator acknowledgement, unexpired manifest, live hash-verified disposable target. | -| `LiveProbeState.cs` | Process-local observations and the command implementations. Every command that acts re-evaluates the gate first. | -| `LiveProbeFaultInjection.cs`, `LiveProbeFaultStage.cs`, `LiveProbeFaultDecision.cs` | The fault switch (see below). Lua-free, compile-linked into the tests. | -| `LiveProbeHostFacts.cs`, `LiveProbeStatusSnapshot.cs`, `LiveProbeStatusReport.cs` | The status record: `PluginHost` facts, gates, fault decisions and observations serialized as `ce77-live-probe-status-v1` JSON. Lua-free, compile-linked into the tests. | -| `HostProfileObservation.cs` | The `ce77-live-host-profile-v1` identity record of host, Lua module, bridge, plugin and target files. | +| File | Content | +|-------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `CE77LiveProbeBootstrap.cs` | The hand-written `CESDK.CESDK.CEPluginInitialize(nint, int)`. It records the second integer raw, then forwards to `PluginHost.InitializeManaged`. With `LIVEPROBE_NON_ASCII_NAME` it selects the non-ASCII factory. | +| `ProbePluginFactory.cs`, `ProbePluginFactoryNonAscii.cs` | The factories. `Create` first evaluates the fault switch. The non-ASCII factory exists only in the `-p:LiveProbeNonAsciiName=true` build. | +| `Ce77LiveProbePlugin.cs` | `OnEnable` registers the console commands, re-checks the gates and applies the `OnEnable` fault; `OnDisable` unregisters them and applies the `OnDisable` fault. | +| `ProbeConsole.cs`, `ProbeHostGlobals.cs` | The `[LuaFunction]` console commands below and the one `[LuaGlobal("getOpenedProcessID")]` binding. | +| `LiveProbeAuthorization.cs`, `AuthorizationDecision.cs` | The fail-closed gate: exact host hash and version, operator acknowledgement, unexpired manifest, live hash-verified disposable target. | +| `LiveProbeState.cs` | Process-local observations and the command implementations. Every command that acts re-evaluates the gate first. | +| `LiveProbeFaultInjection.cs`, `LiveProbeFaultStage.cs`, `LiveProbeFaultDecision.cs` | The fault switch (see below). Lua-free, compile-linked into the tests. | +| `LiveProbeHostFacts.cs`, `LiveProbeStatusSnapshot.cs`, `LiveProbeStatusReport.cs` | The status record: `PluginHost` facts, gates, fault decisions and observations serialized as `ce77-live-probe-status-v1` JSON. Lua-free, compile-linked into the tests. | +| `HostProfileObservation.cs` | The `ce77-live-host-profile-v1` identity record of host, Lua module, bridge, plugin and target files. | ### Console commands @@ -64,18 +66,18 @@ Every command returns a self-contained string. Commands that act (all except the authorization manifest, the target image and CE's opened PID immediately before acting, and return `Live probe denied: ` otherwise. -| Command | Observation | Used by | -|-----------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------| -| `ce77_live_probe_status()` | Human-readable: bootstrap calls, the raw second integer (`opaqueSecondInt`, never labelled size or version), `PluginHost.LastInitRecordArgument`, phase, plugin id, epoch, reported exports size, gates, prior observations. | operator | -| `ce77_live_probe_status_json()` | The same facts as one `ce77-live-probe-status-v1` JSON object, plus assembly locations, MVIDs, the Hosting load context and every fault-switch decision. Not gated: it reads process-local facts only. | Q03, Q04, Q05, Q06, Q08, Q40 | -| `ce77_live_probe_host_profile()` | One `ce77-live-host-profile-v1` JSON identity record for the authorized CE host, loaded Lua module, loaded bridge, plugin and disposable target. | Q40 | -| `ce77_live_probe_throw_managed_exception()` | Throws `InvalidOperationException("CE 7.7 live probe deliberate managed exception (Q14).")` inside the generated thunk; call it under `pcall` and record the Lua error. | Q14 | -| `ce77_live_probe_pump_messages(seconds)` | Pumps CE's messages for 1–60 seconds from admitted main-thread work and returns a `ce77-live-probe-pump-v1` JSON record of the lifecycle phases seen. The operator unticks the plugin meanwhile. An observation, not a promise. | Q07 | -| `ce77_live_probe_begin_synchronize()` then `ce77_live_probe_synchronize_status()` | Worker, thunk and nested-invoke managed thread IDs; return round-trip and propagated exception. | operator | -| `ce77_live_probe_begin_lua_threads()` then `ce77_live_probe_lua_threads_status()` | GUI and worker `lua_State*` identities and a private raw-registry marker read by the worker. Do not execute other Lua for one second. | Q19 | -| `ce77_live_probe_snapshot_before_reset()` / `ce77_live_probe_snapshot_after_reset()` | State pointer, SDK epoch and reference slot before and after an operator-run `resetLuaState()`; whether the old SDK reference still pushed. The harness never calls the reset. | Q17, Q18 | -| `ce77_live_probe_userdata()` | `type(getMainForm())` and `tostring(getMainForm())`, without retaining the userdata or invoking the host-object pusher. | operator | -| `ce77_live_probe_prepare_callback_shutdown()` | Installs a counter callback and leaves it registered in `OnDisable`, so `LuaRuntime.Detach` must neutralize it. Call `pcall(ce77_live_probe_callback_shutdown)` before and after disabling. | Q15 | +| Command | Observation | Used by | +|--------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------| +| `ce77_live_probe_status()` | Human-readable: bootstrap calls, the raw second integer (`opaqueSecondInt`, never labelled size or version), `PluginHost.LastInitRecordArgument`, phase, plugin id, epoch, reported exports size, gates, prior observations. | operator | +| `ce77_live_probe_status_json()` | The same facts as one `ce77-live-probe-status-v1` JSON object, plus assembly locations, MVIDs, the Hosting load context and every fault-switch decision. Not gated: it reads process-local facts only. | Q03, Q04, Q05, Q06, Q08, Q40 | +| `ce77_live_probe_host_profile()` | One `ce77-live-host-profile-v1` JSON identity record for the authorized CE host, loaded Lua module, loaded bridge, plugin and disposable target. | Q40 | +| `ce77_live_probe_throw_managed_exception()` | Throws `InvalidOperationException("CE 7.7 live probe deliberate managed exception (Q14).")` inside the generated thunk; call it under `pcall` and record the Lua error. | Q14 | +| `ce77_live_probe_pump_messages(seconds)` | Pumps CE's messages for 1–60 seconds from admitted main-thread work and returns a `ce77-live-probe-pump-v1` JSON record of the lifecycle phases seen. The operator unticks the plugin meanwhile. An observation, not a promise. | Q07 | +| `ce77_live_probe_begin_synchronize()` then `ce77_live_probe_synchronize_status()` | Worker, thunk and nested-invoke managed thread IDs; return round-trip and propagated exception. | operator | +| `ce77_live_probe_begin_lua_threads()` then `ce77_live_probe_lua_threads_status()` | GUI and worker `lua_State*` identities and a private raw-registry marker read by the worker. Do not execute other Lua for one second. | Q19 | +| `ce77_live_probe_snapshot_before_reset()` / `ce77_live_probe_snapshot_after_reset()` | State pointer, SDK epoch and reference slot before and after an operator-run `resetLuaState()`; whether the old SDK reference still pushed. The harness never calls the reset. | Q17, Q18 | +| `ce77_live_probe_userdata()` | `type(getMainForm())` and `tostring(getMainForm())`, without retaining the userdata or invoking the host-object pusher. | operator | +| `ce77_live_probe_prepare_callback_shutdown()` | Installs a counter callback and leaves it registered in `OnDisable`, so `LuaRuntime.Detach` must neutralize it. Call `pcall(ce77_live_probe_callback_shutdown)` before and after disabling. | Q15 | ### Fault switch (Q06, Q08) @@ -88,7 +90,8 @@ A file named `liveprobe.fault.json` next to `CheatEngine.SDK.LiveProbe.dll` sele `throwIn` is `None`, `FactoryCreate` (the factory throws before constructing the plugin; the enable fails and the next enable tries again), `OnEnable` (after the console commands are registered) or `OnDisable` (after they are unregistered). The switch is read once per enable, without Lua, and only when the authorization gate allows: without -the manifest the file is never opened. An unknown schema, an unknown stage or malformed JSON is ignored and reported. Every +the manifest the file is never opened. An unknown schema, an unknown stage or malformed JSON is ignored and reported. +Every decision is logged and appears under `faultInjection` in `ce77_live_probe_status_json()`, with the list of stages that actually threw. The runner writes and deletes the file in the bundle folder; it never lives in the repository. @@ -97,8 +100,8 @@ actually threw. The runner writes and deletes the file in the bundle folder; it `dotnet build tests/CheatEngine.SDK.LiveProbe/CheatEngine.SDK.LiveProbe.csproj -c Release -p:LiveProbeNonAsciiName=true` defines `LIVEPROBE_NON_ASCII_NAME`, and the bootstrap then registers the name `CheatEngine.SDK Live Probe é 日本` (one Latin-1 character and two characters outside code page 1252). It settles, by observation, whether Cheat Engine 7.7 -decodes the name the SDK converts to the process ANSI code page -([`AnsiNameBuffer`](../../libs/CheatEngine.SDK.Hosting/Bootstrap/AnsiNameBuffer.cs)). The default build keeps the ASCII +decodes the name the SDK converts to the process ANSI code page ([ +`AnsiNameBuffer`](../../libs/CheatEngine.SDK.Hosting/Bootstrap/AnsiNameBuffer.cs)). The default build keeps the ASCII name `CheatEngine.SDK CE 7.7 Live Probe`. The switch writes to the same output folder, so rebuild without it afterwards. ## Build and load @@ -138,7 +141,8 @@ disposable target through its normal cleanup route. Do not force-unload assembli ## Promise - The harness is compiled by CI through `CheatEngine.SDK.slnx` as an x64 dynamic-loading plugin that is not a test - module and never packs (`QualificationHarnessShapeTests.LiveProbe_is_in_the_solution_as_an_x64_dynamic_loading_plugin_that_never_packs`). + module and never packs + (`QualificationHarnessShapeTests.LiveProbe_is_in_the_solution_as_an_x64_dynamic_loading_plugin_that_never_packs`). - A fresh authorization is required before every acting command, and a changed manifest, target image or CE target PID is refused (`LiveProbeStateTests`). - The raw second bootstrap integer and the reported exports size are reported without interpretation @@ -146,7 +150,8 @@ disposable target through its normal cleanup route. Do not force-unload assembli - Without authorization the exception and pump hooks are inert, and the pump refuses a duration outside 1–60 seconds before any host call (`LiveProbeStatusTests`). - The two status commands are deliberately not gated: they serialize process-local facts (bootstrap record, `PluginHost` - state, gate results, fault decisions, assembly identities), touch no target and make no Lua call of their own; an absent context is + state, gate results, fault decisions, assembly identities), touch no target and make no Lua call of their own; an + absent context is reported as absent, never as zero values (`LiveProbeStatusTests.Status_without_an_enabled_context_reports_none_instead_of_zero_values`, `LiveProbeStatusTests.Status_json_reports_the_fault_switch_decision_and_the_assembly_identities`). @@ -157,7 +162,8 @@ disposable target through its normal cleanup route. Do not force-unload assembli to the application (`HostProfileObservationTests.Host_profile_records_the_loaded_bridge_module_and_never_a_file_next_to_the_application`). - No live test is invoked by `dotnet test`, normal CI, Release validation or packaging: the solution only compiles it, - and no workflow references the runner (`LocalQualificationRunnerTests.No_workflow_references_the_local_qualification_runner`). + and no workflow references the runner + (`LocalQualificationRunnerTests.No_workflow_references_the_local_qualification_runner`). ## Run the tests diff --git a/tests/CheatEngine.SDK.Lua.FailureProbe/Program.cs b/tests/CheatEngine.SDK.Lua.FailureProbe/Program.cs index 6fad5749..046c6f97 100644 --- a/tests/CheatEngine.SDK.Lua.FailureProbe/Program.cs +++ b/tests/CheatEngine.SDK.Lua.FailureProbe/Program.cs @@ -95,9 +95,9 @@ public static int Main(string[] arguments) private static bool HasValidArguments(string[] arguments) { return arguments.Length is >= 1 and <= 2 && - (arguments.Length != 2 || - string.Equals(arguments[1], CheckStackGrowthMode, StringComparison.Ordinal) || - string.Equals(arguments[1], GeneratedFunctionAllocationMode, StringComparison.Ordinal)); + (arguments.Length != 2 || + string.Equals(arguments[1], CheckStackGrowthMode, StringComparison.Ordinal) || + string.Equals(arguments[1], GeneratedFunctionAllocationMode, StringComparison.Ordinal)); } private static int RunRequestedProbe(LuaState state, nint module, string[] arguments) @@ -507,7 +507,7 @@ private static int VerifyUncheckedFunctionReservationFailure(LuaState state, Lua catch (InvalidOperationException exception) { if (!string.Equals(exception.Message, UncheckedFunctionReservationFailureMessage, - StringComparison.Ordinal)) + StringComparison.Ordinal)) { return Fail("PushUncheckedFunction returned an unstable reservation failure message"); } @@ -1055,7 +1055,7 @@ private static int ProbeHostObjectPusherLongJump( } if (!state.TryReadString(-1, out string? error) || - !error.Contains("bad argument #1", StringComparison.Ordinal)) + !error.Contains("bad argument #1", StringComparison.Ordinal)) { return Fail("PushHostObject did not leave the native luaL_checkinteger failure message on the stack"); } diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/Initialization/LuaApiBoundTableTests.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/Initialization/LuaApiBoundTableTests.cs index 7aaf14b9..9a5a420c 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/Initialization/LuaApiBoundTableTests.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/Initialization/LuaApiBoundTableTests.cs @@ -41,7 +41,7 @@ public void Every_slot_holds_an_address_inside_the_process() object table = typeof(LuaApi).GetField("s_table", BindingFlags.Static | BindingFlags.NonPublic)!.GetValue(null)!; FieldInfo[] slots = typeof(LuaApi.Table).GetFields(BindingFlags.Instance | BindingFlags.Public | - BindingFlags.NonPublic); + BindingFlags.NonPublic); Assert.NotEmpty(slots); foreach (FieldInfo slot in slots) diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs index bca49f83..bafac348 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs @@ -96,7 +96,7 @@ private static bool HasDelayImports(string path) int delayImportDirectoryOffset = optionalOffset + 112 + (13 * 8); return ReadUInt32(image, delayImportDirectoryOffset) != 0 || - ReadUInt32(image, delayImportDirectoryOffset + sizeof(uint)) != 0; + ReadUInt32(image, delayImportDirectoryOffset + sizeof(uint)) != 0; } private static List ReadExportedNames(string path) diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaInteropPrimitiveMatrixTests.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaInteropPrimitiveMatrixTests.cs index 7d4818eb..721a7f16 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaInteropPrimitiveMatrixTests.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaInteropPrimitiveMatrixTests.cs @@ -9,7 +9,8 @@ namespace CheatEngine.SDK.Lua.Interop.Tests.Protected; /// -/// The primitive matrix tests/CheatEngine.SDK.Repository.Tests/LuaBridge/TestData/lua-interop-primitives.json (embedded) against the real +/// The primitive matrix tests/CheatEngine.SDK.Repository.Tests/LuaBridge/TestData/lua-interop-primitives.json +/// (embedded) against the real /// : one row per public static member, the error class and stack effect its XML documentation /// states, the exports the function-pointer table binds, and the bridge catalogue's direct-call policy. DLL-free. /// @@ -22,10 +23,7 @@ public sealed partial class LuaInteropPrimitiveMatrixTests private static readonly Dictionary RaisesFromRemark = new(StringComparer.Ordinal) { - ["never"] = "Never", - ["memory"] = "Memory", - ["any"] = "Any", - ["always"] = "Always" + ["never"] = "Never", ["memory"] = "Memory", ["any"] = "Any", ["always"] = "Always" }; [Fact] @@ -43,8 +41,11 @@ public void Every_matrix_row_names_an_existing_LuaApi_member() { HashSet members = PublicMembers(); - string[] unknown = [.. Rows().Select(static row => row.GetProperty("member").GetString()!) - .Where(member => !members.Contains(member))]; + string[] unknown = + [ + .. Rows().Select(static row => row.GetProperty("member").GetString()!) + .Where(member => !members.Contains(member)) + ]; Assert.True(unknown.Length == 0, "Rows without a public static LuaApi member: " + string.Join(", ", unknown)); } @@ -53,7 +54,8 @@ public void Every_matrix_row_names_an_existing_LuaApi_member() public void Matrix_raises_class_equals_the_documented_raises_remark() { string path = Path.Combine(AppContext.BaseDirectory, DocumentationFile); - Assert.True(File.Exists(path), $"The XML documentation of CheatEngine.SDK.Lua.Interop was not copied to '{path}'."); + Assert.True(File.Exists(path), + $"The XML documentation of CheatEngine.SDK.Lua.Interop was not copied to '{path}'."); Dictionary remarks = ReadRemarks(XDocument.Load(path)); List problems = []; foreach (JsonElement row in Rows()) @@ -66,9 +68,10 @@ public void Matrix_raises_class_equals_the_documented_raises_remark() ? null : row.GetProperty("stackEffect").GetString(); if (!string.Equals(expectedRaises, row.GetProperty("raises").GetString(), StringComparison.Ordinal) || - !string.Equals(expectedStack, stack, StringComparison.Ordinal)) + !string.Equals(expectedStack, stack, StringComparison.Ordinal)) { - problems.Add($"{member}: documented {expectedStack ?? "no stack"} / {expectedRaises}, matrix {stack ?? "no stack"} / {row.GetProperty("raises").GetString()}."); + problems.Add( + $"{member}: documented {expectedStack ?? "no stack"} / {expectedRaises}, matrix {stack ?? "no stack"} / {row.GetProperty("raises").GetString()}."); } } @@ -122,12 +125,16 @@ private static void CheckPolicy(string member, JsonElement policy, JsonElement r string? bridge = Optional(row, "bridgeOperation"); string expectedDecision = policy.GetProperty("allowedDirectly").GetBoolean() ? "DirectAllowed" - : policy.TryGetProperty("conditionalDirectUse", out _) ? "ConditionallyDirect" : "BridgeRequired"; + : policy.TryGetProperty("conditionalDirectUse", out _) + ? "ConditionallyDirect" + : "BridgeRequired"; if (!string.Equals(expectedDecision, decision, StringComparison.Ordinal) || - !string.Equals(Optional(policy, "bridgeOperation"), bridge, StringComparison.Ordinal) || - !string.Equals(policy.GetProperty("nativeSymbol").GetString(), Optional(row, "nativeSymbol"), StringComparison.Ordinal)) + !string.Equals(Optional(policy, "bridgeOperation"), bridge, StringComparison.Ordinal) || + !string.Equals(policy.GetProperty("nativeSymbol").GetString(), Optional(row, "nativeSymbol"), + StringComparison.Ordinal)) { - problems.Add($"{member}: the policy route ({expectedDecision}, {Optional(policy, "bridgeOperation")}) differs from the row ({decision}, {bridge})."); + problems.Add( + $"{member}: the policy route ({expectedDecision}, {Optional(policy, "bridgeOperation")}) differs from the row ({decision}, {bridge})."); } int policyRank = Rank(policy.GetProperty("raises").GetString()!); @@ -135,10 +142,11 @@ private static void CheckPolicy(string member, JsonElement policy, JsonElement r // The policy may only be more conservative than the documented class, and only where the bridge operation // records the source conflict that justifies it (luaL_unref: documented never, implemented with lua_rawseti). bool conflictRecorded = bridge is not null && operations.TryGetValue(bridge, out JsonElement operation) && - operation.TryGetProperty("provenanceConflict", out _); + operation.TryGetProperty("provenanceConflict", out _); if (policyRank != rowRank && !(policyRank > rowRank && conflictRecorded)) { - problems.Add($"{member}: the policy classifies it {policy.GetProperty("raises").GetString()}, the matrix {row.GetProperty("raises").GetString()}."); + problems.Add( + $"{member}: the policy classifies it {policy.GetProperty("raises").GetString()}, the matrix {row.GetProperty("raises").GetString()}."); } } @@ -171,7 +179,7 @@ private static HashSet PublicMembers() // The LUA_* properties are header constants (library names, the signature), not callable primitives. foreach (PropertyInfo property in typeof(LuaApi).GetProperties(Flags) - .Where(static property => !property.Name.StartsWith("LUA_", StringComparison.Ordinal))) + .Where(static property => !property.Name.StartsWith("LUA_", StringComparison.Ordinal))) { members.Add(property.Name); } @@ -208,11 +216,11 @@ private static JsonElement[] Rows() private static JsonDocument Load(string resource) { using Stream stream = typeof(LuaInteropPrimitiveMatrixTests).Assembly.GetManifestResourceStream(resource) - ?? throw new InvalidOperationException($"The embedded resource {resource} is missing."); + ?? throw new InvalidOperationException($"The embedded resource {resource} is missing."); return JsonDocument.Parse(stream); } [GeneratedRegex(@"Stack: (?.*?)\. Raises: (?\w+)", RegexOptions.CultureInvariant, - matchTimeoutMilliseconds: 1000)] + 1000)] private static partial Regex StackAndRaises(); } diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/README.md b/tests/CheatEngine.SDK.Lua.Interop.Tests/README.md index 260e5dc1..3e84fd9b 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/README.md +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/README.md @@ -59,7 +59,8 @@ dotnet test --project tests/CheatEngine.SDK.Lua.Interop.Tests --filter-trait "Ca imports are explicitly cdecl and retain GC transitions (`LuaProtectedApiTests`). Native fixture checks additionally prove that an incomplete export table, negative input count, and input count above Lua's top return the bridge's no-error sentinel without changing the Lua stack (`LuaBridgeContractBoundaryTests`). -- The primitive matrix `tests/CheatEngine.SDK.Repository.Tests/LuaBridge/TestData/lua-interop-primitives.json` has exactly one row per public static `LuaApi` +- The primitive matrix `tests/CheatEngine.SDK.Repository.Tests/LuaBridge/TestData/lua-interop-primitives.json` has + exactly one row per public static `LuaApi` member, its error class and stack effect equal the member's `Raises:` and `Stack:` remarks, its native symbols are exactly the exports the table binds, and the catalogue's direct-call policy agrees with it (`LuaInteropPrimitiveMatrixTests`). diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/RoundTrips/CallTests.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/RoundTrips/CallTests.cs index 20510f5f..567703ed 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/RoundTrips/CallTests.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/RoundTrips/CallTests.cs @@ -189,13 +189,7 @@ public void Load_pulls_the_chunk_through_a_managed_reader() fixed (byte* second = "* 7"u8) fixed (byte* name = "=pieces"u8) { - ReaderState pieces = new() - { - First = first, - FirstSize = 9, - Second = second, - SecondSize = 3 - }; + ReaderState pieces = new() { First = first, FirstSize = 9, Second = second, SecondSize = 3 }; Assert.Equal(LUA_OK, lua_load(L, &ReadPieces, &pieces, name, null)); Assert.Equal(3, pieces.Calls); diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs index 3ec93411..3f31c105 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs @@ -19,7 +19,7 @@ internal static class IlReader public static List<(OpCode Code, int Operand)> Read(MethodBase method) { byte[] il = method.GetMethodBody()?.GetILAsByteArray() ?? - throw new InvalidOperationException(method.Name + " has no IL body."); + throw new InvalidOperationException(method.Name + " has no IL body."); List<(OpCode Code, int Operand)> instructions = []; int offset = 0; diff --git a/tests/CheatEngine.SDK.Lua.Tests/Allocation/ZeroAllocationTests.cs b/tests/CheatEngine.SDK.Lua.Tests/Allocation/ZeroAllocationTests.cs index c96aa5f8..c2325fb5 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Allocation/ZeroAllocationTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Allocation/ZeroAllocationTests.cs @@ -73,13 +73,13 @@ private static long ReadEachScalar(LuaState state, int top) // Exact on purpose: the round trip through the Lua stack must not change a single bit, // so the bit patterns are compared. if (!DoubleMarshaller.TryRead(state, top + 3, out double d) || - BitConverter.DoubleToInt64Bits(d) != BitConverter.DoubleToInt64Bits(2.5)) + BitConverter.DoubleToInt64Bits(d) != BitConverter.DoubleToInt64Bits(2.5)) { Fail(); } if (!SingleMarshaller.TryRead(state, top + 4, out float f) || - BitConverter.SingleToInt32Bits(f) != BitConverter.SingleToInt32Bits(1.5f)) + BitConverter.SingleToInt32Bits(f) != BitConverter.SingleToInt32Bits(1.5f)) { Fail(); } @@ -90,7 +90,7 @@ private static long ReadEachScalar(LuaState state, int top) } if (!AddressMarshaller.TryRead(state, top + 6, out UIntPtr a) || - a != unchecked((nuint) 0xFFFF_FFFF_FFFF_FFF0UL)) + a != unchecked((nuint) 0xFFFF_FFFF_FFFF_FFF0UL)) { Fail(); } diff --git a/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaCallbackTests.cs b/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaCallbackTests.cs index 2eb6a62d..ee8469da 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaCallbackTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaCallbackTests.cs @@ -215,10 +215,7 @@ public void Two_callbacks_of_the_same_thunk_have_independent_state() using NativeLuaState state = new(); LuaState L = LuaTest.View(state); Counter a = new(); - Counter b = new() - { - Value = 100 - }; + Counter b = new() { Value = 100 }; Assert.True(LuaCallback.TryCreate(L, Thunks.Count, a, out LuaCallback? callbackA).IsOk); Assert.True(LuaCallback.TryCreate(L, Thunks.Count, b, out LuaCallback? callbackB).IsOk); Assert.True(callbackA!.TryRegister(L, "countA"u8).IsOk); diff --git a/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaHostSubscriptionTests.cs b/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaHostSubscriptionTests.cs index 1ea1b1f9..9b40b874 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaHostSubscriptionTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaHostSubscriptionTests.cs @@ -434,24 +434,24 @@ public void Dispose() public bool Register() { if (!LuaHostSubscription.TryRegister(state, RunAdmittedCallback, - (registrationState, callback) => - { - HostCallback = callback; - return static _ => - { - }; - }, out LuaHostSubscription? firstSubscription)) + (registrationState, callback) => + { + HostCallback = callback; + return static _ => + { + }; + }, out LuaHostSubscription? firstSubscription)) { return false; } FirstSubscription = firstSubscription; return LuaHostSubscription.TryRegister(state, static () => - { - }, - (registrationState, callback) => releaseState => SecondUnregisters++, - out LuaHostSubscription? secondSubscription) - && (SecondSubscription = secondSubscription) is not null; + { + }, + (registrationState, callback) => releaseState => SecondUnregisters++, + out LuaHostSubscription? secondSubscription) + && (SecondSubscription = secondSubscription) is not null; } private void RunAdmittedCallback() diff --git a/tests/CheatEngine.SDK.Lua.Tests/CompilerServices/LuaCallSupportOptionalTests.cs b/tests/CheatEngine.SDK.Lua.Tests/CompilerServices/LuaCallSupportOptionalTests.cs index 9a0a7b4f..31d34e60 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/CompilerServices/LuaCallSupportOptionalTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/CompilerServices/LuaCallSupportOptionalTests.cs @@ -9,8 +9,10 @@ namespace CheatEngine.SDK.Lua.Tests.CompilerServices; /// /// The generator-facing helpers behind optional arguments, optional results and variadic results -/// (, , -/// ): omitted, nil and a value stay distinct, reads never +/// (, +/// , +/// ): omitted, nil and a value stay distinct, reads +/// never /// change the stack, and a failure is classified by type, never by text. /// [Trait("Category", "NativeLua")] @@ -73,14 +75,16 @@ public void ReadResults_copies_every_value_to_the_top_or_reports_the_needed_capa Span values = stackalloc long[4]; Span small = stackalloc long[2]; - Assert.Equal(LuaOperationStatus.Success, LuaCallSupport.ReadResults(L, 2, values, out int count)); + Assert.Equal(LuaOperationStatus.Success, + LuaCallSupport.ReadResults(L, 2, values, out int count)); Assert.Equal(3, count); Assert.Equal([10L, 20L, 30L], values[..3].ToArray()); Assert.Equal(LuaOperationStatus.ResultCapacityExceeded, LuaCallSupport.ReadResults(L, 2, small, out int needed)); Assert.Equal(3, needed); Assert.Equal([0L, 0L], small.ToArray()); - Assert.Equal(LuaOperationStatus.Success, LuaCallSupport.ReadResults(L, 5, small, out int none)); + Assert.Equal(LuaOperationStatus.Success, + LuaCallSupport.ReadResults(L, 5, small, out int none)); Assert.Equal(0, none); Assert.Throws(() => LuaCallSupport.ReadResults(L, 0, new long[1], out _)); @@ -98,7 +102,8 @@ public void ReadResults_classifies_a_nil_or_wrong_kind_value_and_clears_what_it_ L.PushNil(); Span values = stackalloc long[4]; - Assert.Equal(LuaOperationStatus.NilResult, LuaCallSupport.ReadResults(L, 1, values, out int nilCount)); + Assert.Equal(LuaOperationStatus.NilResult, + LuaCallSupport.ReadResults(L, 1, values, out int nilCount)); Assert.Equal(0, nilCount); Assert.Equal([0L, 0L, 0L, 0L], values.ToArray()); @@ -125,8 +130,8 @@ public void Optional_helpers_allocate_nothing_when_warm() LuaCallSupport.PushOptional(L, LuaOptional.Of(5L)); LuaCallSupport.PushOptional(L, LuaOptional.Of(6L)); if (!LuaCallSupport.TryReadOptional(L, 1, out LuaOptional value) - || !LuaCallSupport.ReadResults(L, 1, buffer, out int count).IsSuccess - || count != 2) + || !LuaCallSupport.ReadResults(L, 1, buffer, out int count).IsSuccess + || count != 2) { throw new InvalidOperationException("wrong read"); } diff --git a/tests/CheatEngine.SDK.Lua.Tests/Generated/MemoryBindings.cs b/tests/CheatEngine.SDK.Lua.Tests/Generated/MemoryBindings.cs index 9bc11a9f..194a1a52 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Generated/MemoryBindings.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Generated/MemoryBindings.cs @@ -49,7 +49,7 @@ private static partial bool TryReadInt32Raw(nuint address, bool signed, out int LuaState L = LuaRuntime.AcquireState(); // one state acquisition per operation int top = L.Top; // explicit settop: no EH region on the success path if (!LuaGlobalFunctions.TryPush(L, s_readInteger, - "readInteger"u8)) // rawgeti on the cached ref; resolve + type-check + luaL_ref on first use + "readInteger"u8)) // rawgeti on the cached ref; resolve + type-check + luaL_ref on first use { return LuaCallSupport.Fail(L, top, out value); // cold, NoInlining: restore top, default the result } diff --git a/tests/CheatEngine.SDK.Lua.Tests/Marshalling/LuaOptionalTests.cs b/tests/CheatEngine.SDK.Lua.Tests/Marshalling/LuaOptionalTests.cs index 327219de..266e23ec 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Marshalling/LuaOptionalTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Marshalling/LuaOptionalTests.cs @@ -78,7 +78,8 @@ public void Value_throws_unless_a_value_is_present() [Fact] public void Equality_distinguishes_the_three_states() { - LuaOptional[] states = [LuaOptional.Omitted(), LuaOptional.Nil(), LuaOptional.Of(0), LuaOptional.Of(1)]; + LuaOptional[] states = + [LuaOptional.Omitted(), LuaOptional.Nil(), LuaOptional.Of(0), LuaOptional.Of(1)]; for (int i = 0; i < states.Length; i++) { diff --git a/tests/CheatEngine.SDK.Lua.Tests/Protected/NativeFailureProcessTests.cs b/tests/CheatEngine.SDK.Lua.Tests/Protected/NativeFailureProcessTests.cs index 89ac3b29..4feb335e 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Protected/NativeFailureProcessTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Protected/NativeFailureProcessTests.cs @@ -127,7 +127,8 @@ public async Task Allocation_failures_return_through_the_native_boundary() } /// - /// Data-driven from libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json: every operation that can raise names its + /// Data-driven from libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json: every operation that + /// can raise names its /// failure evidence, and every probe marker it names is printed by one run of the failure probe. The probe prints a /// marker only after the failure returned a status and the Lua stack was restored, so a missing marker is a /// failure path that no longer recovers. Adding a raising operation without evidence fails here. @@ -149,11 +150,12 @@ public async Task Every_catalogued_raising_operation_reports_its_failure_marker( } Assert.True(operation.TryGetProperty("failureEvidence", out JsonElement evidence) && - evidence.GetArrayLength() > 0, + evidence.GetArrayLength() > 0, $"Protected operation {id} can raise but names no failure evidence."); foreach (JsonElement item in evidence.EnumerateArray()) { - if (string.Equals(item.GetProperty("kind").GetString(), "FailureProbeMarker", StringComparison.Ordinal)) + if (string.Equals(item.GetProperty("kind").GetString(), "FailureProbeMarker", + StringComparison.Ordinal)) { markers.Add(item.GetProperty("marker").GetString()!); } @@ -173,7 +175,8 @@ private static JsonDocument LoadCatalogue() { const string ResourceName = "CheatEngine.SDK.Lua.Tests.ProtectedOperations.json"; using Stream stream = typeof(NativeFailureProcessTests).Assembly.GetManifestResourceStream(ResourceName) - ?? throw new InvalidOperationException($"The embedded resource {ResourceName} is missing."); + ?? throw new InvalidOperationException( + $"The embedded resource {ResourceName} is missing."); return JsonDocument.Parse(stream); } diff --git a/tests/CheatEngine.SDK.Lua.Tests/Runtime/LuaExternalResetDetectionTests.cs b/tests/CheatEngine.SDK.Lua.Tests/Runtime/LuaExternalResetDetectionTests.cs index 656d93b1..0de8eb90 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Runtime/LuaExternalResetDetectionTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Runtime/LuaExternalResetDetectionTests.cs @@ -58,7 +58,8 @@ public void After_an_external_reset_every_admission_path_reports_ExternalStateRe Assert.False(LuaRuntime.TryAcquireOperation(out LuaRuntimeOperation viaTry)); viaTry.Dispose(); - InvalidOperationException thrown = Assert.Throws(() => LuaRuntime.AcquireOperation()); + InvalidOperationException + thrown = Assert.Throws(() => LuaRuntime.AcquireOperation()); Assert.Contains("replaced its Lua state", thrown.Message, StringComparison.Ordinal); Assert.Throws(() => LuaRuntime.AcquireOperation(main)); @@ -220,7 +221,8 @@ public void The_supported_reset_restamps_the_replacement_state_and_is_not_report [Fact] [Trait("Qualification", "Q17")] - public void A_state_replacement_during_a_registration_transaction_leaves_the_lease_stale_and_the_new_state_untouched() + public void + A_state_replacement_during_a_registration_transaction_leaves_the_lease_stale_and_the_new_state_untouched() { LuaTest.RequireNativeLua(); using NativeLuaState state = new(); @@ -228,7 +230,7 @@ public void A_state_replacement_during_a_registration_transaction_leaves_the_lea using RuntimeScope scope = new(state); using NativeLuaState replacement = new(); LuaState replacementView = new(replacement.L); - LuaRegistrationEntry[] entries = [new LuaRegistrationEntry("sdk013_reset_registration", Thunks.Add)]; + LuaRegistrationEntry[] entries = [new("sdk013_reset_registration", Thunks.Add)]; LuaRegistrationResult result = LuaRegistrationSet.Register(main, entries); Assert.True(result.IsSuccess); LuaRegistrationLease lease = result.Lease!; diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/LibraryProbeContractTests.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/LibraryProbeContractTests.cs index 28789c63..1ea12dbe 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/LibraryProbeContractTests.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/LibraryProbeContractTests.cs @@ -40,7 +40,7 @@ public void Refuses_a_CEPlugin_export_read_from_the_bytes_of_a_patched_image() Assert.Contains("CEPlugin_GetVersion", names, StringComparer.Ordinal); Assert.Contains(LibraryProbeContract.FindViolations(names), static violation => violation.Contains("'CEPlugin_GetVersion'", StringComparison.Ordinal) && - violation.Contains("native-plugin entry point", StringComparison.Ordinal)); + violation.Contains("native-plugin entry point", StringComparison.Ordinal)); } [Theory] @@ -89,7 +89,10 @@ public void The_real_bridge_surface_is_refused_as_a_whole() LibraryProbeContract.FindViolations(PortableExecutableExportReader.ReadExportNames(BridgeImage.Load())); Assert.Equal(6, violations.Count); - Assert.Equal(2, violations.Count(static violation => violation.Contains("required fixture export", StringComparison.Ordinal))); - Assert.Equal(4, violations.Count(static violation => violation.Contains("unexpected export", StringComparison.Ordinal))); + Assert.Equal(2, + violations.Count(static violation => + violation.Contains("required fixture export", StringComparison.Ordinal))); + Assert.Equal(4, + violations.Count(static violation => violation.Contains("unexpected export", StringComparison.Ordinal))); } } diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/NativeAotLibraryProbeExportSurfaceTests.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/NativeAotLibraryProbeExportSurfaceTests.cs index b3a2f3b9..b9af912f 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/NativeAotLibraryProbeExportSurfaceTests.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/NativeAotLibraryProbeExportSurfaceTests.cs @@ -26,9 +26,11 @@ .. typeof(NativeAotLibraryProbeExports) .Order(StringComparer.Ordinal) ]; - Assert.Equal(NativeAotLibraryProbeExportNames.Required.Order(StringComparer.Ordinal), entryPoints, StringComparer.Ordinal); + Assert.Equal(NativeAotLibraryProbeExportNames.Required.Order(StringComparer.Ordinal), entryPoints, + StringComparer.Ordinal); Assert.DoesNotContain(entryPoints, static name => name.StartsWith(LibraryProbeContract.NativePluginPrefix, StringComparison.Ordinal)); - Assert.Empty(LibraryProbeContract.FindViolations([.. entryPoints, .. LibraryProbeContract.AllowedRuntimeExports])); + Assert.Empty( + LibraryProbeContract.FindViolations([.. entryPoints, .. LibraryProbeContract.AllowedRuntimeExports])); } } diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/PortableExecutableExportReaderTests.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/PortableExecutableExportReaderTests.cs index b08fb98d..f79516f3 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/PortableExecutableExportReaderTests.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/PortableExecutableExportReaderTests.cs @@ -1,3 +1,5 @@ +using System.Text; + using CheatEngine.SDK.NativeAotLoaderHarness.Tests.Support; namespace CheatEngine.SDK.NativeAotLoaderHarness.Tests; @@ -68,7 +70,7 @@ public void Refuses_truncated_bytes(int length) public void Refuses_an_image_truncated_inside_an_export_name() { byte[] full = BridgeImage.Load(); - int firstName = full.AsSpan().IndexOf(System.Text.Encoding.ASCII.GetBytes(BridgeImage.ExportNames[0] + "\0")); + int firstName = full.AsSpan().IndexOf(Encoding.ASCII.GetBytes(BridgeImage.ExportNames[0] + "\0")); Assert.True(firstName > 0); byte[] image = full[..(firstName + 3)]; diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/README.md b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/README.md index e1e8bfe6..02b906db 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/README.md +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/README.md @@ -34,8 +34,7 @@ win-x64, Release) exports exactly the two probe names and `DotNetRuntimeDebugHea - The reader returns the bridge's four export names and refuses a non-AMD64 image, an image without an export directory and truncated bytes (`PortableExecutableExportReaderTests`). - The contract refuses a `CEPlugin_*` export, including one read from patched bytes, a missing probe export and any - unexpected export, and accepts exactly the probe names plus the measured runtime export - (`LibraryProbeContractTests`). + unexpected export, and accepts exactly the probe names plus the measured runtime export (`LibraryProbeContractTests`). - The probe source declares exactly the two required entry points and no `CEPlugin_*` name (`NativeAotLibraryProbeExportSurfaceTests`). diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/Support/BridgeImage.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/Support/BridgeImage.cs index a32a384f..202ec915 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/Support/BridgeImage.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/Support/BridgeImage.cs @@ -32,7 +32,8 @@ public static IReadOnlyList ExportNames public static byte[] Load() { using Stream stream = typeof(BridgeImage).Assembly.GetManifestResourceStream(ResourceName) - ?? throw new InvalidOperationException($"The embedded resource {ResourceName} is missing."); + ?? throw new InvalidOperationException( + $"The embedded resource {ResourceName} is missing."); using MemoryStream copy = new(); stream.CopyTo(copy); return copy.ToArray(); diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness/LibraryProbeContract.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness/LibraryProbeContract.cs index 11f91a64..1b2e7500 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness/LibraryProbeContract.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness/LibraryProbeContract.cs @@ -54,8 +54,8 @@ internal static IReadOnlyList FindViolations(IReadOnlyList expor foreach (string exportName in exportNames) { if (!exportName.StartsWith(NativePluginPrefix, StringComparison.Ordinal) && - !Contains(NativeAotLibraryProbeExportNames.Required, exportName) && - !Contains(AllowedRuntimeExports, exportName)) + !Contains(NativeAotLibraryProbeExportNames.Required, exportName) && + !Contains(AllowedRuntimeExports, exportName)) { violations.Add($"The file exposes the unexpected export '{exportName}'."); } diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness/Program.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness/Program.cs index 8af8d9b7..47630394 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness/Program.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness/Program.cs @@ -45,7 +45,7 @@ private static int Run(string[] arguments) } if (arguments.Length == 2 && string.Equals(arguments[0], LoadMode, StringComparison.Ordinal) && - string.Equals(arguments[1], AcknowledgeProcessResidentLoad, StringComparison.Ordinal)) + string.Equals(arguments[1], AcknowledgeProcessResidentLoad, StringComparison.Ordinal)) { LoadAndQueryNames(); return 0; @@ -154,7 +154,10 @@ private static LibraryInspection ReadAndValidateProbe(string libraryPath) return new LibraryInspection(fullPath, sha256, LibraryProbeContract.RuntimeExportsIn(exportNames), fileLock); } - private sealed class LibraryInspection(string path, string sha256, IReadOnlyList runtimeExports, + private sealed class LibraryInspection( + string path, + string sha256, + IReadOnlyList runtimeExports, FileStream fileLock) : IDisposable { public string Path diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness/README.md b/tests/CheatEngine.SDK.NativeAotLoaderHarness/README.md index 61930236..214da015 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness/README.md +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness/README.md @@ -29,7 +29,8 @@ The harness has exactly two modes: Both modes first require the exact export surface of `LibraryProbeContract`: no `CEPlugin_` export (a classic Cheat Engine plugin entry point), both probe exports, and nothing else except the NativeAOT runtime's own -`DotNetRuntimeDebugHeader`, the one extra export a local `dotnet publish` of the probe produced. Any drift exits non-zero +`DotNetRuntimeDebugHeader`, the one extra export a local `dotnet publish` of the probe produced. Any drift exits +non-zero with `harness.error=` naming every violation; a conforming file prints `export.runtime.*`, `export.unexpected=none` and `contract=passed`. The load mode therefore refuses any file that has a `CEPlugin_` export, and it cannot be pointed at an arbitrary path or a production plugin: Windows loader initialization can run while a DLL is mapped, even when no @@ -40,8 +41,8 @@ export is invoked. ## Promise -- The contract and the PE reader are unit-tested without publishing anything - ([`tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests`](../CheatEngine.SDK.NativeAotLoaderHarness.Tests/README.md), +- The contract and the PE reader are unit-tested without publishing anything ([ + `tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests`](../CheatEngine.SDK.NativeAotLoaderHarness.Tests/README.md), Q41 at level C0): a `CEPlugin_*` export, a missing probe export and any unexpected export are refused. - The CI `aot` job's publish and harness transcript are the C2 evidence of Q41, recorded only after a green run. diff --git a/tests/CheatEngine.SDK.QualificationTarget/ImageScanner.cs b/tests/CheatEngine.SDK.QualificationTarget/ImageScanner.cs index 93c2a56c..d31579b1 100644 --- a/tests/CheatEngine.SDK.QualificationTarget/ImageScanner.cs +++ b/tests/CheatEngine.SDK.QualificationTarget/ImageScanner.cs @@ -16,7 +16,7 @@ internal static (nint Base, int Size) MainImage() { using Process process = Process.GetCurrentProcess(); ProcessModule module = process.MainModule - ?? throw new InvalidOperationException("The main module is not available."); + ?? throw new InvalidOperationException("The main module is not available."); return (module.BaseAddress, module.ModuleMemorySize); } diff --git a/tests/CheatEngine.SDK.QualificationTarget/Program.cs b/tests/CheatEngine.SDK.QualificationTarget/Program.cs index 33cd9243..df188a5d 100644 --- a/tests/CheatEngine.SDK.QualificationTarget/Program.cs +++ b/tests/CheatEngine.SDK.QualificationTarget/Program.cs @@ -82,7 +82,7 @@ private static bool TryParse(string[] args, out int heapCopies, out int repetiti break; default: error = "Invalid argument '" + args[index] + - "'. Use --heap-copies 1-1024, --repetitions 1-1000000 and --ready-file PATH."; + "'. Use --heap-copies 1-1024, --repetitions 1-1000000 and --ready-file PATH."; return false; } } @@ -93,6 +93,6 @@ private static bool TryParse(string[] args, out int heapCopies, out int repetiti private static bool TryRange(string? text, int minimum, int maximum, out int value) { return int.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out value) && value >= minimum && - value <= maximum; + value <= maximum; } } diff --git a/tests/CheatEngine.SDK.QualificationTarget/README.md b/tests/CheatEngine.SDK.QualificationTarget/README.md index e6f3620c..d588526e 100644 --- a/tests/CheatEngine.SDK.QualificationTarget/README.md +++ b/tests/CheatEngine.SDK.QualificationTarget/README.md @@ -20,13 +20,13 @@ x86 .NET 6), so the target is published with Native AOT, which supports win-x86 ## How it works -| File | Content | -|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| File | Content | +|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `TargetLayout.cs` | The 16-byte module-resident marker (constant data of the image), the 8-byte many-results pattern (computed at run time, so it is not in the image), the initial values. | -| `TargetMemory.cs` | Pinned heap arrays: N marker copies 64 bytes apart, M back-to-back repetitions of the second pattern, and the Int32/Int64 cells. | -| `ImageScanner.cs` | Counts a pattern in every readable section of the executable image, or in a heap region. | -| `ReadyRecord.cs` | The one-line JSON records, written with `Utf8JsonWriter` (no reflection, trim-safe). | -| `Program.cs` | Arguments, the ready record, and the `step` / `exit` command loop on standard input. | +| `TargetMemory.cs` | Pinned heap arrays: N marker copies 64 bytes apart, M back-to-back repetitions of the second pattern, and the Int32/Int64 cells. | +| `ImageScanner.cs` | Counts a pattern in every readable section of the executable image, or in a heap region. | +| `ReadyRecord.cs` | The one-line JSON records, written with `Utf8JsonWriter` (no reflection, trim-safe). | +| `Program.cs` | Arguments, the ready record, and the `step` / `exit` command loop on standard input. | On start the target prints one line and waits for commands: @@ -44,20 +44,21 @@ compiler may emit a constant more than once, which is why the count is measured measured over their regions. Patterns that must be absent are chosen by the qualification driver, never stored in the target. -| Input | Effect | -|------------------------------|-----------------------------------------------------------------------------------------| -| `--heap-copies N` | Number of heap marker copies, 1–1024 (default 8). | -| `--repetitions M` | Number of many-results repetitions, 1–1000000 (default 20000). | -| `--ready-file PATH` | Also writes the ready record to PATH; the only file the target ever writes. | -| `step` on standard input | Adds one to both value cells and prints `{"event":"step","int32":…,"int64":…}`. | -| `exit` or end of input | Exits with code 0. | +| Input | Effect | +|--------------------------|---------------------------------------------------------------------------------| +| `--heap-copies N` | Number of heap marker copies, 1–1024 (default 8). | +| `--repetitions M` | Number of many-results repetitions, 1–1000000 (default 20000). | +| `--ready-file PATH` | Also writes the ready record to PATH; the only file the target ever writes. | +| `step` on standard input | Adds one to both value cells and prints `{"event":"step","int32":…,"int64":…}`. | +| `exit` or end of input | Exits with code 0. | The target opens no network connection, requests no elevation, reads no file and loads no SDK assembly. ## Promise - The target is in the solution, publishes with Native AOT for `win-x64` and `win-x86`, is not a test module and never - packs (`QualificationHarnessShapeTests.QualificationTarget_is_in_the_solution_and_publishes_native_aot_for_x64_and_x86`, + packs + (`QualificationHarnessShapeTests.QualificationTarget_is_in_the_solution_and_publishes_native_aot_for_x64_and_x86`, `QualificationHarnessShapeTests.Qualification_harnesses_are_not_test_modules_and_never_pack`). - It references no SDK project, so a qualification observes the SDK only from the plugin side (`QualificationHarnessShapeTests.QualificationTarget_references_no_SDK_project`). diff --git a/tests/CheatEngine.SDK.QualificationTarget/ReadyRecord.cs b/tests/CheatEngine.SDK.QualificationTarget/ReadyRecord.cs index c50ffe1b..ef049d44 100644 --- a/tests/CheatEngine.SDK.QualificationTarget/ReadyRecord.cs +++ b/tests/CheatEngine.SDK.QualificationTarget/ReadyRecord.cs @@ -30,7 +30,8 @@ internal static string Create(TargetMemory memory, nint imageBase, int imageSize Region(writer, "heap-marker", memory.HeapMarkersAddress, memory.HeapMarkers.Length, marker, ImageScanner.Count(memory.HeapMarkers, TargetLayout.Marker)); Region(writer, "many-results", memory.RepeatedAddress, memory.Repeated.Length, - TargetLayout.ToPattern(memory.RepeatedPattern), ImageScanner.Count(memory.Repeated, memory.RepeatedPattern)); + TargetLayout.ToPattern(memory.RepeatedPattern), + ImageScanner.Count(memory.Repeated, memory.RepeatedPattern)); writer.WriteEndArray(); writer.WriteStartArray("values"); Value(writer, "int32", memory.Int32Address, memory.Int32); diff --git a/tests/CheatEngine.SDK.QualificationTarget/TargetLayout.cs b/tests/CheatEngine.SDK.QualificationTarget/TargetLayout.cs index 530e7c5d..acc9bcd9 100644 --- a/tests/CheatEngine.SDK.QualificationTarget/TargetLayout.cs +++ b/tests/CheatEngine.SDK.QualificationTarget/TargetLayout.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Text; namespace QualificationTarget; @@ -55,7 +56,7 @@ internal static string ToPattern(ReadOnlySpan bytes) builder.Append(' '); } - builder.Append(value.ToString("X2", System.Globalization.CultureInfo.InvariantCulture)); + builder.Append(value.ToString("X2", CultureInfo.InvariantCulture)); } return builder.ToString(); diff --git a/tests/CheatEngine.SDK.QualificationTarget/TargetMemory.cs b/tests/CheatEngine.SDK.QualificationTarget/TargetMemory.cs index b7958f02..f8fff6de 100644 --- a/tests/CheatEngine.SDK.QualificationTarget/TargetMemory.cs +++ b/tests/CheatEngine.SDK.QualificationTarget/TargetMemory.cs @@ -19,20 +19,20 @@ internal TargetMemory(int heapCopies, int repetitions) Repetitions = repetitions; RepeatedPattern = TargetLayout.CreateRepeatedPattern(); - _heapMarkers = GC.AllocateArray(heapCopies * TargetLayout.HeapCopyStride, pinned: true); + _heapMarkers = GC.AllocateArray(heapCopies * TargetLayout.HeapCopyStride, true); for (int copy = 0; copy < heapCopies; copy++) { TargetLayout.Marker.CopyTo(_heapMarkers.AsSpan(copy * TargetLayout.HeapCopyStride)); } - _repeated = GC.AllocateArray(repetitions * TargetLayout.RepeatedPatternLength, pinned: true); + _repeated = GC.AllocateArray(repetitions * TargetLayout.RepeatedPatternLength, true); for (int repetition = 0; repetition < repetitions; repetition++) { RepeatedPattern.CopyTo(_repeated.AsSpan(repetition * TargetLayout.RepeatedPatternLength)); } // Slot 0 holds the Int32 cell in its low four bytes, slot 1 the Int64 cell; both stay naturally aligned. - _values = GC.AllocateArray(2, pinned: true); + _values = GC.AllocateArray(2, true); Int32 = TargetLayout.InitialInt32; Int64 = TargetLayout.InitialInt64; } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Abi/AbiRouteSeparationTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Abi/AbiRouteSeparationTests.cs index 11e06d4a..ab8eb00f 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Abi/AbiRouteSeparationTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Abi/AbiRouteSeparationTests.cs @@ -34,12 +34,14 @@ public void Managed_exports_are_never_converted_to_the_classic_prefix() { if (Identifier(Managed).IsMatch(code) && Identifier(Prefix).IsMatch(code)) { - problems.Add($"{file} names both {Managed} and {Prefix}: the managed and classic tables are separate routes."); + problems.Add( + $"{file} names both {Managed} and {Prefix}: the managed and classic tables are separate routes."); } foreach (Match cast in PrefixPointerCast().Matches(code)) { - problems.Add($"{file}:{CSharpCode.LineOf(code, cast.Index)} casts to {Prefix}*; read the prefix with ClassicExportedFunctionsPrefixReader."); + problems.Add( + $"{file}:{CSharpCode.LineOf(code, cast.Index)} casts to {Prefix}*; read the prefix with ClassicExportedFunctionsPrefixReader."); } } @@ -56,19 +58,22 @@ .. ProductionCode().Where(static source => Identifier(Prefix).IsMatch(source.Cod ]; Assert.All(consumers, file => Assert.Contains(file, PrefixConsumers, StringComparer.Ordinal)); - Assert.Contains("libs/CheatEngine.SDK.Abi/Native/ClassicDebugEventDispatcher.cs", consumers, StringComparer.Ordinal); + Assert.Contains("libs/CheatEngine.SDK.Abi/Native/ClassicDebugEventDispatcher.cs", consumers, + StringComparer.Ordinal); Assert.All(PrefixConsumers, file => Assert.True(RepositoryDocument.Exists(file), $"{file} no longer exists.")); - Assert.DoesNotContain(consumers, static file => file.StartsWith("libs/CheatEngine.SDK.Hosting/", StringComparison.Ordinal)); + Assert.DoesNotContain(consumers, + static file => file.StartsWith("libs/CheatEngine.SDK.Hosting/", StringComparison.Ordinal)); } [Fact] public void The_rules_see_code_and_ignore_comments_and_strings() { const string Documented = """ - /// Unlike ManagedExportedFunctions, the ExportedFunctionsPrefix is classic. - class C { string s = "ExportedFunctionsPrefix*"; } - """; - const string Converting = "unsafe class C { void M(ManagedExportedFunctions* m) { var p = (ExportedFunctionsPrefix*) m; } }"; + /// Unlike ManagedExportedFunctions, the ExportedFunctionsPrefix is classic. + class C { string s = "ExportedFunctionsPrefix*"; } + """; + const string Converting = + "unsafe class C { void M(ManagedExportedFunctions* m) { var p = (ExportedFunctionsPrefix*) m; } }"; string documented = CSharpCode.BlankCommentsAndLiterals(Documented); string converting = CSharpCode.BlankCommentsAndLiterals(Converting); @@ -92,13 +97,13 @@ private static Regex Identifier(string name) return string.Equals(name, Managed, StringComparison.Ordinal) ? ManagedIdentifier() : PrefixIdentifier(); } - [GeneratedRegex(@"\bManagedExportedFunctions\b", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"\bManagedExportedFunctions\b", RegexOptions.CultureInvariant, 1000)] private static partial Regex ManagedIdentifier(); - [GeneratedRegex(@"\bExportedFunctionsPrefix\b", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"\bExportedFunctionsPrefix\b", RegexOptions.CultureInvariant, 1000)] private static partial Regex PrefixIdentifier(); [GeneratedRegex(@"\(\s*(?:[\w.]+\.)?ExportedFunctionsPrefix\s*\*\s*\)", RegexOptions.CultureInvariant, - matchTimeoutMilliseconds: 1000)] + 1000)] private static partial Regex PrefixPointerCast(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryContract.cs b/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryContract.cs index 7b7a5a91..9bc9c628 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryContract.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryContract.cs @@ -7,7 +7,9 @@ namespace CheatEngine.SDK.Repository.Tests.Abi; /// internal static class ClassicSlotRegistryContract { - internal const string RegistryPath = "tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json"; + internal const string RegistryPath = + "tests/CheatEngine.SDK.Repository.Tests/Abi/TestData/classic-slot-registry.json"; + internal const string Kind = "cheatengine-classic-slot-registry/v0"; internal const string UpstreamCommit = "ec45d5f47f92a239ba0bf51ec5d04a7509c3fd37"; internal const string QualifiableProfile = "ce-7.7.0.10621-x64-managed-hostfxr"; @@ -21,14 +23,16 @@ internal static class ClassicSlotRegistryContract internal static readonly string[] ContractRequired = [ - "pluginContractVersion", "hostTableType", "fieldCount", "pointerFieldCount", "x64TableSize", "sdkDirectPrefixSize", + "pluginContractVersion", "hostTableType", "fieldCount", "pointerFieldCount", "x64TableSize", + "sdkDirectPrefixSize", "sdkPrefixSlots" ]; internal static readonly string[] SlotRequired = [ "slot", "x64Offset", "width", "minDeclaredSize", "section", "hostField", "hostAssignment", "hostImplementation", - "nature", "indirection", "callingConvention", "nullability", "mirrors", "divergenceRefs", "sdkExposure", "sdkField", + "nature", "indirection", "callingConvention", "nullability", "mirrors", "divergenceRefs", "sdkExposure", + "sdkField", "facadeStatus", "ownership", "luaEquivalent", "catalogSurfaceId", "evidenceKind", "layoutEvidenceKind", "hostProfileStatus", "qualification" ]; @@ -41,11 +45,13 @@ internal static class ClassicSlotRegistryContract internal static readonly string[] CallbackCategoryRequired = [ - "pluginType", "name", "hostForm", "headerForm", "additionalForms", "versionVariants", "versionDependent", "context", + "pluginType", "name", "hostForm", "headerForm", "additionalForms", "versionVariants", "versionDependent", + "context", "synchronousDecision", "sdkRecord", "sdkCallbackTyped", "shapeTest", "note", "evidenceKind" ]; - internal static readonly string[] SourceIds = ["plugin-pas", "pluginexports-pas", "cepluginsdk-h", "cepluginsdk-pas"]; + internal static readonly string[] SourceIds = + ["plugin-pas", "pluginexports-pas", "cepluginsdk-h", "cepluginsdk-pas"]; internal static readonly string[] SourceRoles = ["Authority", "HostImplementation", "MirrorC", "MirrorPascal"]; @@ -53,7 +59,8 @@ internal static class ClassicSlotRegistryContract internal static readonly string[] Sections = ["Base", "V2", "V3", "V4", "V5"]; - internal static readonly string[] AssignmentKinds = ["Size", "FunctionAddress", "CellAddress", "VariableAddress", "Nil"]; + internal static readonly string[] AssignmentKinds = + ["Size", "FunctionAddress", "CellAddress", "VariableAddress", "Nil"]; internal static readonly string[] Natures = ["Int32", "Function", "FunctionPointerCell", "DataCell", "ObjectRefCell", "Unknown"]; diff --git a/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryDocumentTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryDocumentTests.cs index a1ca643d..ca3eca61 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryDocumentTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryDocumentTests.cs @@ -26,7 +26,8 @@ public sealed partial class ClassicSlotRegistryDocumentTests .. Enumerable.Range(18, 10), .. Enumerable.Range(30, 6), .. Enumerable.Range(73, 9) ]; - private static readonly string[] AuditDivergences = ["D01", "D02", "D03", "D04", "D05", "D06", "D07", "D08", "D09", "D10"]; + private static readonly string[] AuditDivergences = + ["D01", "D02", "D03", "D04", "D05", "D06", "D07", "D08", "D09", "D10"]; private static JsonElement Registry => RepositoryDocument.LoadJson(ClassicSlotRegistryContract.RegistryPath); @@ -41,7 +42,8 @@ public void Registry_top_level_and_nested_objects_have_the_expected_required_pro AssertProperties(ClassicSlotRegistryContract.ContractRequired, root.GetProperty("contract")); AssertProperties(ClassicSlotRegistryContract.SlotRequired, Slots[0]); AssertProperties(ClassicSlotRegistryContract.DivergenceRequired, root.GetProperty("divergences")[0]); - AssertProperties(ClassicSlotRegistryContract.CallbackCategoryRequired, root.GetProperty("callbackCategories")[0]); + AssertProperties(ClassicSlotRegistryContract.CallbackCategoryRequired, + root.GetProperty("callbackCategories")[0]); Assert.All(root.GetProperty("sources").EnumerateArray(), source => AssertProperties(ClassicSlotRegistryContract.SourceRequired, source)); @@ -53,18 +55,28 @@ public void Registry_top_level_and_nested_objects_have_the_expected_required_pro Assert.Equal(ClassicSlotRegistryContract.Kind, root.GetProperty("schema").GetString()); Assert.All(root.GetProperty("sources").EnumerateArray(), source => - Assert.Contains(source.GetProperty("role").GetString(), ClassicSlotRegistryContract.SourceRoles, StringComparer.Ordinal)); + Assert.Contains(source.GetProperty("role").GetString(), ClassicSlotRegistryContract.SourceRoles, + StringComparer.Ordinal)); Assert.All(Slots, slot => { - Assert.Contains(slot.GetProperty("section").GetString(), ClassicSlotRegistryContract.Sections, StringComparer.Ordinal); - Assert.Contains(slot.GetProperty("hostAssignment").GetProperty("kind").GetString(), ClassicSlotRegistryContract.AssignmentKinds, StringComparer.Ordinal); - Assert.Contains(slot.GetProperty("nature").GetString(), ClassicSlotRegistryContract.Natures, StringComparer.Ordinal); - Assert.Contains(slot.GetProperty("callingConvention").GetString(), ClassicSlotRegistryContract.CallingConventions, StringComparer.Ordinal); - Assert.Contains(slot.GetProperty("nullability").GetString(), ClassicSlotRegistryContract.Nullabilities, StringComparer.Ordinal); - Assert.Contains(slot.GetProperty("sdkExposure").GetString(), ClassicSlotRegistryContract.SdkExposures, StringComparer.Ordinal); - Assert.Contains(slot.GetProperty("facadeStatus").GetString(), ClassicSlotRegistryContract.FacadeStatuses, StringComparer.Ordinal); - Assert.Contains(slot.GetProperty("ownership").GetString(), ClassicSlotRegistryContract.Ownerships, StringComparer.Ordinal); - Assert.Contains(slot.GetProperty("evidenceKind").GetString(), ClassicSlotRegistryContract.SlotEvidenceKinds, StringComparer.Ordinal); + Assert.Contains(slot.GetProperty("section").GetString(), ClassicSlotRegistryContract.Sections, + StringComparer.Ordinal); + Assert.Contains(slot.GetProperty("hostAssignment").GetProperty("kind").GetString(), + ClassicSlotRegistryContract.AssignmentKinds, StringComparer.Ordinal); + Assert.Contains(slot.GetProperty("nature").GetString(), ClassicSlotRegistryContract.Natures, + StringComparer.Ordinal); + Assert.Contains(slot.GetProperty("callingConvention").GetString(), + ClassicSlotRegistryContract.CallingConventions, StringComparer.Ordinal); + Assert.Contains(slot.GetProperty("nullability").GetString(), ClassicSlotRegistryContract.Nullabilities, + StringComparer.Ordinal); + Assert.Contains(slot.GetProperty("sdkExposure").GetString(), ClassicSlotRegistryContract.SdkExposures, + StringComparer.Ordinal); + Assert.Contains(slot.GetProperty("facadeStatus").GetString(), ClassicSlotRegistryContract.FacadeStatuses, + StringComparer.Ordinal); + Assert.Contains(slot.GetProperty("ownership").GetString(), ClassicSlotRegistryContract.Ownerships, + StringComparer.Ordinal); + Assert.Contains(slot.GetProperty("evidenceKind").GetString(), ClassicSlotRegistryContract.SlotEvidenceKinds, + StringComparer.Ordinal); }); } @@ -139,11 +151,14 @@ public void Sections_have_the_audit_slot_ranges() public void Nil_assigned_slots_are_exactly_the_eleven_host_nil_assignments() { int[] nil = SlotsWhere(static slot => IsKind(slot, "Nil")); - int[] nilAssigned = SlotsWhere(static slot => string.Equals(slot.GetProperty("nullability").GetString(), "NilAssigned", StringComparison.Ordinal)); + int[] nilAssigned = SlotsWhere(static slot => + string.Equals(slot.GetProperty("nullability").GetString(), "NilAssigned", StringComparison.Ordinal)); Assert.Equal(NilSlots, nil); Assert.Equal(NilSlots, nilAssigned); - Assert.All(nil, static index => Assert.Equal("nil", Slots[index].GetProperty("hostAssignment").GetProperty("expression").GetString())); + Assert.All(nil, + static index => Assert.Equal("nil", + Slots[index].GetProperty("hostAssignment").GetProperty("expression").GetString())); Assert.Equal("fixmem", HostName(Slots[14])); } @@ -152,8 +167,10 @@ public void Cell_slots_are_the_twenty_five_double_address_assignments() { int[] cells = SlotsWhere(static slot => IsKind(slot, "CellAddress")); int[] doubleAddress = SlotsWhere(static slot => - slot.GetProperty("hostAssignment").GetProperty("expression").GetString()!.StartsWith("@@", StringComparison.Ordinal)); - int[] functionPointerCells = SlotsWhere(static slot => string.Equals(slot.GetProperty("nature").GetString(), "FunctionPointerCell", StringComparison.Ordinal)); + slot.GetProperty("hostAssignment").GetProperty("expression").GetString()!.StartsWith("@@", + StringComparison.Ordinal)); + int[] functionPointerCells = SlotsWhere(static slot => string.Equals(slot.GetProperty("nature").GetString(), + "FunctionPointerCell", StringComparison.Ordinal)); Assert.Equal(25, cells.Length); Assert.Equal(CellSlots, cells); @@ -170,8 +187,12 @@ public void Cell_slots_are_the_twenty_five_double_address_assignments() [Fact] public void Data_and_object_reference_cells_have_their_declared_nature() { - Assert.Equal([4, 5], SlotsWhere(static slot => string.Equals(slot.GetProperty("nature").GetString(), "DataCell", StringComparison.Ordinal))); - Assert.Equal([82, 83], SlotsWhere(static slot => string.Equals(slot.GetProperty("nature").GetString(), "ObjectRefCell", StringComparison.Ordinal))); + Assert.Equal([4, 5], + SlotsWhere(static slot => + string.Equals(slot.GetProperty("nature").GetString(), "DataCell", StringComparison.Ordinal))); + Assert.Equal([82, 83], + SlotsWhere(static slot => + string.Equals(slot.GetProperty("nature").GetString(), "ObjectRefCell", StringComparison.Ordinal))); int[] cells = [4, 5, 82, 83]; foreach (int index in cells) { @@ -197,8 +218,12 @@ public void Data_and_object_reference_cells_have_their_declared_nature() public void Divergence_register_lists_the_ten_audit_divergences() { JsonElement[] divergences = [.. Registry.GetProperty("divergences").EnumerateArray()]; - string[] audit = [.. divergences.Where(static row => string.Equals(row.GetProperty("origin").GetString(), "Audit", StringComparison.Ordinal)) - .Select(static row => row.GetProperty("id").GetString()!)]; + string[] audit = + [ + .. divergences.Where(static row => + string.Equals(row.GetProperty("origin").GetString(), "Audit", StringComparison.Ordinal)) + .Select(static row => row.GetProperty("id").GetString()!) + ]; Assert.Equal(AuditDivergences, audit); Assert.Equal([17], Ints(Divergence(divergences, "D01"), "slots")); @@ -213,7 +238,8 @@ public void Divergence_register_lists_the_ten_audit_divergences() Assert.Contains("PluginInitRecord", Strings(Divergence(divergences, "D10"), "records"), StringComparer.Ordinal); // Lot observations are extra rows, never replacements: each is a source observation of the pinned source. - foreach (JsonElement row in divergences.Where(static row => string.Equals(row.GetProperty("origin").GetString(), "LotObservation", StringComparison.Ordinal))) + foreach (JsonElement row in divergences.Where(static row => + string.Equals(row.GetProperty("origin").GetString(), "LotObservation", StringComparison.Ordinal))) { Assert.Equal("ObservedSource", row.GetProperty("evidenceKind").GetString()); } @@ -232,20 +258,26 @@ public void Divergence_references_resolve_in_both_directions() foreach (JsonElement slot in Slots) { int index = slot.GetProperty("slot").GetInt32(); - string[] refs = [.. slot.GetProperty("divergenceRefs").EnumerateArray().Select(static id => id.GetString()!)]; + string[] refs = + [.. slot.GetProperty("divergenceRefs").EnumerateArray().Select(static id => id.GetString()!)]; foreach (string id in refs) { - Assert.True(slotsById.TryGetValue(id, out int[]? listed), $"Slot {index} cites the unknown divergence {id}."); + Assert.True(slotsById.TryGetValue(id, out int[]? listed), + $"Slot {index} cites the unknown divergence {id}."); Assert.Contains(index, listed); } - string[] expected = [.. slotsById.Where(pair => pair.Value.Contains(index)).Select(static pair => pair.Key).Order(StringComparer.Ordinal)]; + string[] expected = + [ + .. slotsById.Where(pair => pair.Value.Contains(index)).Select(static pair => pair.Key) + .Order(StringComparer.Ordinal) + ]; Assert.Equal(expected, refs.Order(StringComparer.Ordinal), StringComparer.Ordinal); } // D12: every slot of the cell section that the host assigns a direct @ expression (not @@, not nil). int[] direct = SlotsWhere(static slot => slot.GetProperty("slot").GetInt32() is >= 18 and <= 81 && - IsKind(slot, "FunctionAddress")); + IsKind(slot, "FunctionAddress")); Assert.Equal(direct, slotsById["D12"]); } @@ -255,18 +287,23 @@ public void Every_divergent_or_nil_slot_is_never_prefix_typed() foreach (JsonElement slot in Slots) { bool divergent = slot.GetProperty("divergenceRefs").GetArrayLength() > 0; - bool nil = string.Equals(slot.GetProperty("nullability").GetString(), "NilAssigned", StringComparison.Ordinal); + bool nil = string.Equals(slot.GetProperty("nullability").GetString(), "NilAssigned", + StringComparison.Ordinal); if (divergent || nil) { Assert.NotEqual("PrefixTyped", slot.GetProperty("sdkExposure").GetString(), StringComparer.Ordinal); } } - Assert.Equal([14, 17], SlotsWhere(static slot => string.Equals(slot.GetProperty("sdkExposure").GetString(), "PrefixOpaque", StringComparison.Ordinal))); + Assert.Equal([14, 17], + SlotsWhere(static slot => string.Equals(slot.GetProperty("sdkExposure").GetString(), "PrefixOpaque", + StringComparison.Ordinal))); Assert.Equal([.. Enumerable.Range(0, 18).Except([14, 17])], - SlotsWhere(static slot => string.Equals(slot.GetProperty("sdkExposure").GetString(), "PrefixTyped", StringComparison.Ordinal))); + SlotsWhere(static slot => string.Equals(slot.GetProperty("sdkExposure").GetString(), "PrefixTyped", + StringComparison.Ordinal))); Assert.Equal([.. Enumerable.Range(18, 141)], - SlotsWhere(static slot => string.Equals(slot.GetProperty("sdkExposure").GetString(), "None", StringComparison.Ordinal))); + SlotsWhere(static slot => + string.Equals(slot.GetProperty("sdkExposure").GetString(), "None", StringComparison.Ordinal))); Assert.All(Slots[18..], static slot => { Assert.Equal("Deferred", slot.GetProperty("facadeStatus").GetString()); @@ -279,9 +316,12 @@ public void Authority_is_plugin_pas_and_mirrors_carry_their_hashes() { JsonElement[] sources = [.. Registry.GetProperty("sources").EnumerateArray()]; - Assert.Equal(ClassicSlotRegistryContract.SourceIds, sources.Select(static source => source.GetProperty("id").GetString()!), + Assert.Equal(ClassicSlotRegistryContract.SourceIds, + sources.Select(static source => source.GetProperty("id").GetString()!), StringComparer.Ordinal); - JsonElement authority = Assert.Single(sources, static source => string.Equals(source.GetProperty("role").GetString(), "Authority", StringComparison.Ordinal)); + JsonElement authority = Assert.Single(sources, + static source => string.Equals(source.GetProperty("role").GetString(), "Authority", + StringComparison.Ordinal)); Assert.Equal("Cheat Engine/plugin.pas", authority.GetProperty("path").GetString()); foreach (JsonElement source in sources) { @@ -293,7 +333,8 @@ public void Authority_is_plugin_pas_and_mirrors_carry_their_hashes() JsonElement header = sources[2].GetProperty("installed"); Assert.Equal("MirrorC", sources[2].GetProperty("role").GetString()); - Assert.Equal("9c0e31bb753d782ce20710d19828f4e97b4371c8733abd0c5c6f7f485306fb28", header.GetProperty("sha256").GetString()); + Assert.Equal("9c0e31bb753d782ce20710d19828f4e97b4371c8733abd0c5c6f7f485306fb28", + header.GetProperty("sha256").GetString()); Assert.Equal("CommentOnlyDifference", header.GetProperty("relation").GetString()); JsonElement pascal = sources[3].GetProperty("installed"); Assert.Equal("MirrorPascal", sources[3].GetProperty("role").GetString()); @@ -310,14 +351,16 @@ public void Authority_is_plugin_pas_and_mirrors_carry_their_hashes() }); // A host implementation is only cited for a function address whose target plugin.pas assigns. - Assert.All(Slots.Where(static slot => slot.GetProperty("hostImplementation").ValueKind != JsonValueKind.Null), static slot => - { - Assert.Equal("FunctionAddress", AssignmentKind(slot)); - Assert.Equal("pluginexports-pas", slot.GetProperty("hostImplementation").GetProperty("source").GetString()); - Assert.Equal("ObservedSource", slot.GetProperty("evidenceKind").GetString()); - }); + Assert.All(Slots.Where(static slot => slot.GetProperty("hostImplementation").ValueKind != JsonValueKind.Null), + static slot => + { + Assert.Equal("FunctionAddress", AssignmentKind(slot)); + Assert.Equal("pluginexports-pas", + slot.GetProperty("hostImplementation").GetProperty("source").GetString()); + Assert.Equal("ObservedSource", slot.GetProperty("evidenceKind").GetString()); + }); Assert.All(Slots.Where(static slot => IsKind(slot, "FunctionAddress") && - slot.GetProperty("hostImplementation").ValueKind == JsonValueKind.Null), + slot.GetProperty("hostImplementation").ValueKind == JsonValueKind.Null), static slot => Assert.Equal("ToQualify", slot.GetProperty("evidenceKind").GetString())); } @@ -327,14 +370,17 @@ public void Qualifiable_profile_status_is_not_observed_with_a_reason() JsonElement[] statuses = [.. Registry.GetProperty("profileStatus").EnumerateArray()]; JsonElement qualifiable = Assert.Single(statuses, static status => - string.Equals(status.GetProperty("profileId").GetString(), ClassicSlotRegistryContract.QualifiableProfile, StringComparison.Ordinal)); + string.Equals(status.GetProperty("profileId").GetString(), ClassicSlotRegistryContract.QualifiableProfile, + StringComparison.Ordinal)); Assert.Equal("NotObserved", qualifiable.GetProperty("status").GetString()); Assert.Contains("no managed-hostfxr route reaches the classic table", qualifiable.GetProperty("reason").GetString(), StringComparison.Ordinal); JsonElement documentary = Assert.Single(statuses, static status => - string.Equals(status.GetProperty("profileId").GetString(), ClassicSlotRegistryContract.DocumentaryProfile, StringComparison.Ordinal)); + string.Equals(status.GetProperty("profileId").GetString(), ClassicSlotRegistryContract.DocumentaryProfile, + StringComparison.Ordinal)); Assert.Equal("SourceOnly", documentary.GetProperty("status").GetString()); - Assert.All(Slots, static slot => Assert.Equal("NotObserved", slot.GetProperty("hostProfileStatus").GetString())); + Assert.All(Slots, + static slot => Assert.Equal("NotObserved", slot.GetProperty("hostProfileStatus").GetString())); } [Fact] @@ -351,7 +397,8 @@ public void No_slot_is_counted_as_qualified() [Fact] public void Lua_equivalents_are_named_only_for_function_slots() { - JsonElement[] withLua = [.. Slots.Where(static slot => slot.GetProperty("luaEquivalent").ValueKind != JsonValueKind.Null)]; + JsonElement[] withLua = + [.. Slots.Where(static slot => slot.GetProperty("luaEquivalent").ValueKind != JsonValueKind.Null)]; Assert.NotEmpty(withLua); Assert.All(withLua, static slot => @@ -360,7 +407,8 @@ public void Lua_equivalents_are_named_only_for_function_slots() Assert.Equal(HostName(slot), slot.GetProperty("luaEquivalent").GetProperty("name").GetString(), StringComparer.OrdinalIgnoreCase); }); - Assert.All(Slots, static slot => Assert.Equal(JsonValueKind.Null, slot.GetProperty("catalogSurfaceId").ValueKind)); + Assert.All(Slots, + static slot => Assert.Equal(JsonValueKind.Null, slot.GetProperty("catalogSurfaceId").ValueKind)); Assert.Equal("createForm", Slots[124].GetProperty("luaEquivalent").GetProperty("name").GetString()); } @@ -393,10 +441,14 @@ public void Callback_categories_cover_plugin_types_0_to_8() { JsonElement[] categories = [.. Registry.GetProperty("callbackCategories").EnumerateArray()]; - Assert.Equal([.. Enumerable.Range(0, 9)], categories.Select(static row => row.GetProperty("pluginType").GetInt32())); + Assert.Equal([.. Enumerable.Range(0, 9)], + categories.Select(static row => row.GetProperty("pluginType").GetInt32())); Assert.Equal( - ["ptAddressList", "ptMemoryView", "ptOnDebugEvent", "ptProcesswatcherEvent", "ptFunctionPointerchange", "ptMainMenu", - "ptDisassemblerContext", "ptDisassemblerRenderLine", "ptAutoAssembler"], + [ + "ptAddressList", "ptMemoryView", "ptOnDebugEvent", "ptProcesswatcherEvent", "ptFunctionPointerchange", + "ptMainMenu", + "ptDisassemblerContext", "ptDisassemblerRenderLine", "ptAutoAssembler" + ], categories.Select(static row => row.GetProperty("name").GetString()!), StringComparer.Ordinal); Assert.True(categories[2].GetProperty("synchronousDecision").GetBoolean()); Assert.Equal(1, categories.Count(static row => row.GetProperty("synchronousDecision").GetBoolean())); @@ -449,7 +501,8 @@ private static string HostName(JsonElement slot) private static JsonElement Divergence(JsonElement[] divergences, string id) { - return Assert.Single(divergences, row => string.Equals(row.GetProperty("id").GetString(), id, StringComparison.Ordinal)); + return Assert.Single(divergences, + row => string.Equals(row.GetProperty("id").GetString(), id, StringComparison.Ordinal)); } private static int[] Ints(JsonElement row, string property) @@ -464,10 +517,12 @@ private static string[] Strings(JsonElement row, string property) private static bool InRange(JsonElement[] ranges, int line) { - return ranges.Any(range => line >= range.GetProperty("start").GetInt32() && line <= range.GetProperty("end").GetInt32()); + return ranges.Any(range => + line >= range.GetProperty("start").GetInt32() && line <= range.GetProperty("end").GetInt32()); } - [GeneratedRegex(@"(?ProjectReference to. This project has none, by design (its own top-of-file /// comment: it only reads committed files and never builds, packs or restores), so it cannot reflect over a /// referenced assembly. Instead it loads the shipping assemblies' own build output with -/// from artifacts/bin/CheatEngine.SDK/<configuration> — the one +/// from artifacts/bin/CheatEngine.SDK/<configuration> — the one /// folder src/CheatEngine.SDK copies every libs/ assembly into (its csproj comment "Libraries embedded /// under lib/net10.0") alongside its own — which the solution build that runs before this test module (shared /// contracts section 1.8: build, then pack, then test) has already populated. This is still a from-disk load, never @@ -27,7 +27,16 @@ namespace CheatEngine.SDK.Repository.Tests.ApiGates; /// public sealed class ApiGateDiagnosticTests { - private const string UrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md"; + private const string UrlFormat = + "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md"; + + /// + /// The shipping assemblies (libs/ + src/CheatEngine.SDK itself), loaded once per test process from + /// the current configuration's build output. The configuration is read from this test module's own output + /// directory name (artifacts/bin/CheatEngine.SDK.Repository.Tests/<configuration>), never + /// hard-coded, so the same test scans whichever leg (Debug or Release) built it. + /// + private static readonly Lazy> s_shippingAssemblies = new(LoadShippingAssemblies); [Fact] public void Every_api_gate_attribute_uses_a_CESDK_id_and_the_documentation_url_format() @@ -44,7 +53,8 @@ public void Every_api_gate_attribute_uses_a_CESDK_id_and_the_documentation_url_f if (!string.Equals(gate.UrlFormat, UrlFormat, StringComparison.Ordinal)) { - offenders.Add($"{gate.Location}: {gate.Kind}('{gate.Id}') has UrlFormat '{gate.UrlFormat}', expected '{UrlFormat}'."); + offenders.Add( + $"{gate.Location}: {gate.Kind}('{gate.Id}') has UrlFormat '{gate.UrlFormat}', expected '{UrlFormat}'."); } } @@ -99,14 +109,6 @@ private static bool HasExpectedShape(string id, ApiGateKind kind) return true; } - /// - /// The shipping assemblies (libs/ + src/CheatEngine.SDK itself), loaded once per test process from - /// the current configuration's build output. The configuration is read from this test module's own output - /// directory name (artifacts/bin/CheatEngine.SDK.Repository.Tests/<configuration>), never - /// hard-coded, so the same test scans whichever leg (Debug or Release) built it. - /// - private static readonly Lazy> s_shippingAssemblies = new(LoadShippingAssemblies); - private static List ApiGates() { List gates = []; @@ -156,7 +158,8 @@ private static List LoadShippingAssemblies() } List assemblies = []; - foreach (string dll in Directory.EnumerateFiles(directory, "CheatEngine.SDK*.dll", SearchOption.TopDirectoryOnly)) + foreach (string dll in Directory.EnumerateFiles(directory, "CheatEngine.SDK*.dll", + SearchOption.TopDirectoryOnly)) { assemblies.Add(Assembly.LoadFrom(dll)); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Diagnostics/ApiDiagnosticIdTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Diagnostics/ApiDiagnosticIdTests.cs index 3310be7d..c0c5c38e 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Diagnostics/ApiDiagnosticIdTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Diagnostics/ApiDiagnosticIdTests.cs @@ -6,7 +6,8 @@ namespace CheatEngine.SDK.Repository.Tests.Diagnostics; /// /// The diagnostic identifiers that SDK product code declares on its own API through -/// [Obsolete(DiagnosticId = "CESDKnnnn")] and [Experimental("CESDKnnnn")]. The C# compiler raises them in +/// [Obsolete(DiagnosticId = "CESDKnnnn")] and [Experimental("CESDKnnnn")]. The C# compiler raises them +/// in /// consumer code, so, like the analyzer descriptors that DiagnosticCatalogTests covers, each one needs a /// documentation page, a row in analyzers/docs/README.md, the repository help-link format and an identifier /// from its reserved range (shared-contracts section 3.2: 5xxx experimental gates, 7xxx obsoletions). @@ -22,16 +23,15 @@ namespace CheatEngine.SDK.Repository.Tests.Diagnostics; /// public sealed partial class ApiDiagnosticIdTests { - private const string HelpUrlFormat = "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md"; + private const string HelpUrlFormat = + "https://github.com/CheatEngineNet/CheatEngine.SDK/blob/main/analyzers/docs/{0}.md"; /// /// Reviewed obsoletions outside the 7xxx range: the legacy Lua registration pair shares its usage analyzer /// identifier (shared-contracts section 3.3, S-REG-ANALYZER, CESDK1006). /// - private static readonly HashSet s_reviewedObsoleteIdsOutsideTheRange = new(StringComparer.Ordinal) - { - "CESDK1006" - }; + private static readonly HashSet s_reviewedObsoleteIdsOutsideTheRange = + new(StringComparer.Ordinal) { "CESDK1006" }; [Fact] public void the_source_scan_finds_the_declared_api_diagnostic_ids() @@ -39,7 +39,8 @@ public void the_source_scan_finds_the_declared_api_diagnostic_ids() IReadOnlyList ids = ScanApiDiagnosticIds(); Assert.Contains(ids, static id => id is { Kind: ApiDiagnosticKind.Obsolete, Id: "CESDK7001" } && - string.Equals(id.File, "libs/CheatEngine.SDK.Engine/Runtime/PointerSize.cs", StringComparison.Ordinal)); + string.Equals(id.File, "libs/CheatEngine.SDK.Engine/Runtime/PointerSize.cs", + StringComparison.Ordinal)); } [Fact] @@ -97,7 +98,8 @@ public void every_obsolete_or_experimental_diagnostic_id_uses_the_repository_hel { if (!string.Equals(id.UrlFormat, HelpUrlFormat, StringComparison.Ordinal)) { - offenders.Add($"{id.File}: {id.Id} has UrlFormat '{id.UrlFormat ?? "(none)"}', expected '{HelpUrlFormat}'."); + offenders.Add( + $"{id.File}: {id.Id} has UrlFormat '{id.UrlFormat ?? "(none)"}', expected '{HelpUrlFormat}'."); } } @@ -147,7 +149,8 @@ public static void D() { } List ids = [.. Scan("sample.cs", Source)]; Assert.Equal(3, ids.Count); - Assert.Equal(new ApiDiagnosticId("sample.cs", ApiDiagnosticKind.Obsolete, "CESDK7999", "https://example.invalid/{0}"), + Assert.Equal( + new ApiDiagnosticId("sample.cs", ApiDiagnosticKind.Obsolete, "CESDK7999", "https://example.invalid/{0}"), ids[0]); Assert.Equal(new ApiDiagnosticId("sample.cs", ApiDiagnosticKind.Experimental, "CESDK5999", "https://example.invalid/{0}.md"), ids[1]); @@ -224,9 +227,9 @@ public void the_scan_reads_attribute_lists_and_targets_and_reports_identifiers_t new("sample.cs", ApiDiagnosticKind.Experimental, "CESDK5908", null), new("sample.cs", ApiDiagnosticKind.Experimental, "CESDK5909", null), new("sample.cs", ApiDiagnosticKind.Obsolete, "CESDK7911", "c"), - new("sample.cs", ApiDiagnosticKind.Obsolete, "Ids.Old", "d", IsLiteral: false), - new("sample.cs", ApiDiagnosticKind.Experimental, "Ids.Gate", null, IsLiteral: false), - new("sample.cs", ApiDiagnosticKind.Obsolete, "\"SYSLIB0999\"", null, IsLiteral: false) + new("sample.cs", ApiDiagnosticKind.Obsolete, "Ids.Old", "d", false), + new("sample.cs", ApiDiagnosticKind.Experimental, "Ids.Gate", null, false), + new("sample.cs", ApiDiagnosticKind.Obsolete, "\"SYSLIB0999\"", null, false) ]; Assert.Equal(expected, Scan("sample.cs", Source)); @@ -237,7 +240,8 @@ private static List ScanApiDiagnosticIds() List ids = []; foreach (string file in RepositoryRoot.EnumerateSourceFiles("*.cs")) { - if (!file.StartsWith("libs/", StringComparison.Ordinal) && !file.StartsWith("src/", StringComparison.Ordinal)) + if (!file.StartsWith("libs/", StringComparison.Ordinal) && + !file.StartsWith("src/", StringComparison.Ordinal)) { continue; } @@ -274,7 +278,7 @@ private static IEnumerable Scan(string file, string source) if (expression.Success) { yield return new ApiDiagnosticId(file, kind, expression.Groups["expression"].Value.Trim(), urlFormat, - IsLiteral: false); + false); } } } @@ -378,7 +382,7 @@ private void ReadCode(bool inHole) { depth++; } - else if ((current is ')' or ']' or '}') && depth > 0) + else if (current is ')' or ']' or '}' && depth > 0) { depth--; } @@ -408,7 +412,7 @@ private bool TryReadStringLiteral() int index = _position; int dollars = 0; bool verbatim = false; - while (index < _source.Length && (_source[index] is '$' or '@')) + while (index < _source.Length && _source[index] is '$' or '@') { if (_source[index] == '$') { diff --git a/tests/CheatEngine.SDK.Repository.Tests/Generation/GeneratorInventoryTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Generation/GeneratorInventoryTests.cs index 0d2ee319..ba31960c 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Generation/GeneratorInventoryTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Generation/GeneratorInventoryTests.cs @@ -89,8 +89,8 @@ public void Generators_never_embed_a_local_cheat_engine_path() { string text = Read(path); if (text.Contains("Program Files", StringComparison.OrdinalIgnoreCase) || - text.Contains("celua.txt", StringComparison.OrdinalIgnoreCase) || - DriveRootedPath().IsMatch(text)) + text.Contains("celua.txt", StringComparison.OrdinalIgnoreCase) || + DriveRootedPath().IsMatch(text)) { offences.Add(path); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/DependabotConfigurationTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/DependabotConfigurationTests.cs index faeae296..1879ca6e 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/DependabotConfigurationTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/DependabotConfigurationTests.cs @@ -7,7 +7,8 @@ namespace CheatEngine.SDK.Repository.Tests.Governance; /// /// .github/dependabot.yml (audit register PR-CQ-07): every ecosystem waits before proposing a fresh release, /// the Roslyn pin and the SDK-implicit packages never move on their own, and titles stay compatible with the pull -/// request policy. https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference +/// request policy. +/// https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference /// public sealed class DependabotConfigurationTests { @@ -50,7 +51,9 @@ public void Every_ecosystem_has_a_cooldown_of_at_least_seven_days() foreach (string key in s_cooldownKeys) { string? value = YamlDocument.Scalar(cooldown, key); - if (value is not null && (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out int days) || days < MinimumCooldownDays)) + if (value is not null && + (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out int days) || + days < MinimumCooldownDays)) { problems.Add($"{ecosystem}: {key} is {value}"); } @@ -69,7 +72,8 @@ public void Roslyn_pins_and_sdk_implicit_packages_are_ignored() foreach (YamlMappingNode rule in YamlDocument.Mappings(nuget, "ignore")) { // A whole-package ignore has no update-types: a partial ignore would still let some bumps through. - Assert.True(YamlDocument.Child(rule, "update-types") is null && YamlDocument.Child(rule, "versions") is null, + Assert.True( + YamlDocument.Child(rule, "update-types") is null && YamlDocument.Child(rule, "versions") is null, $"The nuget ignore rule for '{YamlDocument.Scalar(rule, "dependency-name")}' must ignore every version."); ignored.Add(YamlDocument.Scalar(rule, "dependency-name") ?? ""); } @@ -92,7 +96,7 @@ public void Roslyn_ignores_cover_every_package_pinned_to_the_roslyn_floor() { string id = (string?) version.Attribute("Include") ?? ""; if (id.StartsWith("Microsoft.CodeAnalysis.", StringComparison.Ordinal) - && string.Equals((string?) version.Attribute("Version"), floor, StringComparison.Ordinal)) + && string.Equals((string?) version.Attribute("Version"), floor, StringComparison.Ordinal)) { pinnedToFloor.Add(id); } @@ -116,13 +120,15 @@ public void Dotnet_sdk_ecosystem_ignores_major_updates() foreach (YamlMappingNode rule in YamlDocument.Mappings(sdk, "ignore")) { if (string.Equals(YamlDocument.Scalar(rule, "dependency-name"), "*", StringComparison.Ordinal) - && YamlDocument.Scalars(rule, "update-types").Contains("version-update:semver-major", StringComparer.Ordinal)) + && YamlDocument.Scalars(rule, "update-types") + .Contains("version-update:semver-major", StringComparer.Ordinal)) { ignoresMajor = true; } } - Assert.True(ignoresMajor, "The dotnet-sdk ecosystem must ignore semver-major updates: a new .NET major is a migration."); + Assert.True(ignoresMajor, + "The dotnet-sdk ecosystem must ignore semver-major updates: a new .NET major is a migration."); } [Fact] @@ -172,7 +178,8 @@ public void Specific_nuget_groups_come_before_the_catch_all_group() private static List Updates() { - IReadOnlyList updates = YamlDocument.Mappings(YamlDocument.Load(ConfigurationPath).Root, "updates"); + IReadOnlyList updates = + YamlDocument.Mappings(YamlDocument.Load(ConfigurationPath).Root, "updates"); Assert.NotEmpty(updates); return [.. updates]; } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceDocumentTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceDocumentTests.cs index eceeb38c..894c5418 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceDocumentTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceDocumentTests.cs @@ -19,9 +19,14 @@ public sealed partial class GovernanceDocumentTests private const string IssueTemplates = ".github/ISSUE_TEMPLATE"; private const string CompatibilityForm = ".github/ISSUE_TEMPLATE/compatibility.yml"; private const string ChooserConfiguration = ".github/ISSUE_TEMPLATE/config.yml"; - private const string PrivateReportingUrl = "https://github.com/CheatEngineNet/CheatEngine.SDK/security/advisories/new"; + + private const string PrivateReportingUrl = + "https://github.com/CheatEngineNet/CheatEngine.SDK/security/advisories/new"; + private const string LuaFixture = "native/cheat-engine/lua53-64.dll"; - private const string BridgeBinary = "native/cheatengine-sdk-lua-bridge/runtimes/win-x64/native/cheatengine-sdk-lua-bridge.dll"; + + private const string BridgeBinary = + "native/cheatengine-sdk-lua-bridge/runtimes/win-x64/native/cheatengine-sdk-lua-bridge.dll"; /// Maintainers who may own paths; CODEOWNERS is informational (no required code-owner review). private static readonly string[] s_knownOwners = ["@AriusII", "@ShadowNineX"]; @@ -42,7 +47,10 @@ public void Security_policy_names_private_reporting_scope_response_and_supported string text = RepositoryFile.ReadText(SecurityPolicy); Assert.Equal( - ["Supported versions", "Reporting a vulnerability", "Scope", "Response", "Verifying releases", "Binary files in this repository"], + [ + "Supported versions", "Reporting a vulnerability", "Scope", "Response", "Verifying releases", + "Binary files in this repository" + ], Level2Headings(text)); Assert.Contains(PrivateReportingUrl, text, StringComparison.Ordinal); Assert.Contains("Never report a vulnerability in a public issue", text, StringComparison.Ordinal); @@ -67,7 +75,8 @@ public void Security_policy_describes_the_committed_binaries_with_their_real_has string actual = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(RepositoryFile.FullPath(LuaFixture)))); Assert.Contains($"`{actual}`", policy, StringComparison.Ordinal); - Assert.Contains($"`{actual}`", RepositoryFile.ReadText("native/cheat-engine/README.md"), StringComparison.Ordinal); + Assert.Contains($"`{actual}`", RepositoryFile.ReadText("native/cheat-engine/README.md"), + StringComparison.Ordinal); } [Fact] @@ -75,7 +84,8 @@ public void Code_of_conduct_routes_reports_through_private_reporting_without_an_ { string text = RepositoryFile.ReadText(CodeOfConduct); - Assert.Contains("https://www.contributor-covenant.org/version/2/1/code_of_conduct.html", text, StringComparison.Ordinal); + Assert.Contains("https://www.contributor-covenant.org/version/2/1/code_of_conduct.html", text, + StringComparison.Ordinal); Assert.Contains(PrivateReportingUrl, text, StringComparison.Ordinal); Assert.DoesNotMatch(EmailAddress(), text); } @@ -103,7 +113,8 @@ public void Codeowners_patterns_point_to_existing_paths_and_known_owners() Assert.NotEmpty(owners); foreach (string owner in owners) { - Assert.True(Array.IndexOf(s_knownOwners, owner) >= 0, $"{CodeOwners}: '{owner}' is not a known maintainer."); + Assert.True(Array.IndexOf(s_knownOwners, owner) >= 0, + $"{CodeOwners}: '{owner}' is not a known maintainer."); } // GitHub rejects "!" negation and "[ ]" ranges in CODEOWNERS. @@ -116,7 +127,8 @@ public void Codeowners_patterns_point_to_existing_paths_and_known_owners() string path = pattern.Trim('/'); Assert.True(RepositoryFile.ExistsWithExactCase(path, out bool isDirectory), $"{CodeOwners}: '{pattern}' matches nothing in the repository (exact case)."); - Assert.True(!pattern.EndsWith('/') || isDirectory, $"{CodeOwners}: '{pattern}' names a folder that is a file."); + Assert.True(!pattern.EndsWith('/') || isDirectory, + $"{CodeOwners}: '{pattern}' names a folder that is a file."); } } @@ -136,24 +148,29 @@ public void Compatibility_issue_form_requires_the_full_tuple() foreach (string id in s_requiredTupleIds) { - Assert.True(elements.TryGetValue(id, out YamlMappingNode? element), $"{CompatibilityForm} has no '{id}' field."); + Assert.True(elements.TryGetValue(id, out YamlMappingNode? element), + $"{CompatibilityForm} has no '{id}' field."); Assert.True(IsRequired(element), $"{CompatibilityForm}: '{id}' must be required."); } foreach (string id in s_optionalTupleIds) { - Assert.True(elements.TryGetValue(id, out YamlMappingNode? element), $"{CompatibilityForm} has no '{id}' field."); + Assert.True(elements.TryGetValue(id, out YamlMappingNode? element), + $"{CompatibilityForm} has no '{id}' field."); Assert.False(IsRequired(element), $"{CompatibilityForm}: '{id}' is optional."); } - IReadOnlyList levels = YamlDocument.Scalars(YamlDocument.Child(elements["evidence-level"], "attributes"), "options"); + IReadOnlyList levels = + YamlDocument.Scalars(YamlDocument.Child(elements["evidence-level"], "attributes"), "options"); foreach (string level in (string[]) ["(C0)", "(C1/C2)", "(C3)", "(C4)"]) { Assert.Contains(levels, option => option.EndsWith(level, StringComparison.Ordinal)); } - IReadOnlyList profiles = YamlDocument.Scalars(YamlDocument.Child(elements["load-profile"], "attributes"), "options"); - Assert.Contains(profiles, static option => option.Contains("ce-7.7.0.10621-x64-managed-hostfxr", StringComparison.Ordinal)); + IReadOnlyList profiles = + YamlDocument.Scalars(YamlDocument.Child(elements["load-profile"], "attributes"), "options"); + Assert.Contains(profiles, + static option => option.Contains("ce-7.7.0.10621-x64-managed-hostfxr", StringComparison.Ordinal)); } [Fact] @@ -193,17 +210,20 @@ public void Issue_form_element_ids_are_unique_and_valid() foreach (YamlMappingNode element in body) { string type = YamlDocument.Scalar(element, "type") ?? ""; - Assert.Contains(type, (string[]) ["markdown", "input", "textarea", "dropdown", "checkboxes"], StringComparer.Ordinal); + Assert.Contains(type, (string[]) ["markdown", "input", "textarea", "dropdown", "checkboxes"], + StringComparer.Ordinal); string? id = YamlDocument.Scalar(element, "id"); if (string.Equals(type, "markdown", StringComparison.Ordinal)) { continue; } - Assert.True(id is not null && ElementId().IsMatch(id), $"{path}: a {type} element has no valid id ('{id}')."); + Assert.True(id is not null && ElementId().IsMatch(id), + $"{path}: a {type} element has no valid id ('{id}')."); Assert.True(ids.Add(id), $"{path}: the id '{id}' is used twice."); YamlNode? attributes = YamlDocument.Child(element, "attributes"); - Assert.False(string.IsNullOrWhiteSpace(YamlDocument.Scalar(attributes, "label")), $"{path}: '{id}' has no label."); + Assert.False(string.IsNullOrWhiteSpace(YamlDocument.Scalar(attributes, "label")), + $"{path}: '{id}' has no label."); if (string.Equals(type, "dropdown", StringComparison.Ordinal)) { IReadOnlyList options = YamlDocument.Scalars(attributes, "options"); @@ -216,7 +236,8 @@ public void Issue_form_element_ids_are_unique_and_valid() Assert.DoesNotMatch(AbsoluteLocalPath(), form.Text); foreach (Match link in SelfLink().Matches(form.Text)) { - Assert.True(TryCheckSelfLink(link, out string? problem), $"{path}: {link.Value} does not resolve ({problem})."); + Assert.True(TryCheckSelfLink(link, out string? problem), + $"{path}: {link.Value} does not resolve ({problem})."); } } } @@ -232,7 +253,8 @@ public void Issue_forms_disable_blank_issues_and_link_private_reporting() { foreach (string key in (string[]) ["name", "url", "about"]) { - Assert.False(string.IsNullOrWhiteSpace(YamlDocument.Scalar(link, key)), $"{ChooserConfiguration}: a contact link has no {key}."); + Assert.False(string.IsNullOrWhiteSpace(YamlDocument.Scalar(link, key)), + $"{ChooserConfiguration}: a contact link has no {key}."); } string url = YamlDocument.Scalar(link, "url")!; @@ -257,8 +279,8 @@ public void Issue_forms_never_instruct_editing_the_cheat_engine_runtime_configur foreach (string sentence in Sentences(text)) { if (sentence.Contains("runtimeconfig", StringComparison.OrdinalIgnoreCase) - && EditInstruction().IsMatch(sentence) - && !NegationPattern().IsMatch(sentence)) + && EditInstruction().IsMatch(sentence) + && !NegationPattern().IsMatch(sentence)) { offenders.Add($"{path}: '{sentence}'"); } @@ -266,7 +288,8 @@ public void Issue_forms_never_instruct_editing_the_cheat_engine_runtime_configur } } - Assert.True(offenders.Count == 0, $"Issue forms must never ask users to edit ce.runtimeconfig.json: {string.Join("; ", offenders)}"); + Assert.True(offenders.Count == 0, + $"Issue forms must never ask users to edit ce.runtimeconfig.json: {string.Join("; ", offenders)}"); } /// The ## (ATX level-2) headings of a Markdown document, outside fenced code blocks, in order. @@ -278,7 +301,8 @@ private static List Level2Headings(string text) { string line = rawLine.TrimEnd(); string trimmedStart = line.TrimStart(); - if (trimmedStart.StartsWith("```", StringComparison.Ordinal) || trimmedStart.StartsWith("~~~", StringComparison.Ordinal)) + if (trimmedStart.StartsWith("```", StringComparison.Ordinal) || + trimmedStart.StartsWith("~~~", StringComparison.Ordinal)) { inFence = !inFence; continue; @@ -376,33 +400,37 @@ private static IEnumerable Sentences(string text) } } - [GeneratedRegex(@"(?<=[.!?;])\s+|\r?\n", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"(?<=[.!?;])\s+|\r?\n", RegexOptions.CultureInvariant, 1000)] private static partial Regex SentenceBoundary(); - [GeneratedRegex(@"\b(edit|modify|change|replace|overwrite)", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture, - matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"\b(edit|modify|change|replace|overwrite)", + RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture, + 1000)] private static partial Regex EditInstruction(); - [GeneratedRegex(@"\b(supported|qualified|compatible)\b", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture, - matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"\b(supported|qualified|compatible)\b", + RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture, + 1000)] private static partial Regex QualificationClaim(); - [GeneratedRegex(@"\b(not|never|no|without)\b", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture, - matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"\b(not|never|no|without)\b", + RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture, + 1000)] private static partial Regex NegationPattern(); - [GeneratedRegex("^[A-Za-z0-9_-]+$", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex("^[A-Za-z0-9_-]+$", RegexOptions.CultureInvariant, 1000)] private static partial Regex ElementId(); - [GeneratedRegex(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}", RegexOptions.CultureInvariant, 1000)] private static partial Regex EmailAddress(); /// A drive path, a user-profile folder or a file: URI: never valid in a public issue form. - [GeneratedRegex(@"[A-Za-z]:\\|\\Users\\|/home/|/Users/|file://", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"[A-Za-z]:\\|\\Users\\|/home/|/Users/|file://", RegexOptions.CultureInvariant, 1000)] private static partial Regex AbsoluteLocalPath(); /// An absolute link back into this repository on main. Group rest is the path as written. - [GeneratedRegex(@"(?i:https://github\.com/CheatEngineNet/CheatEngine\.SDK)/(?:blob|tree)/main/(?[^\s)\]""'`>]*)", - RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex( + @"(?i:https://github\.com/CheatEngineNet/CheatEngine\.SDK)/(?:blob|tree)/main/(?[^\s)\]""'`>]*)", + RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture, 1000)] private static partial Regex SelfLink(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceWorkflowTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceWorkflowTests.cs index 4e2add89..18e79c7b 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceWorkflowTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceWorkflowTests.cs @@ -31,8 +31,8 @@ public void Governance_workflows_pin_every_action_by_full_sha_with_a_version_com { Match uses = UsesLine().Match(lines[i]); if (uses.Success && !uses.Groups["reference"].Value.StartsWith("./", StringComparison.Ordinal) - && !(PinnedReference().IsMatch(uses.Groups["reference"].Value) - && VersionComment().IsMatch(uses.Groups["comment"].Value))) + && !(PinnedReference().IsMatch(uses.Groups["reference"].Value) + && VersionComment().IsMatch(uses.Groups["comment"].Value))) { offenders.Add($"{path}:{i + 1}: {lines[i].Trim()}"); } @@ -53,7 +53,8 @@ public void Governance_jobs_use_literal_runner_labels_and_timeouts() string? runner = YamlDocument.Scalar(job.Value, "runs-on"); Assert.True(runner is not null && Array.IndexOf(s_runnerLabels, runner) >= 0, $"{path} job {job.Key}: runs-on '{runner}' must be a literal windows-2025 or ubuntu-24.04 label."); - Assert.True(int.TryParse(YamlDocument.Scalar(job.Value, "timeout-minutes"), NumberStyles.None, CultureInfo.InvariantCulture, + Assert.True(int.TryParse(YamlDocument.Scalar(job.Value, "timeout-minutes"), NumberStyles.None, + CultureInfo.InvariantCulture, out int minutes) && minutes > 0, $"{path} job {job.Key} needs timeout-minutes."); } @@ -81,7 +82,7 @@ public void Governance_workflows_start_read_only_and_comment_every_job_elevation string name = ((YamlScalarNode) scope.Key).Value ?? ""; string access = ((YamlScalarNode) scope.Value).Value ?? ""; if (string.Equals(name, "contents", StringComparison.Ordinal) - && string.Equals(access, "read", StringComparison.Ordinal)) + && string.Equals(access, "read", StringComparison.Ordinal)) { continue; } @@ -105,7 +106,8 @@ public void Governance_checkouts_never_persist_credentials() { if (YamlDocument.UsesAction(step, "actions/checkout")) { - Assert.True(string.Equals(YamlDocument.Scalar(YamlDocument.Child(step, "with"), "persist-credentials"), "false", + Assert.True(string.Equals( + YamlDocument.Scalar(YamlDocument.Child(step, "with"), "persist-credentials"), "false", StringComparison.Ordinal), $"{path} job {job.Key}: actions/checkout must set persist-credentials: false."); } @@ -126,8 +128,10 @@ public void Governance_multi_line_scripts_stop_on_the_first_error() { foreach (YamlMappingNode step in YamlDocument.Steps(job.Value)) { - string[] lines = (YamlDocument.Scalar(step, "run") ?? "").ReplaceLineEndings("\n").Trim().Split('\n'); - if (lines.Length > 1 && !string.Equals(lines[0].Trim(), "$ErrorActionPreference = 'Stop'", StringComparison.Ordinal)) + string[] lines = (YamlDocument.Scalar(step, "run") ?? "").ReplaceLineEndings("\n").Trim() + .Split('\n'); + if (lines.Length > 1 && !string.Equals(lines[0].Trim(), "$ErrorActionPreference = 'Stop'", + StringComparison.Ordinal)) { offenders.Add($"{path} job {job.Key} step '{YamlDocument.Scalar(step, "name")}'"); } @@ -165,7 +169,8 @@ public void Governance_scripts_check_the_exit_code_of_every_native_command() next++; } - if (next >= lines.Length || !lines[next].TrimStart().StartsWith("if ($LASTEXITCODE -ne 0)", StringComparison.Ordinal)) + if (next >= lines.Length || !lines[next].TrimStart() + .StartsWith("if ($LASTEXITCODE -ne 0)", StringComparison.Ordinal)) { offenders.Add($"{path} job {job.Key}: '{lines[i].Trim()}'"); } @@ -244,7 +249,8 @@ public void Codeql_analyzes_csharp_cpp_and_actions_with_literal_runner_labels() ["cpp"] = ("c-cpp", "none", "windows-2025"), ["actions"] = ("actions", "none", "ubuntu-24.04") }; - Assert.Equal(expected.Keys.Order(StringComparer.Ordinal), YamlDocument.KeysOf(YamlDocument.Child(workflow.Root, "jobs")).Order(StringComparer.Ordinal)); + Assert.Equal(expected.Keys.Order(StringComparer.Ordinal), + YamlDocument.KeysOf(YamlDocument.Child(workflow.Root, "jobs")).Order(StringComparer.Ordinal)); foreach ((string id, (string language, string buildMode, string runner)) in expected) { YamlMappingNode job = workflow.Job(id); @@ -258,7 +264,8 @@ public void Codeql_analyzes_csharp_cpp_and_actions_with_literal_runner_labels() Assert.Equal(language, YamlDocument.Scalar(init, "languages")); Assert.Equal(buildMode, YamlDocument.Scalar(init, "build-mode")); Assert.Equal("security-extended", YamlDocument.Scalar(init, "queries")); - Assert.Equal($"/language:{language}", YamlDocument.Scalar(WithOf(job, "github/codeql-action/analyze"), "category")); + Assert.Equal($"/language:{language}", + YamlDocument.Scalar(WithOf(job, "github/codeql-action/analyze"), "category")); } // Python is not analysed: the repository has no Python source left, and a language without sources fails. @@ -271,19 +278,22 @@ public void Codeql_csharp_job_builds_the_product_graph_manually_without_shared_c YamlMappingNode job = YamlDocument.Load(GovernanceWorkflows.CodeQl).Job("csharp"); IReadOnlyList steps = YamlDocument.Steps(job); - YamlMappingNode checkout = Assert.Single(steps, static step => YamlDocument.UsesAction(step, "actions/checkout")); + YamlMappingNode checkout = + Assert.Single(steps, static step => YamlDocument.UsesAction(step, "actions/checkout")); Assert.Equal("0", YamlDocument.Scalar(YamlDocument.Child(checkout, "with"), "fetch-depth")); YamlMappingNode setup = Assert.Single(steps, static step => string.Equals(YamlDocument.Uses(step), "./.github/actions/setup-dotnet", StringComparison.Ordinal)); - Assert.Equal("src/CheatEngine.SDK/CheatEngine.SDK.csproj", YamlDocument.Scalar(YamlDocument.Child(setup, "with"), "restore")); + Assert.Equal("src/CheatEngine.SDK/CheatEngine.SDK.csproj", + YamlDocument.Scalar(YamlDocument.Child(setup, "with"), "restore")); YamlMappingNode build = Assert.Single(steps, static step => YamlDocument.Scalar(step, "run") is not null); string run = YamlDocument.NormalizeWhitespace(YamlDocument.Scalar(build, "run")!); foreach (string fragment in (string[]) - [ - "dotnet build src/CheatEngine.SDK/CheatEngine.SDK.csproj", "-c Release", "--no-restore", "--no-incremental", - "--disable-build-servers", "-p:UseSharedCompilation=false", "$LASTEXITCODE" - ]) + [ + "dotnet build src/CheatEngine.SDK/CheatEngine.SDK.csproj", "-c Release", "--no-restore", + "--no-incremental", + "--disable-build-servers", "-p:UseSharedCompilation=false", "$LASTEXITCODE" + ]) { Assert.Contains(fragment, run, StringComparison.Ordinal); } @@ -300,7 +310,8 @@ public void Codeql_csharp_job_builds_the_product_graph_manually_without_shared_c } } - Assert.True(IndexOf(steps, "./.github/actions/setup-dotnet") < init && init < buildIndex && buildIndex < analyze, + Assert.True( + IndexOf(steps, "./.github/actions/setup-dotnet") < init && init < buildIndex && buildIndex < analyze, "The CodeQL C# job must restore, then init, then build, then analyze."); } @@ -371,7 +382,8 @@ public void Scorecard_steps_use_only_the_actions_the_verifier_allows() "actions/checkout", "actions/create-github-app-token", "ossf/scorecard-action", "actions/upload-artifact", "github/codeql-action/upload-sarif", "step-security/harden-runner" ]; - foreach (YamlMappingNode step in YamlDocument.Steps(YamlDocument.Load(GovernanceWorkflows.Scorecard).Job("analysis"))) + foreach (YamlMappingNode step in YamlDocument.Steps(YamlDocument.Load(GovernanceWorkflows.Scorecard) + .Job("analysis"))) { string uses = YamlDocument.Uses(step) ?? ""; string action = uses.Split('@')[0]; @@ -402,7 +414,7 @@ public void Only_the_scorecard_job_requests_an_id_token() foreach (string holder in holders) { Assert.True(string.Equals(holder, GovernanceWorkflows.Scorecard + "#analysis", StringComparison.Ordinal) - || holder.StartsWith(".github/workflows/release.yml#", StringComparison.Ordinal), + || holder.StartsWith(".github/workflows/release.yml#", StringComparison.Ordinal), $"{holder} requests an id-token; only the Scorecard analysis job and the release workflow may."); } @@ -426,7 +438,8 @@ public void Zizmor_online_pins_the_tool_version_and_enables_online_audits() // Fork pull requests cannot upload SARIF, and drafts wait. string condition = YamlDocument.NormalizeWhitespace(YamlDocument.Scalar(job, "if") ?? ""); - Assert.Contains("github.event.pull_request.head.repo.full_name == github.repository", condition, StringComparison.Ordinal); + Assert.Contains("github.event.pull_request.head.repo.full_name == github.repository", condition, + StringComparison.Ordinal); Assert.Contains("!github.event.pull_request.draft", condition, StringComparison.Ordinal); Assert.Equal(["push", "pull_request", "schedule", "workflow_dispatch"], workflow.Triggers); } @@ -443,7 +456,8 @@ public void Online_and_gate_zizmor_runs_pin_the_same_version() { if (YamlDocument.UsesAction(step, "zizmorcore/zizmor-action")) { - Assert.True(string.Equals(YamlDocument.Scalar(YamlDocument.Child(step, "with"), "version"), ZizmorVersion, + Assert.True(string.Equals(YamlDocument.Scalar(YamlDocument.Child(step, "with"), "version"), + ZizmorVersion, StringComparison.Ordinal), $"{path} job {job.Key} must pin zizmor {ZizmorVersion} like {GovernanceWorkflows.ZizmorOnline}."); } @@ -477,8 +491,8 @@ public void Only_the_dependency_submit_job_holds_contents_write() foreach (KeyValuePair job in YamlDocument.Load(path).Jobs) { if (YamlDocument.Permissions(job.Value) is { } permissions - && permissions.TryGetValue("contents", out string? access) - && string.Equals(access, "write", StringComparison.Ordinal)) + && permissions.TryGetValue("contents", out string? access) + && string.Equals(access, "write", StringComparison.Ordinal)) { writers.Add($"{path}#{job.Key}"); } @@ -486,7 +500,8 @@ public void Only_the_dependency_submit_job_holds_contents_write() } Assert.Equal([GovernanceWorkflows.DependencySubmission + "#submit"], writers); - Assert.Null(YamlDocument.Permissions(YamlDocument.Load(GovernanceWorkflows.DependencySubmission).Job("detect"))); + Assert.Null( + YamlDocument.Permissions(YamlDocument.Load(GovernanceWorkflows.DependencySubmission).Job("detect"))); } [Fact] @@ -496,7 +511,8 @@ public void Dependency_submit_job_runs_no_third_party_code() IReadOnlyList steps = YamlDocument.Steps(workflow.Job("submit")); Assert.Equal(2, steps.Count); - Assert.True(YamlDocument.UsesAction(steps[0], "actions/download-artifact"), "submit starts by downloading the snapshot."); + Assert.True(YamlDocument.UsesAction(steps[0], "actions/download-artifact"), + "submit starts by downloading the snapshot."); Assert.Equal("dependency-snapshot", YamlDocument.Scalar(YamlDocument.Child(steps[0], "with"), "name")); Assert.Null(YamlDocument.Uses(steps[1])); string run = YamlDocument.Scalar(steps[1], "run") ?? ""; @@ -512,7 +528,8 @@ public void Dependency_submit_job_runs_no_third_party_code() } // The official action fetches the latest Component Detection at run time next to the write token. - Assert.DoesNotContain("component-detection-dependency-submission-action", workflow.Text, StringComparison.Ordinal); + Assert.DoesNotContain("component-detection-dependency-submission-action", workflow.Text, + StringComparison.Ordinal); } [Fact] @@ -525,8 +542,12 @@ public void Dependency_detection_uses_a_pinned_hash_verified_component_detection "Run Component Detection and build the snapshot", StringComparison.Ordinal)); string script = YamlDocument.Scalar(step, "run") ?? ""; - Assert.Matches(new Regex(@"^\s*\$detectorVersion = '\d+\.\d+\.\d+'\r?$", RegexOptions.Multiline, TimeSpan.FromSeconds(1)), script); - Assert.Matches(new Regex(@"^\s*\$detectorSha256 = '[0-9a-f]{64}'\r?$", RegexOptions.Multiline, TimeSpan.FromSeconds(1)), script); + Assert.Matches( + new Regex(@"^\s*\$detectorVersion = '\d+\.\d+\.\d+'\r?$", RegexOptions.Multiline, TimeSpan.FromSeconds(1)), + script); + Assert.Matches( + new Regex(@"^\s*\$detectorSha256 = '[0-9a-f]{64}'\r?$", RegexOptions.Multiline, TimeSpan.FromSeconds(1)), + script); Assert.Contains("releases/download/v$detectorVersion/$detectorAsset", script, StringComparison.Ordinal); Assert.Contains("Get-FileHash -LiteralPath $detector -Algorithm SHA256", script, StringComparison.Ordinal); Assert.Contains("--locked-mode", script, StringComparison.Ordinal); @@ -554,14 +575,20 @@ public async Task Dependency_submit_step_submits_only_a_snapshot_of_this_run(str ["ref"] = Is(variant, "other_ref") ? "refs/heads/feature" : Ref, ["job"] = new Dictionary(StringComparer.Ordinal) { - ["correlator"] = Is(variant, "other_correlator") ? "other" : "sdk-nuget", - ["id"] = "1" + ["correlator"] = Is(variant, "other_correlator") ? "other" : "sdk-nuget", ["id"] = "1" }, - ["detector"] = new Dictionary(StringComparer.Ordinal) { ["name"] = "d", ["version"] = "1", ["url"] = "u" }, + ["detector"] = + new Dictionary(StringComparer.Ordinal) + { + ["name"] = "d", ["version"] = "1", ["url"] = "u" + }, ["scanned"] = "2026-09-23T00:00:00Z", ["manifests"] = Is(variant, "no_manifest") ? new Dictionary(StringComparer.Ordinal) - : new Dictionary(StringComparer.Ordinal) { ["src/A.csproj"] = new Dictionary(StringComparer.Ordinal) } + : new Dictionary(StringComparer.Ordinal) + { + ["src/A.csproj"] = new Dictionary(StringComparer.Ordinal) + } }; if (Is(variant, "extra_property")) { @@ -571,11 +598,12 @@ public async Task Dependency_submit_step_submits_only_a_snapshot_of_this_run(str await File.WriteAllTextAsync(directory.File("snapshot/snapshot.json"), JsonSerializer.Serialize(snapshot), TestContext.Current.CancellationToken); - YamlMappingNode submit = YamlDocument.Steps(YamlDocument.Load(GovernanceWorkflows.DependencySubmission).Job("submit"))[1]; + YamlMappingNode submit = + YamlDocument.Steps(YamlDocument.Load(GovernanceWorkflows.DependencySubmission).Job("submit"))[1]; string marker = directory.File("gh-called.txt"); string script = $"Set-Location -LiteralPath {PwshScript.Quote(directory.Path)}" + Environment.NewLine + - $"function gh {{ $args -join ' ' | Set-Content -LiteralPath {PwshScript.Quote(marker)}; $global:LASTEXITCODE = 0 }}" + - Environment.NewLine + YamlDocument.Scalar(submit, "run"); + $"function gh {{ $args -join ' ' | Set-Content -LiteralPath {PwshScript.Quote(marker)}; $global:LASTEXITCODE = 0 }}" + + Environment.NewLine + YamlDocument.Scalar(submit, "run"); Dictionary environment = new(StringComparer.Ordinal) { ["REPOSITORY"] = "CheatEngineNet/CheatEngine.SDK", @@ -608,7 +636,8 @@ private static bool Is(string value, string expected) private static YamlNode? WithOf(YamlMappingNode job, string action) { YamlMappingNode step = Assert.Single(YamlDocument.Steps(job), step => YamlDocument.UsesAction(step, action) - || string.Equals(YamlDocument.Uses(step), action, StringComparison.Ordinal)); + || string.Equals(YamlDocument.Uses(step), + action, StringComparison.Ordinal)); return YamlDocument.Child(step, "with"); } @@ -617,7 +646,7 @@ private static int IndexOf(IReadOnlyList steps, string action) for (int i = 0; i < steps.Count; i++) { if (YamlDocument.UsesAction(steps[i], action) - || string.Equals(YamlDocument.Uses(steps[i]), action, StringComparison.Ordinal)) + || string.Equals(YamlDocument.Uses(steps[i]), action, StringComparison.Ordinal)) { return i; } @@ -626,17 +655,18 @@ private static int IndexOf(IReadOnlyList steps, string action) return -1; } - [GeneratedRegex(@"^\s*(-\s+)?uses:\s+(?\S+)(?.*)$", RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture, - matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^\s*(-\s+)?uses:\s+(?\S+)(?.*)$", + RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture, + 1000)] private static partial Regex UsesLine(); - [GeneratedRegex(@"^[A-Za-z0-9_.-]+/[A-Za-z0-9_./-]+@[0-9a-f]{40}$", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^[A-Za-z0-9_.-]+/[A-Za-z0-9_./-]+@[0-9a-f]{40}$", RegexOptions.CultureInvariant, 1000)] private static partial Regex PinnedReference(); - [GeneratedRegex(@"^\s+# v\d+\.\d+\.\d+$", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^\s+# v\d+\.\d+\.\d+$", RegexOptions.CultureInvariant, 1000)] private static partial Regex VersionComment(); /// A line that starts a native command or a repository script (same pattern as WorkflowContractTests). - [GeneratedRegex(@"^\s*(?:dotnet|xmake|git|gh|tar)\s|^\s*\./|^\s*&\s", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^\s*(?:dotnet|xmake|git|gh|tar)\s|^\s*\./|^\s*&\s", RegexOptions.CultureInvariant, 1000)] private static partial Regex NativeInvocation(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshResult.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshResult.cs index 036ae325..1f42a36c 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshResult.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshResult.cs @@ -4,5 +4,6 @@ namespace CheatEngine.SDK.Repository.Tests.Governance; internal sealed record PwshResult(int ExitCode, string StandardOutput, string StandardError) { /// Both streams, for assertion messages. - public string Transcript => $"exit code {ExitCode}{Environment.NewLine}--- stdout ---{Environment.NewLine}{StandardOutput}{Environment.NewLine}--- stderr ---{Environment.NewLine}{StandardError}"; + public string Transcript => + $"exit code {ExitCode}{Environment.NewLine}--- stdout ---{Environment.NewLine}{StandardOutput}{Environment.NewLine}--- stderr ---{Environment.NewLine}{StandardError}"; } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshScript.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshScript.cs index e6974a49..fd3253b5 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshScript.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshScript.cs @@ -23,7 +23,8 @@ internal static class PwshScript [ "GITHUB_STEP_SUMMARY", "GITHUB_OUTPUT", "GITHUB_ENV", "GITHUB_PATH", "GITHUB_STATE", "GITHUB_ACTIONS", "CI", "PR_TITLE", "PR_BODY", "PR_AUTHOR", "BASE_SHA", "HEAD_SHA", "GH_TOKEN", "GITHUB_TOKEN", "GH_REPO", - "NEEDS", "RUN_URL", "DRIFT", "BROKEN_LINKS", "REPOSITORY", "SNAPSHOT_SHA", "SNAPSHOT_REF", "SNAPSHOT_CORRELATOR", + "NEEDS", "RUN_URL", "DRIFT", "BROKEN_LINKS", "REPOSITORY", "SNAPSHOT_SHA", "SNAPSHOT_REF", + "SNAPSHOT_CORRELATOR", "SNAPSHOT_JOB_ID", "SNAPSHOT_JOB_URL", "CESDK_PACKAGED_UMBRELLA_NUPKG" ]; @@ -34,7 +35,7 @@ public static async Task RunTextAsync(string scriptText, using TemporaryDirectory directory = new(); string scriptPath = Path.Combine(directory.Path, "script.ps1"); string preamble = "Set-StrictMode -Version Latest" + Environment.NewLine + - "$ErrorActionPreference = 'Stop'" + Environment.NewLine; + "$ErrorActionPreference = 'Stop'" + Environment.NewLine; await File.WriteAllTextAsync(scriptPath, preamble + scriptText, new UTF8Encoding(false), TestContext.Current.CancellationToken); return await RunFileAsync(scriptPath, [], environment); @@ -85,7 +86,7 @@ public static async Task RunFileAsync(string scriptPath, IReadOnlyLi timeout.CancelAfter(s_timeout); using Process process = Process.Start(startInfo) - ?? throw new InvalidOperationException($"'{startInfo.FileName}' did not start."); + ?? throw new InvalidOperationException($"'{startInfo.FileName}' did not start."); process.StandardInput.Close(); Task standardOutput = process.StandardOutput.ReadToEndAsync(timeout.Token); Task standardError = process.StandardError.ReadToEndAsync(timeout.Token); @@ -95,9 +96,10 @@ public static async Task RunFileAsync(string scriptPath, IReadOnlyLi } catch (OperationCanceledException) { - process.Kill(entireProcessTree: true); + process.Kill(true); TestContext.Current.CancellationToken.ThrowIfCancellationRequested(); - Assert.Fail($"pwsh did not finish '{RepositoryRoot.ToRelative(fullPath)}' within {s_timeout.TotalSeconds} s."); + Assert.Fail( + $"pwsh did not finish '{RepositoryRoot.ToRelative(fullPath)}' within {s_timeout.TotalSeconds} s."); } return new PwshResult(process.ExitCode, await standardOutput, await standardError); diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/TemporaryDirectory.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/TemporaryDirectory.cs index be241ad8..74ce04eb 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/TemporaryDirectory.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/TemporaryDirectory.cs @@ -15,17 +15,11 @@ public string Path get; } - /// The absolute path of a file inside the folder. - public string File(string name) - { - return System.IO.Path.Combine(Path, name); - } - public void Dispose() { try { - Directory.Delete(Path, recursive: true); + Directory.Delete(Path, true); } catch (IOException) { @@ -36,4 +30,10 @@ public void Dispose() // Same as above. } } + + /// The absolute path of a file inside the folder. + public string File(string name) + { + return System.IO.Path.Combine(Path, name); + } } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/YamlDocument.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/YamlDocument.cs index e35dcc97..be8ba19b 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/YamlDocument.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/YamlDocument.cs @@ -5,7 +5,8 @@ namespace CheatEngine.SDK.Repository.Tests.Governance; /// /// A committed YAML file (workflow, Dependabot configuration, issue form) read through YamlDotNet's representation /// model. Every scalar stays the string written in the file: the workflow key on stays "on" (no YAML 1.1 -/// boolean resolution) and 'true' and true both read as "true", which is how GitHub compares them. +/// boolean resolution) and 'true' and true both read as "true", which is how GitHub compares +/// them. /// internal sealed class YamlDocument { @@ -46,7 +47,8 @@ public IReadOnlyList> Jobs { if (entry.Value is YamlMappingNode job) { - jobs.Add(new KeyValuePair(((YamlScalarNode) entry.Key).Value ?? "", job)); + jobs.Add(new KeyValuePair(((YamlScalarNode) entry.Key).Value ?? "", + job)); } } } diff --git a/tests/CheatEngine.SDK.Repository.Tests/HostContract/ConcurrencyContractDocumentationTests.cs b/tests/CheatEngine.SDK.Repository.Tests/HostContract/ConcurrencyContractDocumentationTests.cs index b279cec4..4b3f54f4 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/HostContract/ConcurrencyContractDocumentationTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/HostContract/ConcurrencyContractDocumentationTests.cs @@ -11,25 +11,26 @@ namespace CheatEngine.SDK.Repository.Tests.HostContract; /// public sealed class ConcurrencyContractDocumentationTests { + // This test's own source quotes the banned phrases verbatim (as the pattern it looks for and in this remark), so + // it is excluded from its own scan; every other file under libs/ and tests/ is still checked. + private const string SelfPath = + "tests/CheatEngine.SDK.Repository.Tests/HostContract/ConcurrencyContractDocumentationTests.cs"; + private static readonly Regex UnqualifiedCardinalityClaim = new( @"\(one per plugin\)|one load context hosts one plugin|hosted by this assembly load context", RegexOptions.IgnoreCase | RegexOptions.Compiled, TimeSpan.FromSeconds(1)); - // This test's own source quotes the banned phrases verbatim (as the pattern it looks for and in this remark), so - // it is excluded from its own scan; every other file under libs/ and tests/ is still checked. - private const string SelfPath = "tests/CheatEngine.SDK.Repository.Tests/HostContract/ConcurrencyContractDocumentationTests.cs"; - [Fact] public void Sources_and_readmes_never_claim_one_runtime_or_load_context_per_plugin() { List offenders = []; foreach (string relative in RepositoryRoot.EnumerateSourceFiles("*.cs") - .Concat(RepositoryRoot.EnumerateSourceFiles("*.md")) - .Where(static path => (path.StartsWith("libs/", StringComparison.Ordinal) - || path.StartsWith("tests/", StringComparison.Ordinal)) - && !string.Equals(path, SelfPath, StringComparison.Ordinal)) - .Distinct(StringComparer.Ordinal) - .Order(StringComparer.Ordinal)) + .Concat(RepositoryRoot.EnumerateSourceFiles("*.md")) + .Where(static path => (path.StartsWith("libs/", StringComparison.Ordinal) + || path.StartsWith("tests/", StringComparison.Ordinal)) + && !string.Equals(path, SelfPath, StringComparison.Ordinal)) + .Distinct(StringComparer.Ordinal) + .Order(StringComparer.Ordinal)) { string text = File.ReadAllText(Path.Combine(RepositoryRoot.Path, relative)); foreach (Match match in UnqualifiedCardinalityClaim.Matches(text)) @@ -39,13 +40,15 @@ public void Sources_and_readmes_never_claim_one_runtime_or_load_context_per_plug } Assert.True(offenders.Count == 0, - "Unqualified plugin-cardinality claim(s):" + Environment.NewLine + string.Join(Environment.NewLine, offenders)); + "Unqualified plugin-cardinality claim(s):" + Environment.NewLine + + string.Join(Environment.NewLine, offenders)); } [Fact] public void Hosting_readme_publishes_the_ADR_07_concurrency_contract() { - string readme = File.ReadAllText(Path.Combine(RepositoryRoot.Path, "libs", "CheatEngine.SDK.Hosting", "README.md")); + string readme = + File.ReadAllText(Path.Combine(RepositoryRoot.Path, "libs", "CheatEngine.SDK.Hosting", "README.md")); Assert.Contains("Threading and Lua concurrency contract (ADR-07)", readme, StringComparison.Ordinal); int sectionStart = readme.IndexOf("Threading and Lua concurrency contract (ADR-07)", StringComparison.Ordinal); string section = readme[sectionStart..]; diff --git a/tests/CheatEngine.SDK.Repository.Tests/HostContract/NativeHostEmulatorScriptTests.cs b/tests/CheatEngine.SDK.Repository.Tests/HostContract/NativeHostEmulatorScriptTests.cs index 6e1b6f24..b12e6ca5 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/HostContract/NativeHostEmulatorScriptTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/HostContract/NativeHostEmulatorScriptTests.cs @@ -52,7 +52,8 @@ public void Emulator_scripts_never_reference_a_cheat_engine_installation() continue; } - string text = File.ReadAllText(Path.Combine(RepositoryRoot.Path, relativePath.Replace('/', Path.DirectorySeparatorChar))); + string text = File.ReadAllText(Path.Combine(RepositoryRoot.Path, + relativePath.Replace('/', Path.DirectorySeparatorChar))); if (CheatEngineInstallationReference().IsMatch(text)) { offendingFiles.Add(relativePath); @@ -77,7 +78,8 @@ public void Build_script_writes_only_under_its_output_directory() } string codePortion = CommentStart().Split(line)[0]; - Assert.False(DriveLetterPath().IsMatch(codePortion), $"Hardcoded drive-letter path outside a comment: '{line.Trim()}'"); + Assert.False(DriveLetterPath().IsMatch(codePortion), + $"Hardcoded drive-letter path outside a comment: '{line.Trim()}'"); } } @@ -86,22 +88,25 @@ private static string RepositoryFile(string relativePath) return Path.Combine(RepositoryRoot.Path, relativePath.Replace('/', Path.DirectorySeparatorChar)); } - [GeneratedRegex(@"&\s*\$compiler\.Source\b", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"&\s*\$compiler\.Source\b", RegexOptions.CultureInvariant, 1000)] private static partial Regex NativeCommandInvocation(); - [GeneratedRegex(@"Program Files\\Cheat Engine|cheatengine-x86_64", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"Program Files\\Cheat Engine|cheatengine-x86_64", + RegexOptions.CultureInvariant | RegexOptions.IgnoreCase, 1000)] private static partial Regex CheatEngineInstallationReference(); - [GeneratedRegex(@"^\s*(Copy-Item|Set-Content).*$", RegexOptions.CultureInvariant | RegexOptions.Multiline | RegexOptions.ExplicitCapture, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^\s*(Copy-Item|Set-Content).*$", + RegexOptions.CultureInvariant | RegexOptions.Multiline | RegexOptions.ExplicitCapture, 1000)] private static partial Regex WriteCommand(); - [GeneratedRegex(@"resolvedOutputDirectory|nethostDllDestination|runtimeConfigDestination|manifestPath|\$exe\b|\$objectFile\b", - RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex( + @"resolvedOutputDirectory|nethostDllDestination|runtimeConfigDestination|manifestPath|\$exe\b|\$objectFile\b", + RegexOptions.CultureInvariant, 1000)] private static partial Regex OutputDirectoryDerivedVariable(); - [GeneratedRegex(@"[A-Za-z]:\\", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"[A-Za-z]:\\", RegexOptions.CultureInvariant, 1000)] private static partial Regex DriveLetterPath(); - [GeneratedRegex(@"(? 0, "No project sets RuntimeIdentifier: the Native AOT probes are expected to."); + Assert.True(runtimeSpecificProjects > 0, + "No project sets RuntimeIdentifier: the Native AOT probes are expected to."); } [Fact] diff --git a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaApiUseScanner.cs b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaApiUseScanner.cs index 0ca857fd..130038b4 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaApiUseScanner.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaApiUseScanner.cs @@ -38,11 +38,11 @@ internal static IReadOnlyList Scan(string source, IReadOnlySet(?:global::)?(?:CheatEngine\.SDK\.Lua\.Interop\.Api\.)?LuaApi\s*\.\s*)?\b(?(?:lua|luaL|luaopen)_\w+)\b", - RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + RegexOptions.CultureInvariant, 1000)] private static partial Regex MemberReference(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaBridgeDocuments.cs b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaBridgeDocuments.cs index 0b13608d..311fb696 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaBridgeDocuments.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaBridgeDocuments.cs @@ -14,7 +14,10 @@ namespace CheatEngine.SDK.Repository.Tests.LuaBridge; internal static class LuaBridgeDocuments { internal const string CataloguePath = "libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json"; - internal const string MatrixPath = "tests/CheatEngine.SDK.Repository.Tests/LuaBridge/TestData/lua-interop-primitives.json"; + + internal const string MatrixPath = + "tests/CheatEngine.SDK.Repository.Tests/LuaBridge/TestData/lua-interop-primitives.json"; + internal const string BridgeSourcePath = "native/cheatengine-sdk-lua-bridge/cheatengine_sdk_lua_bridge.c"; internal const string XmakePath = "native/cheatengine-sdk-lua-bridge/xmake.lua"; internal const string LuaFixturePath = "native/cheat-engine/lua53-64.dll"; diff --git a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaInteropPrimitiveMatrixDocumentTests.cs b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaInteropPrimitiveMatrixDocumentTests.cs index 6e958eec..8d37f94f 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaInteropPrimitiveMatrixDocumentTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaInteropPrimitiveMatrixDocumentTests.cs @@ -28,7 +28,8 @@ public sealed class LuaInteropPrimitiveMatrixDocumentTests [Fact] public void Primitive_matrix_has_its_schema_identity() { - Assert.Equal("cheatengine-lua-interop-primitives/v0", LuaBridgeDocuments.Matrix.GetProperty("schema").GetString()); + Assert.Equal("cheatengine-lua-interop-primitives/v0", + LuaBridgeDocuments.Matrix.GetProperty("schema").GetString()); } [Fact] @@ -44,7 +45,8 @@ public void Primitive_matrix_is_canonical_and_its_lists_are_sorted_and_unique() string[] exceptions = [ .. matrix.GetProperty("productionExceptions").EnumerateArray() - .Select(static item => item.GetProperty("member").GetString() + "|" + item.GetProperty("file").GetString()) + .Select(static item => + item.GetProperty("member").GetString() + "|" + item.GetProperty("file").GetString()) ]; Assert.Equal(exceptions.Order(StringComparer.Ordinal), exceptions, StringComparer.Ordinal); Assert.Equal(exceptions.Length, exceptions.Distinct(StringComparer.Ordinal).Count()); @@ -56,7 +58,8 @@ public void Rows_are_consistent_with_their_decision_bridge_operation_and_manual_ HashSet operations = new(LuaBridgeDocuments.Operations.Select(static operation => operation.GetProperty("id").GetString()!), StringComparer.Ordinal); Dictionary divergences = LuaBridgeDocuments.Matrix.GetProperty("manualDivergences") - .EnumerateArray().ToDictionary(static item => item.GetProperty("member").GetString()!, StringComparer.Ordinal); + .EnumerateArray().ToDictionary(static item => item.GetProperty("member").GetString()!, + StringComparer.Ordinal); List problems = []; foreach (JsonElement row in LuaBridgeDocuments.Rows) { @@ -65,7 +68,8 @@ public void Rows_are_consistent_with_their_decision_bridge_operation_and_manual_ } Assert.True(problems.Count == 0, string.Join(Environment.NewLine, problems)); - HashSet members = new(LuaBridgeDocuments.Rows.Select(static row => row.GetProperty("member").GetString()!), + HashSet members = new( + LuaBridgeDocuments.Rows.Select(static row => row.GetProperty("member").GetString()!), StringComparer.Ordinal); Assert.All(divergences.Keys, member => Assert.Contains(member, members)); } @@ -77,7 +81,8 @@ public void Production_raw_LuaApi_uses_are_classified_or_explicitly_excepted() static row => row.GetProperty("member").GetString()!, static row => row.GetProperty("decision").GetString()!, StringComparer.Ordinal); HashSet excepted = new(LuaBridgeDocuments.Matrix.GetProperty("productionExceptions").EnumerateArray() - .Select(static item => item.GetProperty("member").GetString() + "|" + item.GetProperty("file").GetString()), + .Select(static item => + item.GetProperty("member").GetString() + "|" + item.GetProperty("file").GetString()), StringComparer.Ordinal); HashSet members = new(decisions.Keys, StringComparer.Ordinal); HashSet used = new(StringComparer.Ordinal); @@ -91,7 +96,8 @@ public void Production_raw_LuaApi_uses_are_classified_or_explicitly_excepted() used.Add(key); if (decisions[use.Member] is not ("DirectAllowed" or "Lifecycle") && !excepted.Contains(key)) { - problems.Add($"{file}:{use.Line}: {use.Member} is {decisions[use.Member]}; route it through the bridge or add a production exception."); + problems.Add( + $"{file}:{use.Line}: {use.Member} is {decisions[use.Member]}; route it through the bridge or add a production exception."); } } } @@ -111,16 +117,16 @@ public void Scanner_sees_qualified_and_static_uses_and_ignores_comments_and_lite { HashSet members = new(["lua_tolstring", "lua_settop", "lua_gettop"], StringComparer.Ordinal); const string Source = """" - using static CheatEngine.SDK.Lua.Interop.Api.LuaApi; - // lua_gettop(L) in a comment - /* LuaApi.lua_gettop */ - class C - { - string s = "lua_gettop(L)"; - string v = @"LuaApi.lua_gettop ""quoted"""; - void M(void* L) { lua_settop(L, 0); _ = LuaApi.lua_tolstring(L, -1, null); other.lua_gettop(); } - } - """"; + using static CheatEngine.SDK.Lua.Interop.Api.LuaApi; + // lua_gettop(L) in a comment + /* LuaApi.lua_gettop */ + class C + { + string s = "lua_gettop(L)"; + string v = @"LuaApi.lua_gettop ""quoted"""; + void M(void* L) { lua_settop(L, 0); _ = LuaApi.lua_tolstring(L, -1, null); other.lua_gettop(); } + } + """"; IReadOnlyList uses = LuaApiUseScanner.Scan(Source, members); @@ -139,7 +145,8 @@ public void Checkstack_proof_record_matches_the_bundled_lua_and_the_lf_pinned_br proof.GetProperty("bridgeSourceSha256").GetString()); Assert.Equal(RepositoryDocument.RawSha256(LuaBridgeDocuments.XmakePath), proof.GetProperty("xmakeSha256").GetString()); - Assert.DoesNotContain((byte) '\r', File.ReadAllBytes(RepositoryDocument.Absolute(LuaBridgeDocuments.BridgeSourcePath))); + Assert.DoesNotContain((byte) '\r', + File.ReadAllBytes(RepositoryDocument.Absolute(LuaBridgeDocuments.BridgeSourcePath))); string[] test = proof.GetProperty("checkstackEvidence").GetString()!.Split('.'); string file = Assert.Single(RepositoryRoot.EnumerateSourceFiles(test[0] + ".cs"), @@ -152,9 +159,10 @@ public void Bundled_lua_fixture_hash_equals_the_catalogue_and_primitive_matrix_h { string fixture = RepositoryDocument.RawSha256(LuaBridgeDocuments.LuaFixturePath); - Assert.Equal(fixture, LuaBridgeDocuments.Matrix.GetProperty("bridgeProof").GetProperty("luaFixtureSha256").GetString()); + Assert.Equal(fixture, + LuaBridgeDocuments.Matrix.GetProperty("bridgeProof").GetProperty("luaFixtureSha256").GetString()); Assert.Equal(fixture, LuaBridgeDocuments.Catalogue.GetProperty("host").GetProperty("lua") - .GetProperty("fixtureSha256").GetString(), ignoreCase: true); + .GetProperty("fixtureSha256").GetString(), true); } private static void CheckRoute(JsonElement row, HashSet operations, List problems) @@ -164,7 +172,7 @@ private static void CheckRoute(JsonElement row, HashSet operations, List string raises = row.GetProperty("raises").GetString()!; string? bridge = LuaBridgeDocuments.OptionalString(row, "bridgeOperation"); string? native = LuaBridgeDocuments.OptionalString(row, "nativeSymbol"); - if (raises is "Memory" or "Any" or "Always" && (decision is "DirectAllowed" or "Lifecycle")) + if (raises is "Memory" or "Any" or "Always" && decision is "DirectAllowed" or "Lifecycle") { problems.Add($"{member}: a raising member cannot be {decision}."); } @@ -175,9 +183,10 @@ private static void CheckRoute(JsonElement row, HashSet operations, List } if (string.Equals(decision, "BridgeRequired", StringComparison.Ordinal) && bridge is null && - !string.Equals(member, "lua_error", StringComparison.Ordinal)) + !string.Equals(member, "lua_error", StringComparison.Ordinal)) { - problems.Add($"{member}: BridgeRequired names no bridge operation (only lua_error, raised by the bridge's C code, may)."); + problems.Add( + $"{member}: BridgeRequired names no bridge operation (only lua_error, raised by the bridge's C code, may)."); } if (native is not null && !string.Equals(native, member, StringComparison.Ordinal)) @@ -186,7 +195,8 @@ private static void CheckRoute(JsonElement row, HashSet operations, List } } - private static void CheckProvenance(JsonElement row, Dictionary divergences, List problems) + private static void CheckProvenance(JsonElement row, Dictionary divergences, + List problems) { string member = row.GetProperty("member").GetString()!; JsonElement provenance = row.GetProperty("provenance"); @@ -215,11 +225,12 @@ private static void CheckProvenance(JsonElement row, Dictionary ProductionSources() { return RepositoryRoot.EnumerateSourceFiles("*.cs") .Where(static file => file.StartsWith("libs/", StringComparison.Ordinal) && - !file.StartsWith(RawApiDirectory, StringComparison.Ordinal)) + !file.StartsWith(RawApiDirectory, StringComparison.Ordinal)) .Order(StringComparer.Ordinal); } } diff --git a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/ProtectedOperationCatalogTests.cs b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/ProtectedOperationCatalogTests.cs index 7196dcf2..fcae737e 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/ProtectedOperationCatalogTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/ProtectedOperationCatalogTests.cs @@ -26,7 +26,8 @@ public sealed partial class ProtectedOperationCatalogTests public void Catalog_has_its_schema_version_and_identity() { Assert.Equal(1, LuaBridgeDocuments.Catalogue.GetProperty("schemaVersion").GetInt32()); - Assert.Equal("cheatengine-sdk-lua-protected-operations", LuaBridgeDocuments.Catalogue.GetProperty("catalogId").GetString()); + Assert.Equal("cheatengine-sdk-lua-protected-operations", + LuaBridgeDocuments.Catalogue.GetProperty("catalogId").GetString()); } [Fact] @@ -53,8 +54,10 @@ public void Operation_ids_opcodes_native_enums_and_constants_are_unique_and_deri AssertUnique(operations, static operation => operation.GetProperty("id").GetString()!); AssertUnique(operations, static operation => operation.GetProperty("nativeEnum").GetString()!); - AssertUnique(operations, static operation => operation.GetProperty("managed").GetProperty("constant").GetString()!); - AssertUnique(operations, static operation => operation.GetProperty("managed").GetProperty("wrapper").GetString()!); + AssertUnique(operations, + static operation => operation.GetProperty("managed").GetProperty("constant").GetString()!); + AssertUnique(operations, + static operation => operation.GetProperty("managed").GetProperty("wrapper").GetString()!); Assert.Equal(BitmapWidth, contract.GetProperty("operationBitmapWidth").GetInt32()); Assert.Equal(string.Create(CultureInfo.InvariantCulture, $"0x{bitmap:X16}"), contract.GetProperty("operationBitmap").GetString()); @@ -79,11 +82,13 @@ public void Every_operation_has_its_native_enum_value_and_switch_case_in_the_lf_ { string name = Regex.Escape(operation.GetProperty("nativeEnum").GetString()!); int opcode = operation.GetProperty("opcode").GetInt32(); - Assert.True(Regex.IsMatch(values, $@"\b{name}\s*=\s*{opcode}\b", RegexOptions.CultureInvariant, RegexTimeout), + Assert.True( + Regex.IsMatch(values, $@"\b{name}\s*=\s*{opcode}\b", RegexOptions.CultureInvariant, RegexTimeout), $"The native enum does not define {name} = {opcode}."); Assert.True(Regex.IsMatch(source, $@"\bcase\s+{name}\s*:", RegexOptions.CultureInvariant, RegexTimeout), $"The native bridge has no case for {name}."); - Assert.True(Regex.IsMatch(mask.Groups["mask"].Value, $@"\b{name}\b", RegexOptions.CultureInvariant, RegexTimeout), + Assert.True( + Regex.IsMatch(mask.Groups["mask"].Value, $@"\b{name}\b", RegexOptions.CultureInvariant, RegexTimeout), $"The native operation mask does not name {name}."); } } @@ -118,9 +123,10 @@ public void Direct_api_policy_routes_are_exclusive_explicit_and_never_direct_for } if (policy.TryGetProperty("conditionalDirectUse", out JsonElement conditional) && - (direct || !bridge || !conditional.GetProperty("allowed").GetBoolean())) + (direct || !bridge || !conditional.GetProperty("allowed").GetBoolean())) { - problems.Add($"{symbol}: a conditional direct use keeps the bridge as its default route and opts in explicitly."); + problems.Add( + $"{symbol}: a conditional direct use keeps the bridge as its default route and opts in explicitly."); } } @@ -135,9 +141,10 @@ public void Every_raising_operation_names_a_failure_test() foreach (JsonElement operation in LuaBridgeDocuments.Operations) { string id = operation.GetProperty("id").GetString()!; - bool raises = !string.Equals(operation.GetProperty("raises").GetString(), "never", StringComparison.Ordinal); + bool raises = !string.Equals(operation.GetProperty("raises").GetString(), "never", + StringComparison.Ordinal); if (raises && (!operation.TryGetProperty("failureEvidence", out JsonElement evidence) || - evidence.GetArrayLength() == 0)) + evidence.GetArrayLength() == 0)) { problems.Add($"{id} can raise but names no failure evidence (a failure-probe marker or a Q13 test)."); } @@ -170,7 +177,8 @@ public void Managed_failure_evidence_resolves_to_a_Q13_traited_method() public void Probe_marker_evidence_is_emitted_by_the_failure_probe_source() { string probe = RepositoryDocument.ReadNormalizedText(LuaBridgeDocuments.FailureProbePath); - string[] markers = [.. Evidence(ProbeMarkerKind).Select(static item => item.GetProperty("marker").GetString()!)]; + string[] markers = + [.. Evidence(ProbeMarkerKind).Select(static item => item.GetProperty("marker").GetString()!)]; Assert.NotEmpty(markers); Assert.Equal(markers.Length, markers.Distinct(StringComparer.Ordinal).Count()); @@ -199,8 +207,10 @@ public void Retired_live_ids_are_absent() } JsonElement pusher = Assert.Single(LuaBridgeDocuments.Operations, - static operation => string.Equals(operation.GetProperty("id").GetString(), "PushHostObject", StringComparison.Ordinal)); - Assert.Contains("Q23", pusher.GetProperty("provenance")[0].GetProperty("verification").GetString(), StringComparison.Ordinal); + static operation => string.Equals(operation.GetProperty("id").GetString(), "PushHostObject", + StringComparison.Ordinal)); + Assert.Contains("Q23", pusher.GetProperty("provenance")[0].GetProperty("verification").GetString(), + StringComparison.Ordinal); Assert.Contains("Q23", RepositoryDocument.ReadNormalizedText("libs/CheatEngine.SDK.Lua.Interop/README.md"), StringComparison.Ordinal); } @@ -226,20 +236,24 @@ private static IEnumerable Evidence(string kind) private static void AssertUnique(JsonElement[] items, Func key) { - string[] duplicates = [.. items.GroupBy(key, StringComparer.Ordinal).Where(static group => group.Count() > 1) - .Select(static group => group.Key)]; + string[] duplicates = + [ + .. items.GroupBy(key, StringComparer.Ordinal).Where(static group => group.Count() > 1) + .Select(static group => group.Key) + ]; Assert.True(duplicates.Length == 0, "Duplicated: " + string.Join(", ", duplicates)); } - [GeneratedRegex(@"enum\s*\{\s*(?OP_PUSH_BYTES\s*=\s*0,[\s\S]*?CHEATENGINE_SDK_LUA_BRIDGE_OPERATION_COUNT\s*=\s*\d+)\s*\};", - RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex( + @"enum\s*\{\s*(?OP_PUSH_BYTES\s*=\s*0,[\s\S]*?CHEATENGINE_SDK_LUA_BRIDGE_OPERATION_COUNT\s*=\s*\d+)\s*\};", + RegexOptions.CultureInvariant, 1000)] private static partial Regex NativeOperationEnum(); [GeneratedRegex(@"CHEATENGINE_SDK_LUA_BRIDGE_OPERATION_COUNT\s*=\s*(?\d+)", RegexOptions.CultureInvariant, - matchTimeoutMilliseconds: 1000)] + 1000)] private static partial Regex OperationCount(); [GeneratedRegex(@"#define\s+CHEATENGINE_SDK_LUA_BRIDGE_OPERATION_MASK\s*\\(?[\s\S]*?)\n\s*\n", - RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + RegexOptions.CultureInvariant, 1000)] private static partial Regex OperationMask(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Ownership/OwnershipPolicyTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Ownership/OwnershipPolicyTests.cs index 83587689..c27e7b55 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Ownership/OwnershipPolicyTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Ownership/OwnershipPolicyTests.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Text.RegularExpressions; using CheatEngine.SDK.Repository.Tests.Infrastructure; @@ -39,19 +40,20 @@ public void No_shipping_library_binds_delete_all_registered_symbols() foreach (string file in RepositoryRoot.EnumerateSourceFiles("*")) { bool shippingCode = (file.StartsWith("libs/", StringComparison.Ordinal) || - file.StartsWith("src/", StringComparison.Ordinal)) && - file.EndsWith(".cs", StringComparison.Ordinal); + file.StartsWith("src/", StringComparison.Ordinal)) && + file.EndsWith(".cs", StringComparison.Ordinal); bool generatorSpec = file.StartsWith("source-generators/", StringComparison.Ordinal) && - file.Contains("/Specs/", StringComparison.Ordinal); + file.Contains("/Specs/", StringComparison.Ordinal); if ((shippingCode || generatorSpec) && - File.ReadAllText(Absolute(file)).Contains(DeleteAllRegisteredSymbols, StringComparison.Ordinal)) + File.ReadAllText(Absolute(file)).Contains(DeleteAllRegisteredSymbols, StringComparison.Ordinal)) { offenders.Add(file); } } Assert.True(offenders.Count == 0, - DeleteAllRegisteredSymbols + " removes every plugin's and script's symbols; bind per-plugin cleanup instead: " + + DeleteAllRegisteredSymbols + + " removes every plugin's and script's symbols; bind per-plugin cleanup instead: " + string.Join(", ", offenders)); } @@ -98,7 +100,7 @@ private static List FindFinalizers(string file, string[] lines) if (FinalizerDeclaration.IsMatch(line)) { - hits.Add(file + ":" + (index + 1).ToString(System.Globalization.CultureInfo.InvariantCulture)); + hits.Add(file + ":" + (index + 1).ToString(CultureInfo.InvariantCulture)); } } diff --git a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/EnumContractTests.cs b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/EnumContractTests.cs index 8b15f7a4..eeb907a4 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/EnumContractTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/EnumContractTests.cs @@ -80,14 +80,20 @@ public sealed class EnumContractTests /// declared through CompatibilitySuppressions.xml when the enum shipped, and a PublicAPI change). The list only /// shrinks: fails once an entry is fixed. /// - private static readonly Dictionary s_pendingZeroValueFixes = new(StringComparer.Ordinal) - { - }; + private static readonly Dictionary s_pendingZeroValueFixes = new(StringComparer.Ordinal); /// Zero-member names that read as "it worked" (or, for a failure-kind enum, "no failure"). private static readonly HashSet s_successLikeNames = new(StringComparer.Ordinal) { - "Complete", "Completed", "Done", "None", "Ok", "Released", "Succeeded", "Success", "Successful" + "Complete", + "Completed", + "Done", + "None", + "Ok", + "Released", + "Succeeded", + "Success", + "Successful" }; /// @@ -99,15 +105,6 @@ public sealed class EnumContractTests "Unknown", "Unspecified", "Uninitialized", "NotAttempted" }; - private enum EnumCategory - { - Unknown = 0, - StatusOrOutcome, - Policy, - ReasonOrEvidence, - AbiDecision - } - [Fact] public void Enums_mirroring_cheat_engine_constants_or_client_signatures_keep_their_1_0_0_members() { @@ -128,7 +125,7 @@ public void Enums_mirroring_cheat_engine_constants_or_client_signatures_keep_the foreach (string added in library.Added) { if (IsMemberOfFrozenEnum(added, out string enumType) - && PublicApiDeclarations.TryParseEnumMember(added, out _, out string member, out _)) + && PublicApiDeclarations.TryParseEnumMember(added, out _, out string member, out _)) { Assert.True(s_reviewedFrozenEnumAdditions.Contains($"{enumType}.{member}"), $"{library.UnshippedPath}: '{added}' adds a member to the frozen enum {enumType} without a reviewed entry."); @@ -168,7 +165,8 @@ public void Status_and_outcome_enums_added_after_1_0_0_do_not_default_to_success } string? zero = ZeroMember(declared[enumType]); - Assert.True(zero is not null, $"{enumType} has no member with value 0, so default({SimpleName(enumType)}) has no name."); + Assert.True(zero is not null, + $"{enumType} has no member with value 0, so default({SimpleName(enumType)}) has no name."); Assert.False(s_successLikeNames.Contains(zero), $"{enumType}.{zero} = 0 reads as success."); Assert.True(s_neutralZeroNames.Contains(zero), $"{enumType}.{zero} = 0: a status/outcome enum starts with Unknown = 0 (tolerated: {string.Join(", ", s_neutralZeroNames)})."); @@ -181,10 +179,14 @@ public void Pending_zero_value_fixes_are_still_needed() Dictionary> declared = EnumMembers(static l => l.Declared); foreach ((string enumType, string owner) in s_pendingZeroValueFixes) { - Assert.True(s_addedEnums.TryGetValue(enumType, out EnumCategory category) && category == EnumCategory.StatusOrOutcome, + Assert.True( + s_addedEnums.TryGetValue(enumType, out EnumCategory category) && + category == EnumCategory.StatusOrOutcome, $"{enumType} is pending but not classified as {EnumCategory.StatusOrOutcome}."); Assert.False(string.IsNullOrWhiteSpace(owner)); - string? zero = declared.TryGetValue(enumType, out SortedDictionary? members) ? ZeroMember(members) : null; + string? zero = declared.TryGetValue(enumType, out SortedDictionary? members) + ? ZeroMember(members) + : null; Assert.True(zero is not null && s_successLikeNames.Contains(zero), $"{enumType} no longer starts with a success-like member ({zero ?? "no zero member"}): {owner} fixed it, so remove it from {nameof(s_pendingZeroValueFixes)}."); } @@ -209,7 +211,8 @@ private static Dictionary> EnumMembers( { foreach (string line in lines(library)) { - if (PublicApiDeclarations.TryParseEnumMember(line, out string enumType, out string member, out long value)) + if (PublicApiDeclarations.TryParseEnumMember(line, out string enumType, out string member, + out long value)) { if (!enums.TryGetValue(enumType, out SortedDictionary? members)) { @@ -242,4 +245,13 @@ private static string SimpleName(string typeName) { return typeName[(typeName.LastIndexOf('.') + 1)..]; } + + private enum EnumCategory + { + Unknown = 0, + StatusOrOutcome, + Policy, + ReasonOrEvidence, + AbiDecision + } } diff --git a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiDeclarations.cs b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiDeclarations.cs index 3c431de0..ddfea00a 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiDeclarations.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiDeclarations.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Text; using System.Text.RegularExpressions; @@ -89,7 +90,7 @@ public static IReadOnlySet CandidateKeysOf(string docId) keys.Add($"{type}.{SimpleName(type)}"); break; case 'M' when member.StartsWith("get_", StringComparison.Ordinal) - || member.StartsWith("set_", StringComparison.Ordinal): + || member.StartsWith("set_", StringComparison.Ordinal): AddPropertyKeys(keys, type, accessorName); break; case 'M' when member.StartsWith("add_", StringComparison.Ordinal): @@ -140,7 +141,7 @@ public static bool TryParseEnumMember(string line, out string enumType, out stri enumType = match.Groups["type"].Value; member = match.Groups["member"].Value; - value = long.Parse(match.Groups["value"].Value, System.Globalization.CultureInfo.InvariantCulture); + value = long.Parse(match.Groups["value"].Value, CultureInfo.InvariantCulture); return true; } @@ -185,10 +186,10 @@ private static string SimpleName(string type) return type[(type.LastIndexOf('.') + 1)..]; } - [GeneratedRegex(@"`+\d+", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"`+\d+", RegexOptions.CultureInvariant, 1000)] private static partial Regex GenericArity(); [GeneratedRegex(@"^(?[\w.]+)\.(?\w+) = (?-?\d+) -> \k$", RegexOptions.CultureInvariant, - matchTimeoutMilliseconds: 1000)] + 1000)] private static partial Regex EnumMemberLine(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiLibrary.cs b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiLibrary.cs index 7ad821fd..f7b66036 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiLibrary.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiLibrary.cs @@ -113,7 +113,7 @@ public static IReadOnlyList LoadAll() foreach (string directory in EnumerateLibraryDirectories()) { if (File.Exists(FullPath($"{directory}/{ShippedFileName}")) - && File.Exists(FullPath($"{directory}/{UnshippedFileName}"))) + && File.Exists(FullPath($"{directory}/{UnshippedFileName}"))) { libraries.Add(new PublicApiLibrary(directory)); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/README.md b/tests/CheatEngine.SDK.Repository.Tests/README.md index 64b32a5e..8c7f97a1 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/README.md +++ b/tests/CheatEngine.SDK.Repository.Tests/README.md @@ -14,21 +14,21 @@ workflow's own "submit" step text against a mocked `gh`, offline. ## How it works -| Folder | Content | -|--------------------|--------------------------------------------------------------------------------------------------------| -| `Infrastructure/` | `RepositoryRoot` finds `CheatEngine.SDK.slnx` above the test binaries and enumerates source files. | -| `Solution/` | `SolutionInventoryTests` compares the projects on disk with the projects listed in the solution; `QualificationHarnessShapeTests` checks the shape of the two qualification-harness projects. | -| `Toolchain/` | `ToolchainPinTests` reads `global.json`, `Directory.Build.props` and `Directory.Solution.targets`: exact SDK, analysis-level pin, NuGet audit policy. | -| `LockFiles/` | `LockFileTests` mirror the structural checks a locked restore relies on, over the committed `packages.lock.json` files. | -| `PublicApi/` | `PublicApiFileTests` and `EnumContractTests` check the shape of every shipping library's PublicAPI files and the classification of enums added since 1.0.0. | -| `Abi/` | `ClassicSlotRegistryDocumentTests` checks the committed classic slot registry `Abi/TestData/classic-slot-registry.json` (test-owned data, never a top-level `docs/` folder); `NativeAotProfileDocumentTests` checks the NativeAOT restrictions published in `libs/CheatEngine.SDK.Abi/README.md`; `AbiRouteSeparationTests` keeps the managed and classic exported-function tables apart in `libs/**`. | -| `SourceScanning/` | `CSharpCode` blanks the comments and literals of C# source read as text, and `TestMethodTraits` reads the `[Trait("Qualification", …)]` attributes above a named test method, both for the rules in `Abi/` and `LuaBridge/`. | -| `LuaBridge/` | `ProtectedOperationCatalogTests` checks `libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json` against the LF-pinned C bridge source and the failure probe; `LuaInteropPrimitiveMatrixDocumentTests` checks the committed primitive matrix `LuaBridge/TestData/lua-interop-primitives.json` and the raw `LuaApi` uses of `libs/**`. | -| `Workflows/` | `WorkflowContractTests` parse `.github/workflows/*.yml` and the composite actions with YamlDotNet and freeze the CI contract (job ids, the Gate, lint, format, restore, supply-chain jobs). | -| `Release/` | `ReleaseWorkflowContractTests` reads `.github/workflows/release.yml`: the draft-first job chain, tag guards, write scopes, trusted publishing placement and the reserved artifact names. | -| `Governance/` | `GovernanceWorkflowTests` freeze CodeQL, Scorecard, the online zizmor run and dependency submission; `DependabotConfigurationTests` checks `.github/dependabot.yml`; `GovernanceDocumentTests` checks `SECURITY.md`, `CODE_OF_CONDUCT.md`, `.github/CODEOWNERS` and the issue forms. | -| `Generation/` | `GeneratorInventoryTests` pins the reviewed source generator projects, keeps the extended analyzer rules on every Roslyn component and refuses a local Cheat Engine path in their sources. | -| `Ownership/` | `OwnershipPolicyTests` scans the shipping sources: no finalizer, and no binding of Cheat Engine's global that deletes every registered symbol. | +| Folder | Content | +|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Infrastructure/` | `RepositoryRoot` finds `CheatEngine.SDK.slnx` above the test binaries and enumerates source files. | +| `Solution/` | `SolutionInventoryTests` compares the projects on disk with the projects listed in the solution; `QualificationHarnessShapeTests` checks the shape of the two qualification-harness projects. | +| `Toolchain/` | `ToolchainPinTests` reads `global.json`, `Directory.Build.props` and `Directory.Solution.targets`: exact SDK, analysis-level pin, NuGet audit policy. | +| `LockFiles/` | `LockFileTests` mirror the structural checks a locked restore relies on, over the committed `packages.lock.json` files. | +| `PublicApi/` | `PublicApiFileTests` and `EnumContractTests` check the shape of every shipping library's PublicAPI files and the classification of enums added since 1.0.0. | +| `Abi/` | `ClassicSlotRegistryDocumentTests` checks the committed classic slot registry `Abi/TestData/classic-slot-registry.json` (test-owned data, never a top-level `docs/` folder); `NativeAotProfileDocumentTests` checks the NativeAOT restrictions published in `libs/CheatEngine.SDK.Abi/README.md`; `AbiRouteSeparationTests` keeps the managed and classic exported-function tables apart in `libs/**`. | +| `SourceScanning/` | `CSharpCode` blanks the comments and literals of C# source read as text, and `TestMethodTraits` reads the `[Trait("Qualification", …)]` attributes above a named test method, both for the rules in `Abi/` and `LuaBridge/`. | +| `LuaBridge/` | `ProtectedOperationCatalogTests` checks `libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json` against the LF-pinned C bridge source and the failure probe; `LuaInteropPrimitiveMatrixDocumentTests` checks the committed primitive matrix `LuaBridge/TestData/lua-interop-primitives.json` and the raw `LuaApi` uses of `libs/**`. | +| `Workflows/` | `WorkflowContractTests` parse `.github/workflows/*.yml` and the composite actions with YamlDotNet and freeze the CI contract (job ids, the Gate, lint, format, restore, supply-chain jobs). | +| `Release/` | `ReleaseWorkflowContractTests` reads `.github/workflows/release.yml`: the draft-first job chain, tag guards, write scopes, trusted publishing placement and the reserved artifact names. | +| `Governance/` | `GovernanceWorkflowTests` freeze CodeQL, Scorecard, the online zizmor run and dependency submission; `DependabotConfigurationTests` checks `.github/dependabot.yml`; `GovernanceDocumentTests` checks `SECURITY.md`, `CODE_OF_CONDUCT.md`, `.github/CODEOWNERS` and the issue forms. | +| `Generation/` | `GeneratorInventoryTests` pins the reviewed source generator projects, keeps the extended analyzer rules on every Roslyn component and refuses a local Cheat Engine path in their sources. | +| `Ownership/` | `OwnershipPolicyTests` scans the shipping sources: no finalizer, and no binding of Cheat Engine's global that deletes every registered symbol. | ## Promise @@ -59,8 +59,8 @@ workflow's own "submit" step text against a mocked `gh`, offline. `Every_enum_added_after_1_0_0_is_classified`, `Status_and_outcome_enums_added_after_1_0_0_do_not_default_to_success`, `Pending_zero_value_fixes_are_still_needed`). - Every project, inside or outside the solution, has a lock file in NuGet's version 2 format, ending as NuGet writes it; - Native AOT projects lock their runtime-specific ILCompiler package; no lock resolves a CheatEngine.* package from a feed - (`Every_project_has_a_committed_lock_file`, `Lock_files_parse_and_declare_a_supported_format_version`, + Native AOT projects lock their runtime-specific ILCompiler package; no lock resolves a CheatEngine.* package from a + feed (`Every_project_has_a_committed_lock_file`, `Lock_files_parse_and_declare_a_supported_format_version`, `Every_lock_file_is_version_2_because_every_project_uses_central_package_management`, `Version_1_lock_files_hold_no_central_transitive_entries`, `Native_aot_projects_lock_the_win_x64_ilcompiler_packages`, `No_lock_file_resolves_a_cheatengine_package`, `Lock_files_end_without_a_final_newline_as_nuget_writes_them`). @@ -77,27 +77,34 @@ workflow's own "submit" step text against a mocked `gh`, offline. `Pull_request_and_main_callers_request_sonar_and_the_release_run_never_does`). - No workflow listens to `pull_request_target` or `merge_group`, the pull-request workflow filters no path, main keeps every run and pull requests cancel superseded ones - (`No_workflow_uses_pull_request_target_or_a_merge_group_trigger`, `Pull_request_and_policy_workflows_have_no_path_filters`, - `Main_ci_runs_every_push_to_main_without_a_concurrency_group`, `Pull_request_ci_skips_drafts_and_cancels_superseded_runs`). + (`No_workflow_uses_pull_request_target_or_a_merge_group_trigger`, + `Pull_request_and_policy_workflows_have_no_path_filters`, + `Main_ci_runs_every_push_to_main_without_a_concurrency_group`, + `Pull_request_ci_skips_drafts_and_cancels_superseded_runs`). - Every job runs on `windows-2025` or `ubuntu-24.04` with a timeout, workflows grant read permissions only at the top - level and the pipeline never elevates, every remote action is pinned to a commit with its version, every checkout drops + level and the pipeline never elevates, every remote action is pinned to a commit with its version, every checkout + drops its credentials, every native command checks its exit code, no run script interpolates an expression, and the pipeline scripts run in `pwsh` (`Every_job_has_a_timeout_and_a_pinned_runner_label`, `Workflows_grant_only_read_permissions_at_the_top_level`, `Pipeline_jobs_never_elevate_permissions`, - `Every_remote_action_is_pinned_to_a_full_sha_with_a_version_comment`, `Every_checkout_disables_credential_persistence`, + `Every_remote_action_is_pinned_to_a_full_sha_with_a_version_comment`, + `Every_checkout_disables_credential_persistence`, `Every_native_command_in_a_workflow_script_checks_its_exit_code`, `No_run_script_interpolates_an_expression`, `Pipeline_workflows_and_composite_actions_run_scripts_in_pwsh`). - Every dotnet job installs the pinned SDK through the composite action, every restore is locked, and no job reachable from a release, Sonar or CodeQL run uses a package cache (`Every_dotnet_job_uses_the_composite_setup_action`, `Composite_setup_restores_in_locked_mode`, `Every_restore_in_the_pipeline_is_locked`, - `Release_reachable_workflows_never_enable_a_package_cache`, `Sonar_restores_locked_from_nuget_org_before_the_scanner_begins`). + `Release_reachable_workflows_never_enable_a_package_cache`, + `Sonar_restores_locked_from_nuget_org_before_the_scanner_begins`). - The Release leg packs before it tests and hands the exact nupkg to the packaging tests, with an inlined pre-publish sanity check (one package, its nuspec identity, the embedded SBOM and the CI-built native bridge); the Debug leg excludes packaging tests by trait, never by skip; every module runs once with hang and crash dumps well inside the job timeout (`Release_leg_packs_before_testing_and_exports_the_exact_nupkg`, - `Debug_leg_excludes_packaging_tests_by_trait_never_by_skip`, `Test_step_runs_every_module_once_with_the_contract_options`, + `Debug_leg_excludes_packaging_tests_by_trait_never_by_skip`, + `Test_step_runs_every_module_once_with_the_contract_options`, `Every_test_module_references_the_extensions_the_test_step_uses`, - `Hang_dump_timeout_is_well_below_the_build_test_job_timeout`, `Build_test_runs_both_configurations_without_fail_fast`). + `Hang_dump_timeout_is_well_below_the_build_test_job_timeout`, + `Build_test_runs_both_configurations_without_fail_fast`). - Artifacts use the reserved names and retentions only, binary logs and dumps are uploaded on failure only and never from Sonar or release runs, jobs that version a package fetch full history, the Native AOT probes are published, and the live probe is compiled exactly once and never shipped (`Every_uploaded_artifact_name_is_reserved`, @@ -115,7 +122,8 @@ workflow's own "submit" step text against a mocked `gh`, offline. - No workflow runs a local qualification runner or generates ApiCompat suppressions (`No_workflow_references_the_local_qualification_runner`, `No_workflow_passes_ApiCompatGenerateSuppressionFile`). - The release workflow is draft-first (`verify → ci → attest → draft-release → publish → verify-publication → - finalize-release`), runs for `v*.*.*` tags and manual dry runs without cancelling a run in progress, and calls `ci.yml` + finalize-release`), runs for `v*.*.*` tags and manual dry runs without cancelling a run in progress, and calls + `ci.yml` with the tag version, a 90-day retention and no Sonar (`Release_jobs_form_the_draft_first_chain`, `Release_runs_for_version_tags_and_manual_dry_runs_without_cancelling`, `Release_calls_ci_with_the_tag_version_ninety_day_retention_and_no_sonar`). diff --git a/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflow.cs b/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflow.cs index ba38e34c..db2e8352 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflow.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflow.cs @@ -154,13 +154,17 @@ public static string Normalize(string? value) /// A child mapping, or null. public static YamlMappingNode? Mapping(YamlMappingNode node, string key) { - return node.Children.TryGetValue(new YamlScalarNode(key), out YamlNode? value) ? value as YamlMappingNode : null; + return node.Children.TryGetValue(new YamlScalarNode(key), out YamlNode? value) + ? value as YamlMappingNode + : null; } /// A child sequence, or null. public static YamlSequenceNode? Sequence(YamlMappingNode node, string key) { - return node.Children.TryGetValue(new YamlScalarNode(key), out YamlNode? value) ? value as YamlSequenceNode : null; + return node.Children.TryGetValue(new YamlScalarNode(key), out YamlNode? value) + ? value as YamlSequenceNode + : null; } /// The keys of a mapping, in order. @@ -187,6 +191,6 @@ public static List ScalarValues(YamlSequenceNode sequence) return values; } - [GeneratedRegex(@"\s+", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"\s+", RegexOptions.CultureInvariant, 1000)] private static partial Regex Whitespace(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflowContractTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflowContractTests.cs index 048717fb..ba5a4531 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflowContractTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflowContractTests.cs @@ -6,8 +6,12 @@ namespace CheatEngine.SDK.Repository.Tests.Release; /// /// The release workflow is draft-first and compatible with immutable releases (shared contract 1.11, audit ch.21 -/// "Le tuple a qualifier", Checkpoint F): verify → ci → attest → draft-release → publish → verify-publication → -/// finalize-release. Attestations and every asset exist before the draft is published, publication jobs run only +/// "Le tuple a qualifier", Checkpoint F): +/// +/// verify → ci → attest → draft-release → publish → verify-publication → +/// finalize-release +/// +/// . Attestations and every asset exist before the draft is published, publication jobs run only /// for version tags of this repository, the only write tokens live in the jobs that need them, NuGet trusted /// publishing stays in the publish job with environment nuget, and nothing is ever uploaded to a /// published release. These tests read the committed YAML only. @@ -31,9 +35,11 @@ private static readonly (string Id, string Name, string[] Needs)[] s_chain = ("finalize-release", "Publish GitHub release", ["verify", "attest", "verify-publication"]) ]; - private static readonly string[] s_publicationJobs = ["draft-release", "publish", "verify-publication", "finalize-release"]; + private static readonly string[] s_publicationJobs = + ["draft-release", "publish", "verify-publication", "finalize-release"]; - private static readonly HashSet s_runnerLabels = new(StringComparer.Ordinal) { "windows-2025", "ubuntu-24.04" }; + private static readonly HashSet s_runnerLabels = + new(StringComparer.Ordinal) { "windows-2025", "ubuntu-24.04" }; [Fact] public void Release_runs_for_version_tags_and_manual_dry_runs_without_cancelling() @@ -50,7 +56,8 @@ public void Release_runs_for_version_tags_and_manual_dry_runs_without_cancelling YamlMappingNode concurrency = ReleaseWorkflow.Mapping(workflow.Root, "concurrency")!; Assert.Equal("${{ github.workflow }}-${{ github.ref }}", ReleaseWorkflow.Scalar(concurrency, "group")); Assert.Equal("false", ReleaseWorkflow.Scalar(concurrency, "cancel-in-progress")); - Assert.Equal("read", ReleaseWorkflow.Scalar(ReleaseWorkflow.Mapping(workflow.Root, "permissions")!, "contents")); + Assert.Equal("read", + ReleaseWorkflow.Scalar(ReleaseWorkflow.Mapping(workflow.Root, "permissions")!, "contents")); Assert.Single(ReleaseWorkflow.Keys(ReleaseWorkflow.Mapping(workflow.Root, "permissions")!)); } @@ -78,11 +85,13 @@ public void Publication_jobs_run_only_for_tags_of_this_repository() string guard = ReleaseWorkflow.Normalize(ReleaseWorkflow.Scalar(workflow.Job(id), "if")); if (s_publicationJobs.Contains(id, StringComparer.Ordinal)) { - Assert.True(string.Equals(TagGuard, guard, StringComparison.Ordinal), $"Job '{id}' must run only when '{TagGuard}', not '{guard}'."); + Assert.True(string.Equals(TagGuard, guard, StringComparison.Ordinal), + $"Job '{id}' must run only when '{TagGuard}', not '{guard}'."); } else { - Assert.True(guard.Length == 0, $"Job '{id}' runs on dry runs too and must not be conditional ('{guard}')."); + Assert.True(guard.Length == 0, + $"Job '{id}' runs on dry runs too and must not be conditional ('{guard}')."); } } @@ -93,7 +102,8 @@ public void Publication_jobs_run_only_for_tags_of_this_repository() foreach (YamlMappingNode step in ReleaseWorkflow.Steps(attest)) { bool signsOrVerifies = attestations.Contains(step) - || (ReleaseWorkflow.Scalar(step, "run") ?? "").Contains("gh attestation verify", StringComparison.Ordinal); + || (ReleaseWorkflow.Scalar(step, "run") ?? "").Contains("gh attestation verify", + StringComparison.Ordinal); if (signsOrVerifies) { Assert.Equal(TagGuard, ReleaseWorkflow.Normalize(ReleaseWorkflow.Scalar(step, "if"))); @@ -132,13 +142,16 @@ public void Only_the_publish_job_uses_the_nuget_environment_and_nuget_login() { YamlMappingNode job = workflow.Job(id); bool isPublish = string.Equals(id, "publish", StringComparison.Ordinal); - YamlNode? environment = job.Children.TryGetValue(new YamlScalarNode("environment"), out YamlNode? value) ? value : null; + YamlNode? environment = job.Children.TryGetValue(new YamlScalarNode("environment"), out YamlNode? value) + ? value + : null; List logins = ReleaseWorkflow.StepsUsing(job, "NuGet/login@"); bool pushes = ReleaseWorkflow.RunText(job).Contains("dotnet nuget push", StringComparison.Ordinal); if (!isPublish) { Assert.True(environment is null, $"Job '{id}' uses an environment; only 'publish' may use 'nuget'."); - Assert.True(logins.Count == 0 && !pushes, $"Job '{id}' logs in to or pushes to NuGet; only 'publish' may."); + Assert.True(logins.Count == 0 && !pushes, + $"Job '{id}' logs in to or pushes to NuGet; only 'publish' may."); continue; } @@ -150,7 +163,8 @@ public void Only_the_publish_job_uses_the_nuget_environment_and_nuget_login() List steps = ReleaseWorkflow.Steps(job); int loginIndex = steps.IndexOf(login); Assert.True(loginIndex + 1 < steps.Count, "The NuGet login must be followed by the push."); - Assert.Contains("dotnet nuget push", ReleaseWorkflow.Scalar(steps[loginIndex + 1], "run") ?? "", StringComparison.Ordinal); + Assert.Contains("dotnet nuget push", ReleaseWorkflow.Scalar(steps[loginIndex + 1], "run") ?? "", + StringComparison.Ordinal); Assert.Equal("${{ steps.login.outputs.NUGET_API_KEY }}", ReleaseWorkflow.Scalar(ReleaseWorkflow.Mapping(steps[loginIndex + 1], "env")!, "NUGET_API_KEY")); } @@ -176,7 +190,9 @@ public void Contents_write_is_limited_to_draft_release_and_finalize_release() { foreach ((string scope, string value) in ReleaseWorkflow.Permissions(workflow.Job(id))) { - Assert.True(!string.Equals(value, "write", StringComparison.Ordinal) || scope is "contents" or "id-token" or "attestations", + Assert.True( + !string.Equals(value, "write", StringComparison.Ordinal) || + scope is "contents" or "id-token" or "attestations", $"Job '{id}' grants '{scope}: write'."); } } @@ -192,12 +208,16 @@ public void Release_is_created_as_a_draft_and_published_only_by_finalize() string run = ReleaseWorkflow.RunText(workflow.Job(id)); bool creates = run.Contains("gh release create", StringComparison.Ordinal); bool edits = run.Contains("gh release edit", StringComparison.Ordinal); - bool clobbers = run.Contains("--clobber", StringComparison.Ordinal) && run.Contains("gh release upload", StringComparison.Ordinal); + bool clobbers = run.Contains("--clobber", StringComparison.Ordinal) && + run.Contains("gh release upload", StringComparison.Ordinal); bool publishes = run.Contains("--draft=false", StringComparison.Ordinal); Assert.True(!creates || id is "draft-release", $"Job '{id}' creates a release; only 'draft-release' may."); - Assert.True(!edits || id is "finalize-release", $"Job '{id}' edits a release; only 'finalize-release' may."); - Assert.True(!publishes || id is "finalize-release", $"Job '{id}' publishes the release; only 'finalize-release' may."); - Assert.True(!clobbers || id is "draft-release" or "finalize-release", $"Job '{id}' replaces a release asset."); + Assert.True(!edits || id is "finalize-release", + $"Job '{id}' edits a release; only 'finalize-release' may."); + Assert.True(!publishes || id is "finalize-release", + $"Job '{id}' publishes the release; only 'finalize-release' may."); + Assert.True(!clobbers || id is "draft-release" or "finalize-release", + $"Job '{id}' replaces a release asset."); Assert.DoesNotContain("gh release delete", run, StringComparison.Ordinal); } @@ -216,8 +236,10 @@ public void Release_is_created_as_a_draft_and_published_only_by_finalize() // Publishing runs only while the release is still a draft. YamlMappingNode publishStep = Assert.Single(ReleaseWorkflow.Steps(workflow.Job("finalize-release")), - static step => (ReleaseWorkflow.Scalar(step, "run") ?? "").Contains("--draft=false", StringComparison.Ordinal)); - Assert.Equal("steps.state.outputs.draft == 'true'", ReleaseWorkflow.Normalize(ReleaseWorkflow.Scalar(publishStep, "if"))); + static step => + (ReleaseWorkflow.Scalar(step, "run") ?? "").Contains("--draft=false", StringComparison.Ordinal)); + Assert.Equal("steps.state.outputs.draft == 'true'", + ReleaseWorkflow.Normalize(ReleaseWorkflow.Scalar(publishStep, "if"))); } [Fact] @@ -238,7 +260,9 @@ public void Publication_is_verified_on_nuget_org_before_the_release_is_published // The publish job pushes only the file SHA256SUMS of the draft lists. string publish = ReleaseWorkflow.RunText(workflow.Job("publish")); - Assert.True(publish.IndexOf("SHA256SUMS", StringComparison.Ordinal) < publish.IndexOf("dotnet nuget push", StringComparison.Ordinal), + Assert.True( + publish.IndexOf("SHA256SUMS", StringComparison.Ordinal) < + publish.IndexOf("dotnet nuget push", StringComparison.Ordinal), "The publish job must check the package against SHA256SUMS before pushing it."); } @@ -271,8 +295,9 @@ public void Release_jobs_have_a_timeout_and_a_pinned_runner() string? runsOn = ReleaseWorkflow.Scalar(job, "runs-on"); Assert.True(runsOn is not null && s_runnerLabels.Contains(runsOn), $"Job '{id}' runs on '{runsOn}'."); - Assert.True(int.TryParse(ReleaseWorkflow.Scalar(job, "timeout-minutes"), NumberStyles.None, CultureInfo.InvariantCulture, out int minutes) - && minutes is > 0 and <= 60, + Assert.True(int.TryParse(ReleaseWorkflow.Scalar(job, "timeout-minutes"), NumberStyles.None, + CultureInfo.InvariantCulture, out int minutes) + && minutes is > 0 and <= 60, $"Job '{id}' needs a timeout-minutes between 1 and 60."); } } @@ -295,7 +320,8 @@ public void Release_uploads_only_reserved_artifact_names() // The nupkg travels only in ci.yml's nuget-package artifact: attestation-bundles never carries a second copy. Assert.Equal(["release-notes", "attestation-bundles"], uploaded); - YamlMappingNode bundles = Assert.Single(ReleaseWorkflow.StepsUsing(workflow.Job("attest"), "actions/upload-artifact@")); + YamlMappingNode bundles = + Assert.Single(ReleaseWorkflow.StepsUsing(workflow.Job("attest"), "actions/upload-artifact@")); Assert.Contains("!artifacts/release/*.nupkg", ReleaseWorkflow.With(bundles, "path"), StringComparison.Ordinal); } @@ -310,7 +336,8 @@ public void Release_jobs_that_run_dotnet_install_the_pinned_sdk_and_never_cache_ Assert.Empty(ReleaseWorkflow.StepsUsing(job, "actions/cache")); foreach (YamlMappingNode setup in ReleaseWorkflow.StepsUsing(job, "./.github/actions/setup-dotnet")) { - Assert.True(ReleaseWorkflow.With(setup, "cache") is null or "false", $"Job '{id}' enables a package cache."); + Assert.True(ReleaseWorkflow.With(setup, "cache") is null or "false", + $"Job '{id}' enables a package cache."); } bool needsDotnet = id is "publish" or "verify-publication"; @@ -336,7 +363,7 @@ private static void AssertWriteScope(string scope, string[] allowed) foreach (string id in Ids()) { if (ReleaseWorkflow.Permissions(workflow.Job(id)).TryGetValue(scope, out string? value) - && string.Equals(value, "write", StringComparison.Ordinal)) + && string.Equals(value, "write", StringComparison.Ordinal)) { granted.Add(id); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Runtime/RuntimeCapabilitySpecTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Runtime/RuntimeCapabilitySpecTests.cs index d56429f6..6bab619b 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Runtime/RuntimeCapabilitySpecTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Runtime/RuntimeCapabilitySpecTests.cs @@ -27,8 +27,17 @@ public sealed partial class RuntimeCapabilitySpecTests /// private static readonly SortedSet s_readOnlyGlobals = new(StringComparer.Ordinal) { - "getCEVersion", "isConnectedToCEServer", "targetIs64Bit", "targetIsX86", "targetIsArm", "targetIsAndroid", - "getABI", "getPointerSize", "getCheatEngineFileVersion", "getSystemArchitecture", "cheatEngineIs64Bit", + "getCEVersion", + "isConnectedToCEServer", + "targetIs64Bit", + "targetIsX86", + "targetIsArm", + "targetIsAndroid", + "getABI", + "getPointerSize", + "getCheatEngineFileVersion", + "getSystemArchitecture", + "cheatEngineIs64Bit", "getOperatingSystem" }; @@ -113,12 +122,15 @@ public void target_backend_members_are_the_readme_backend_rows_and_only_local_pr SortedSet rows = new(StringComparer.Ordinal); List qualified = []; - foreach (string[] cells in BackendTableRows(File.ReadAllLines(Path.Combine(RepositoryRoot.Path, EngineReadmePath)))) + foreach (string[] cells in BackendTableRows( + File.ReadAllLines(Path.Combine(RepositoryRoot.Path, EngineReadmePath)))) { string backend = cells[0].Trim('`'); Assert.True(rows.Add(backend), $"Duplicate backend row {backend}."); string verdict = cells[^1]; - Assert.True(string.Equals(verdict, "no", StringComparison.Ordinal) || verdict.StartsWith("yes, ", StringComparison.Ordinal), + Assert.True( + string.Equals(verdict, "no", StringComparison.Ordinal) || + verdict.StartsWith("yes, ", StringComparison.Ordinal), $"The qualified cell of {backend} is neither 'no' nor 'yes, ': {verdict}"); if (verdict.StartsWith("yes", StringComparison.Ordinal)) { @@ -146,7 +158,7 @@ private static List BackendTableRows(string[] lines) string[] cells = Cells(lines[index]); if (string.Equals(cells[0], "Backend", StringComparison.Ordinal) - && string.Equals(cells[^1], "Qualified backend", StringComparison.Ordinal)) + && string.Equals(cells[^1], "Qualified backend", StringComparison.Ordinal)) { Assert.Equal(-1, header); header = index; diff --git a/tests/CheatEngine.SDK.Repository.Tests/Solution/QualificationHarnessShapeTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Solution/QualificationHarnessShapeTests.cs index d5cee953..cb355de2 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Solution/QualificationHarnessShapeTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Solution/QualificationHarnessShapeTests.cs @@ -10,7 +10,9 @@ namespace CheatEngine.SDK.Repository.Tests.Solution; public sealed class QualificationHarnessShapeTests { private const string LiveProbe = "tests/CheatEngine.SDK.LiveProbe/CheatEngine.SDK.LiveProbe.csproj"; - private const string Target = "tests/CheatEngine.SDK.QualificationTarget/CheatEngine.SDK.QualificationTarget.csproj"; + + private const string Target = + "tests/CheatEngine.SDK.QualificationTarget/CheatEngine.SDK.QualificationTarget.csproj"; [Fact] public void LiveProbe_is_in_the_solution_as_an_x64_dynamic_loading_plugin_that_never_packs() @@ -35,7 +37,8 @@ public void QualificationTarget_is_in_the_solution_and_publishes_native_aot_for_ Assert.Equal("Exe", Property(project, "OutputType")); Assert.Equal("true", Property(project, "PublishAot")); Assert.Equal(["win-x64", "win-x86"], - (Property(project, "RuntimeIdentifiers") ?? string.Empty).Split(';', StringSplitOptions.RemoveEmptyEntries)); + (Property(project, "RuntimeIdentifiers") ?? string.Empty).Split(';', + StringSplitOptions.RemoveEmptyEntries)); Assert.Null(Property(project, "RuntimeIdentifier")); Assert.True(File.Exists(Absolute("tests/CheatEngine.SDK.QualificationTarget/README.md"))); } @@ -65,7 +68,7 @@ public void QualificationTarget_references_no_SDK_project() Assert.Empty(project.Descendants("ProjectReference")); Assert.Empty(project.Descendants("PackageReference")); foreach (string source in Directory.EnumerateFiles( - Absolute("tests/CheatEngine.SDK.QualificationTarget"), "*.cs")) + Absolute("tests/CheatEngine.SDK.QualificationTarget"), "*.cs")) { Assert.DoesNotContain("CheatEngine.SDK.", File.ReadAllText(source), StringComparison.Ordinal); } @@ -73,7 +76,8 @@ public void QualificationTarget_references_no_SDK_project() private static XElement Project(string path) { - return XDocument.Load(Absolute(path)).Root ?? throw new InvalidOperationException(path + " has no root element."); + return XDocument.Load(Absolute(path)).Root ?? + throw new InvalidOperationException(path + " has no root element."); } private static string? Property(XElement project, string name) @@ -112,7 +116,7 @@ private static HashSet SolutionProjects() foreach (XElement project in XDocument.Load(RepositoryRoot.SolutionPath).Descendants("Project")) { if (string.Equals(((string?) project.Attribute("Path"))?.Replace('\\', '/'), projectPath, - StringComparison.Ordinal)) + StringComparison.Ordinal)) { return (string?) project.Element("Platform")?.Attribute("Project"); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Toolchain/ToolchainPinTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Toolchain/ToolchainPinTests.cs index 5066ab8e..5fb656a4 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Toolchain/ToolchainPinTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Toolchain/ToolchainPinTests.cs @@ -231,18 +231,14 @@ private static HashSet ExpandCodes(XDocument document, string value) private static JsonElement ReadGlobalJsonSdk() { - JsonDocumentOptions options = new() - { - CommentHandling = JsonCommentHandling.Skip, - AllowTrailingCommas = true - }; + JsonDocumentOptions options = new() { CommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true }; using JsonDocument document = JsonDocument.Parse(File.ReadAllText(RepositoryFile(GlobalJson)), options); return document.RootElement.GetProperty("sdk").Clone(); } - [GeneratedRegex(@"^\d+\.\d+\.\d{3}$", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^\d+\.\d+\.\d{3}$", RegexOptions.CultureInvariant, 1000)] private static partial Regex ExactSdkVersion(); - [GeneratedRegex(@"^\d+\.\d+-recommended$", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^\d+\.\d+-recommended$", RegexOptions.CultureInvariant, 1000)] private static partial Regex PinnedAnalysisLevel(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContract.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContract.cs index 6bcb54e6..d9cf2b13 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContract.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContract.cs @@ -48,7 +48,8 @@ internal static class WorkflowContract public const string BinlogRetention = "5"; /// The only runner labels a job may use (never a floating -latest label). - public static readonly HashSet RunnerLabels = new(StringComparer.Ordinal) { "windows-2025", "ubuntu-24.04" }; + public static readonly HashSet + RunnerLabels = new(StringComparer.Ordinal) { "windows-2025", "ubuntu-24.04" }; /// The workflows that call ci.yml and so produce "CI / Gate". public static readonly string[] Callers = ["pull-request-ci.yml", "main-ci.yml", "release.yml"]; @@ -150,8 +151,8 @@ public static void AssertNoViolations(string rule, IReadOnlyCollection(WorkflowFile.Mapping(job.Node, "strategy")); Assert.Equal("false", WorkflowFile.Scalar(strategy, "fail-fast")); YamlMappingNode matrix = Assert.IsType(WorkflowFile.Mapping(strategy, "matrix")); - Assert.Equal(["Debug", "Release"], WorkflowFile.ScalarValues(Assert.IsType(WorkflowFile.Sequence(matrix, "configuration")))); + Assert.Equal(["Debug", "Release"], + WorkflowFile.ScalarValues(Assert.IsType(WorkflowFile.Sequence(matrix, "configuration")))); Assert.Equal(["native", "native-host-emulator"], job.Needs()); // One build of the whole solution per leg, logged for failure analysis; every later step reuses it. string build = WorkflowFile.Scalar(job.Step("Build"), "run") ?? ""; - Assert.Contains("dotnet build CheatEngine.SDK.slnx -c $env:CONFIGURATION --no-restore", build, StringComparison.Ordinal); + Assert.Contains("dotnet build CheatEngine.SDK.slnx -c $env:CONFIGURATION --no-restore", build, + StringComparison.Ordinal); Assert.Contains("\"-bl:artifacts/logs/build-test-$env:CONFIGURATION.binlog\"", build, StringComparison.Ordinal); } @@ -58,7 +60,8 @@ public void Release_leg_packs_before_testing_and_exports_the_exact_nupkg() Assert.Equal("matrix.configuration == 'Release'", WorkflowFile.Scalar(packStep, "if")); Assert.Equal("${{ inputs.package-version }}", WorkflowJob.Env(packStep, "PACKAGE_VERSION")); string packRun = WorkflowFile.Scalar(packStep, "run") ?? ""; - Assert.Contains("dotnet pack src/CheatEngine.SDK -c Release --no-restore -o artifacts/nuget -bl:artifacts/logs/pack-Release.binlog", + Assert.Contains( + "dotnet pack src/CheatEngine.SDK -c Release --no-restore -o artifacts/nuget -bl:artifacts/logs/pack-Release.binlog", packRun, StringComparison.Ordinal); // The packaging tests consume the packed file itself, in the Release leg only, and log its SHA-256. @@ -77,7 +80,8 @@ public void Release_leg_packs_before_testing_and_exports_the_exact_nupkg() Assert.Contains("'_manifest/spdx_2.2/manifest.spdx.json'", packRun, StringComparison.Ordinal); Assert.Contains("\"nupkg=$($package.FullName)\"", packRun, StringComparison.Ordinal); Assert.Contains("\"sha256=$sha256\"", packRun, StringComparison.Ordinal); - Assert.Contains("$package.Name -cne \"CheatEngine.SDK.$($env:PACKAGE_VERSION).nupkg\"", packRun, StringComparison.Ordinal); + Assert.Contains("$package.Name -cne \"CheatEngine.SDK.$($env:PACKAGE_VERSION).nupkg\"", packRun, + StringComparison.Ordinal); Assert.Contains("'build/native/cheatengine-sdk-lua-bridge.dll'", packRun, StringComparison.Ordinal); } @@ -91,14 +95,18 @@ public void Debug_leg_excludes_packaging_tests_by_trait_never_by_skip() int debug = run.IndexOf("if ($env:CONFIGURATION -eq 'Debug') {", StringComparison.Ordinal); int release = run.IndexOf("else {", debug + 1, StringComparison.Ordinal); int failSkips = run.IndexOf("'--fail-skips', 'on'", StringComparison.Ordinal); - int filter = run.IndexOf($"'--filter-not-trait', '{WorkflowContract.PackagingTrait}'", StringComparison.Ordinal); + int filter = run.IndexOf($"'--filter-not-trait', '{WorkflowContract.PackagingTrait}'", + StringComparison.Ordinal); Assert.True(options >= 0 && options < failSkips && failSkips < debug, "--fail-skips on must be a common option of both legs."); Assert.True(debug < filter && filter < release, "The packaging trait filter belongs to the Debug leg only."); // No other way to hide a test: no second filter, no ignored exit code, no retries in the required run. Assert.Equal(1, Occurrences(run, "--filter")); - foreach (string forbidden in new[] { "--ignore-exit-code", "--retry-failed-tests", "TESTINGPLATFORM_EXITCODE_IGNORE" }) + foreach (string forbidden in new[] + { + "--ignore-exit-code", "--retry-failed-tests", "TESTINGPLATFORM_EXITCODE_IGNORE" + }) { Assert.DoesNotContain(forbidden, run, StringComparison.Ordinal); } @@ -118,11 +126,12 @@ public void Test_step_runs_every_module_once_with_the_contract_options() Assert.Equal(1, Occurrences(run, "dotnet test")); Assert.Contains("dotnet test @options", run, StringComparison.Ordinal); foreach (string option in new[] - { - "'--solution', 'CheatEngine.SDK.slnx'", "'--no-build'", "'--results-directory', $env:RESULTS", "'--report-trx'", - "'--report-gh', '--report-gh-groups', 'off'", "'--hangdump', '--hangdump-timeout'", "'--crashdump'", - "'--coverage', '--coverage-output-format', 'xml'" - }) + { + "'--solution', 'CheatEngine.SDK.slnx'", "'--no-build'", "'--results-directory', $env:RESULTS", + "'--report-trx'", "'--report-gh', '--report-gh-groups', 'off'", + "'--hangdump', '--hangdump-timeout'", "'--crashdump'", + "'--coverage', '--coverage-output-format', 'xml'" + }) { Assert.Contains(option, run, StringComparison.Ordinal); } @@ -140,7 +149,8 @@ public void Every_test_module_references_the_extensions_the_test_step_uses() HashSet referenced = new(StringComparer.Ordinal); foreach (XElement group in props.Descendants("ItemGroup")) { - if (!((string?) group.Attribute("Condition") ?? "").Contains("$(MSBuildProjectName.EndsWith('.Tests'))", StringComparison.Ordinal)) + if (!((string?) group.Attribute("Condition") ?? "").Contains("$(MSBuildProjectName.EndsWith('.Tests'))", + StringComparison.Ordinal)) { continue; } @@ -167,7 +177,8 @@ public void Hang_dump_timeout_is_well_below_the_build_test_job_timeout() Match hang = HangDumpTimeout().Match(run); Assert.True(hang.Success, "The Test step must pass '--hangdump-timeout', 'm'."); int hangMinutes = int.Parse(hang.Groups["minutes"].Value, NumberStyles.None, CultureInfo.InvariantCulture); - int jobMinutes = int.Parse(WorkflowFile.Scalar(job.Node, "timeout-minutes") ?? "0", NumberStyles.None, CultureInfo.InvariantCulture); + int jobMinutes = int.Parse(WorkflowFile.Scalar(job.Node, "timeout-minutes") ?? "0", NumberStyles.None, + CultureInfo.InvariantCulture); // The dump must be written, uploaded and the job reported well before the runner kills it. Assert.True(hangMinutes > 0 && hangMinutes * 2 <= jobMinutes, @@ -188,7 +199,8 @@ public void Every_uploaded_artifact_name_is_reserved() string retention = WorkflowJob.With(step, "retention-days") ?? ""; foreach (string name in ExpandConfiguration(template)) { - Assert.True(names.Add(name), $"{workflow.FileName} uploads '{name}' twice; artifact names are unique per run."); + Assert.True(names.Add(name), + $"{workflow.FileName} uploads '{name}' twice; artifact names are unique per run."); } string? expectedRetention = ExpectedRetention(template); @@ -218,10 +230,13 @@ public void Binlogs_are_uploaded_only_on_failure_and_never_from_sonar_or_release foreach (YamlMappingNode step in job.StepsUsing("actions/upload-artifact@")) { string name = WorkflowJob.With(step, "name") ?? ""; - if (name.StartsWith("binlogs-", StringComparison.Ordinal) || name.StartsWith("test-dumps-", StringComparison.Ordinal)) + if (name.StartsWith("binlogs-", StringComparison.Ordinal) || + name.StartsWith("test-dumps-", StringComparison.Ordinal)) { - Assert.True(mayLogBuilds, $"{job.Location} uploads '{name}'; sonar.yml and release.yml never do."); - Assert.True(string.Equals(WorkflowFile.Scalar(step, "if"), "failure()", StringComparison.Ordinal), + Assert.True(mayLogBuilds, + $"{job.Location} uploads '{name}'; sonar.yml and release.yml never do."); + Assert.True( + string.Equals(WorkflowFile.Scalar(step, "if"), "failure()", StringComparison.Ordinal), $"{job.Location} uploads '{name}' outside 'if: failure()'."); } } @@ -231,7 +246,8 @@ public void Binlogs_are_uploaded_only_on_failure_and_never_from_sonar_or_release // The jobs that build, pack or publish keep their logs for a failed run. WorkflowFile pipeline = Pipeline(); Assert.Single(pipeline.Job(BuildTestJob).StepsUsing("actions/upload-artifact@"), - static step => string.Equals(WorkflowJob.With(step, "name"), "binlogs-build-test-${{ matrix.configuration }}", StringComparison.Ordinal)); + static step => string.Equals(WorkflowJob.With(step, "name"), + "binlogs-build-test-${{ matrix.configuration }}", StringComparison.Ordinal)); Assert.Single(pipeline.Job("aot").StepsUsing("actions/upload-artifact@"), static step => string.Equals(WorkflowJob.With(step, "name"), "binlogs-aot", StringComparison.Ordinal)); Assert.Equal(3, BinaryLogSwitch().Count(pipeline.Job("aot").RunText())); @@ -245,7 +261,8 @@ public void Jobs_that_pack_or_test_fetch_full_history() foreach (WorkflowJob job in workflow.Jobs()) { string run = job.RunText(); - bool packs = VersionedPack().IsMatch(run) || run.Contains("dotnet-sonarscanner", StringComparison.Ordinal); + bool packs = VersionedPack().IsMatch(run) || + run.Contains("dotnet-sonarscanner", StringComparison.Ordinal); bool builds = VersionedBuild().IsMatch(run); if (!packs && !builds) { @@ -254,7 +271,8 @@ public void Jobs_that_pack_or_test_fetch_full_history() // MinVer computes the version from tags and history; a shallow clone packs 0.0.0-alpha.0. YamlMappingNode checkout = Assert.Single(job.StepsUsing("actions/checkout@")); - bool fullHistory = string.Equals(WorkflowJob.With(checkout, "fetch-depth"), "0", StringComparison.Ordinal); + bool fullHistory = string.Equals(WorkflowJob.With(checkout, "fetch-depth"), "0", + StringComparison.Ordinal); bool skipsVersioning = !packs && run.Contains("MinVerSkip=true", StringComparison.Ordinal); Assert.True(fullHistory || skipsVersioning, $"{job.Location} builds, packs, tests or analyses: check out with fetch-depth: 0 (MinVer)."); @@ -280,13 +298,17 @@ public void Aot_job_publishes_the_native_aot_probes() // Publication and inspection only: a NativeAOT publish is never presented as a Cheat Engine load (audit A20-07). string run = aot.RunText(); - Assert.Contains("dotnet publish tests/CheatEngine.SDK.AotProbe/CheatEngine.SDK.AotProbe.csproj -c Release --no-restore", run, + Assert.Contains( + "dotnet publish tests/CheatEngine.SDK.AotProbe/CheatEngine.SDK.AotProbe.csproj -c Release --no-restore", + run, StringComparison.Ordinal); - Assert.Contains("$libraryProject = 'tests/CheatEngine.SDK.NativeAotLibraryProbe/CheatEngine.SDK.NativeAotLibraryProbe.csproj'", + Assert.Contains( + "$libraryProject = 'tests/CheatEngine.SDK.NativeAotLibraryProbe/CheatEngine.SDK.NativeAotLibraryProbe.csproj'", run, StringComparison.Ordinal); Assert.Contains("dotnet publish $libraryProject -c Release --no-restore", run, StringComparison.Ordinal); Assert.Contains("& $harness --analyze $library", run, StringComparison.Ordinal); - Assert.Contains("lua-protection-bridge", WorkflowJob.With(Assert.Single(aot.StepsUsing("actions/download-artifact@")), "name"), + Assert.Contains("lua-protection-bridge", + WorkflowJob.With(Assert.Single(aot.StepsUsing("actions/download-artifact@")), "name"), StringComparison.Ordinal); } @@ -321,7 +343,8 @@ public void Live_probe_is_compiled_by_the_ci_solution_build() { foreach (YamlMappingNode upload in pipelineJob.StepsUsing("actions/upload-artifact@")) { - Assert.DoesNotContain("LiveProbe", WorkflowJob.With(upload, "path") ?? "", StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("LiveProbe", WorkflowJob.With(upload, "path") ?? "", + StringComparison.OrdinalIgnoreCase); } } } @@ -357,8 +380,8 @@ private static int Occurrences(string text, string value) { int count = 0; for (int index = text.IndexOf(value, StringComparison.Ordinal); - index >= 0; - index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) + index >= 0; + index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) { count++; } @@ -398,18 +421,19 @@ private static bool IsReservedWithoutRetention(string template) return WorkflowContract.ReservedArtifacts.TryGetValue(template, out string? retention) && retention is null; } - [GeneratedRegex(@"'--hangdump-timeout',\s*'(?\d+)m'", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"'--hangdump-timeout',\s*'(?\d+)m'", RegexOptions.CultureInvariant, 1000)] private static partial Regex HangDumpTimeout(); - [GeneratedRegex(@"\bdotnet\s+pack\b", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"\bdotnet\s+pack\b", RegexOptions.CultureInvariant, 1000)] private static partial Regex VersionedPack(); - [GeneratedRegex(@"\bdotnet\s+(?:build|test|publish)\b", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"\bdotnet\s+(?:build|test|publish)\b", RegexOptions.CultureInvariant, 1000)] private static partial Regex VersionedBuild(); - [GeneratedRegex(@"(?:^|\s|"")[-/]bl(?::|\s|$)", RegexOptions.Multiline | RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"(?:^|\s|"")[-/]bl(?::|\s|$)", RegexOptions.Multiline | RegexOptions.CultureInvariant, 1000)] private static partial Regex BinaryLogSwitch(); - [GeneratedRegex(@"^binlogs-[a-z0-9-]+?(?:-\$\{\{ matrix\.configuration \}\})?$", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^binlogs-[a-z0-9-]+?(?:-\$\{\{ matrix\.configuration \}\})?$", RegexOptions.CultureInvariant, + 1000)] private static partial Regex BinlogName(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Gate.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Gate.cs index 3f75b01f..df2f5df8 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Gate.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Gate.cs @@ -1,3 +1,5 @@ +using System.Globalization; + using YamlDotNet.RepresentationModel; namespace CheatEngine.SDK.Repository.Tests.Workflows; @@ -29,7 +31,7 @@ public void Callers_invoke_ci_through_job_ci_named_CI() if (string.Equals(job.Uses, PipelineUses, StringComparison.Ordinal)) { Assert.True(string.Equals(job.Id, WorkflowContract.CallerJobId, StringComparison.Ordinal) && - string.Equals(job.Name, WorkflowContract.CallerJobName, StringComparison.Ordinal), + string.Equals(job.Name, WorkflowContract.CallerJobName, StringComparison.Ordinal), $"{job.Location} calls ci.yml; only a job 'ci' named 'CI' may."); } } @@ -75,7 +77,8 @@ public void Gate_job_is_named_Gate_runs_always_and_has_no_permissions() Assert.Contains("$required = 'skipped'", run, StringComparison.Ordinal); Assert.Contains("if ($result -ne $required)", run, StringComparison.Ordinal); Assert.Contains("| Job | Result | Required | Reason |", run, StringComparison.Ordinal); - Assert.Contains("Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8", run, StringComparison.Ordinal); + Assert.Contains("Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8", run, + StringComparison.Ordinal); Assert.Contains("exit 1", run, StringComparison.Ordinal); } @@ -122,7 +125,7 @@ public void Ci_jobs_match_the_frozen_contract_ids_and_names() Assert.True(jobs.Remove(expected.Id, out WorkflowJob? job), $"ci.yml has no job '{expected.Id}'."); Assert.Equal(expected.Name, job.Name); Assert.Equal(expected.RunsOn, job.RunsOn); - Assert.Equal(expected.TimeoutMinutes?.ToString(System.Globalization.CultureInfo.InvariantCulture), + Assert.Equal(expected.TimeoutMinutes?.ToString(CultureInfo.InvariantCulture), WorkflowFile.Scalar(job.Node, "timeout-minutes")); } @@ -149,7 +152,9 @@ public void Ci_declares_exactly_the_contract_inputs_and_secret() YamlMappingNode secrets = Assert.IsType(WorkflowFile.Mapping(call, "secrets")); Assert.Equal(["SONAR_TOKEN"], WorkflowFile.Keys(secrets)); - Assert.Equal("false", WorkflowFile.Scalar(Assert.IsType(WorkflowFile.Mapping(secrets, "SONAR_TOKEN")), "required")); + Assert.Equal("false", + WorkflowFile.Scalar(Assert.IsType(WorkflowFile.Mapping(secrets, "SONAR_TOKEN")), + "required")); Assert.False(WorkflowFile.Has(call, "outputs"), "ci.yml has no workflow_call outputs in v1 (contract 1.4)."); // No repository variable steers the pipeline (contract 1.4). @@ -176,7 +181,8 @@ public void Sonar_waits_for_the_quality_gate_outside_push_events() Assert.Equal(["build-test"], sonar.Needs()); Assert.Equal("${{ github.event_name != 'push' }}", WorkflowJob.With(sonar.Node, "wait-quality-gate")); Assert.Equal("${{ secrets.SONAR_TOKEN }}", - WorkflowFile.Scalar(Assert.IsType(WorkflowFile.Mapping(sonar.Node, "secrets")), "SONAR_TOKEN")); + WorkflowFile.Scalar(Assert.IsType(WorkflowFile.Mapping(sonar.Node, "secrets")), + "SONAR_TOKEN")); WorkflowJob analyze = WorkflowFile.LoadWorkflow(WorkflowContract.Sonar).Job("analyze"); YamlMappingNode env = Assert.IsType(WorkflowFile.Mapping(analyze.Node, "env")); @@ -188,7 +194,8 @@ public void Sonar_waits_for_the_quality_gate_outside_push_events() YamlMappingNode link = analyze.Step("Link the analysis"); Assert.True(analyze.StepIndex("End analysis") < analyze.StepIndex("Link the analysis")); Assert.Equal("${{ !cancelled() }}", WorkflowFile.Scalar(link, "if")); - Assert.Contains("Out-File -FilePath $env:GITHUB_STEP_SUMMARY", WorkflowFile.Scalar(link, "run"), StringComparison.Ordinal); + Assert.Contains("Out-File -FilePath $env:GITHUB_STEP_SUMMARY", WorkflowFile.Scalar(link, "run"), + StringComparison.Ordinal); } [Fact] @@ -199,17 +206,18 @@ public void Sonar_excludes_non_product_trees_from_analysis_and_coverage() HashSet exclusions = new(SonarProperty(begin, "sonar.exclusions").Split(','), StringComparer.Ordinal); foreach (string tree in new[] - { - "artifacts/**", "tests/CheatEngine.SDK.QualificationTarget/**", "tests/native-host-emulator/**", "eng/tools/**", - "docs/**" - }) + { + "artifacts/**", "tests/CheatEngine.SDK.QualificationTarget/**", + "tests/native-host-emulator/**", "eng/tools/**", "docs/**" + }) { Assert.True(exclusions.Contains(tree), $"sonar.exclusions must list {tree}."); } // Tests stay analysed (their issues are triaged by rule), but they never count as product coverage. Assert.False(exclusions.Contains("tests/**"), "Tests stay analysed; only their coverage is excluded."); - HashSet coverage = new(SonarProperty(begin, "sonar.coverage.exclusions").Split(','), StringComparer.Ordinal); + HashSet coverage = new(SonarProperty(begin, "sonar.coverage.exclusions").Split(','), + StringComparer.Ordinal); foreach (string tree in new[] { "tests/**", "eng/**", "docs/**" }) { Assert.True(coverage.Contains(tree), $"sonar.coverage.exclusions must list {tree}."); @@ -239,7 +247,8 @@ public void Pull_request_and_policy_workflows_have_no_path_filters() { // pr-policy.yml no longer exists (the PR title/changelog policy engine was removed); pull-request-ci.yml // must always exist. - Assert.False(string.Equals(fileName, "pull-request-ci.yml", StringComparison.Ordinal), $"{fileName} is missing."); + Assert.False(string.Equals(fileName, "pull-request-ci.yml", StringComparison.Ordinal), + $"{fileName} is missing."); continue; } @@ -251,7 +260,8 @@ public void Pull_request_and_policy_workflows_have_no_path_filters() continue; } - Assert.False(WorkflowFile.Has(configuration, "paths") || WorkflowFile.Has(configuration, "paths-ignore"), + Assert.False( + WorkflowFile.Has(configuration, "paths") || WorkflowFile.Has(configuration, "paths-ignore"), $"{fileName} '{trigger}' must not filter paths: its required check must report on every pull request."); } } @@ -264,7 +274,8 @@ public void Main_ci_runs_every_push_to_main_without_a_concurrency_group() Assert.Equal(["push", "workflow_dispatch"], main.Triggers()); YamlMappingNode push = Assert.IsType(main.Trigger("push")); - Assert.Equal(["main"], WorkflowFile.ScalarValues(Assert.IsType(WorkflowFile.Sequence(push, "branches")))); + Assert.Equal(["main"], + WorkflowFile.ScalarValues(Assert.IsType(WorkflowFile.Sequence(push, "branches")))); Assert.False(WorkflowFile.Has(main.Root, "concurrency"), "main-ci.yml keeps every main commit's run: a concurrency group would cancel or drop intermediate runs."); } @@ -278,10 +289,13 @@ public void Pull_request_ci_skips_drafts_and_cancels_superseded_runs() YamlMappingNode trigger = Assert.IsType(pullRequest.Trigger("pull_request")); Assert.Equal(["opened", "synchronize", "reopened", "ready_for_review"], WorkflowFile.ScalarValues(Assert.IsType(WorkflowFile.Sequence(trigger, "types")))); - Assert.Equal("${{ !github.event.pull_request.draft }}", pullRequest.Job(WorkflowContract.CallerJobId).Condition); + Assert.Equal("${{ !github.event.pull_request.draft }}", + pullRequest.Job(WorkflowContract.CallerJobId).Condition); - YamlMappingNode concurrency = Assert.IsType(WorkflowFile.Mapping(pullRequest.Root, "concurrency")); - Assert.Equal("${{ github.workflow }}-${{ github.event.pull_request.number }}", WorkflowFile.Scalar(concurrency, "group")); + YamlMappingNode concurrency = + Assert.IsType(WorkflowFile.Mapping(pullRequest.Root, "concurrency")); + Assert.Equal("${{ github.workflow }}-${{ github.event.pull_request.number }}", + WorkflowFile.Scalar(concurrency, "group")); Assert.Equal("true", WorkflowFile.Scalar(concurrency, "cancel-in-progress")); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Hygiene.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Hygiene.cs index d97272ce..80fcdb24 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Hygiene.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Hygiene.cs @@ -29,7 +29,8 @@ public void Every_job_has_a_timeout_and_a_pinned_runner_label() } string? timeout = WorkflowFile.Scalar(job.Node, "timeout-minutes"); - if (!int.TryParse(timeout, NumberStyles.None, CultureInfo.InvariantCulture, out int minutes) || minutes <= 0) + if (!int.TryParse(timeout, NumberStyles.None, CultureInfo.InvariantCulture, out int minutes) || + minutes <= 0) { violations.Add(new Violation(workflow.FileName, job.Id, $"{job.Location} has no positive timeout-minutes ('{timeout}').")); @@ -45,7 +46,8 @@ public void Workflows_grant_only_read_permissions_at_the_top_level() { foreach (WorkflowFile workflow in WorkflowFile.LoadWorkflows()) { - Assert.True(workflow.Root.Children.TryGetValue(new YamlScalarNode("permissions"), out YamlNode? permissions), + Assert.True( + workflow.Root.Children.TryGetValue(new YamlScalarNode("permissions"), out YamlNode? permissions), $"{workflow.FileName} must declare top-level permissions (contents: read) and elevate per job only."); if (permissions is YamlScalarNode scalar) { @@ -144,7 +146,8 @@ public void Every_checkout_disables_credential_persistence() } checkouts++; - Assert.True(string.Equals(WorkflowJob.With(step, "persist-credentials"), "false", StringComparison.Ordinal), + Assert.True( + string.Equals(WorkflowJob.With(step, "persist-credentials"), "false", StringComparison.Ordinal), $"{file.RelativePath} line {step.Start.Line}: actions/checkout must set persist-credentials: false."); } } @@ -187,7 +190,7 @@ public void Every_native_command_in_a_workflow_script_checks_its_exit_code() } if (next >= lines.Length || - !lines[next].TrimStart().StartsWith("if ($LASTEXITCODE -ne 0)", StringComparison.Ordinal)) + !lines[next].TrimStart().StartsWith("if ($LASTEXITCODE -ne 0)", StringComparison.Ordinal)) { violations.Add(new Violation(file.FileName, subject, $"{file.RelativePath} ({subject}): '{lines[index].Trim()}' must be followed by if ($LASTEXITCODE -ne 0) {{ throw ... }}.")); @@ -221,7 +224,8 @@ public void Pipeline_workflows_and_composite_actions_run_scripts_in_pwsh() WorkflowFile workflow = WorkflowFile.LoadWorkflow(fileName); YamlMappingNode? defaults = WorkflowFile.Mapping(workflow.Root, "defaults"); YamlMappingNode? run = defaults is null ? null : WorkflowFile.Mapping(defaults, "run"); - Assert.True(run is not null && string.Equals(WorkflowFile.Scalar(run, "shell"), "pwsh", StringComparison.Ordinal), + Assert.True( + run is not null && string.Equals(WorkflowFile.Scalar(run, "shell"), "pwsh", StringComparison.Ordinal), $"{fileName} must declare defaults.run.shell: pwsh."); } @@ -256,18 +260,18 @@ public void No_workflow_passes_ApiCompatGenerateSuppressionFile() { // Suppressions are regenerated by the integrator only; CI must fail on an undeclared break instead. Assert.False(file.Text.Contains("ApiCompatGenerateSuppressionFile", StringComparison.OrdinalIgnoreCase) || - file.Text.Contains("GenerateCompatibilitySuppressionFile", StringComparison.OrdinalIgnoreCase), + file.Text.Contains("GenerateCompatibilitySuppressionFile", StringComparison.OrdinalIgnoreCase), $"{file.RelativePath} generates an ApiCompat suppression file; CI must fail on an undeclared break instead."); } } - [GeneratedRegex(@"^\s*(?:-\s+)?uses:\s*(?\S+)(?.*)$", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^\s*(?:-\s+)?uses:\s*(?\S+)(?.*)$", RegexOptions.CultureInvariant, 1000)] private static partial Regex UsesLine(); [GeneratedRegex(@"^(?[A-Za-z0-9-]+/[A-Za-z0-9._/-]+)@(?[0-9a-f]{40}) # v\d+\.\d+\.\d+\s*$", - RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + RegexOptions.CultureInvariant, 1000)] private static partial Regex PinnedReference(); - [GeneratedRegex(@"^\s*(?:dotnet|xmake|git|gh|tar)\s|^\s*\./|^\s*&\s", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^\s*(?:dotnet|xmake|git|gh|tar)\s|^\s*\./|^\s*&\s", RegexOptions.CultureInvariant, 1000)] private static partial Regex NativeInvocation(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Lint.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Lint.cs index 0fe5929e..d46d2ffb 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Lint.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Lint.cs @@ -92,7 +92,8 @@ public void Format_job_verifies_whitespace_without_restore() YamlMappingNode setup = Assert.Single(format.StepsUsing(WorkflowContract.SetupAction)); Assert.Null(WorkflowJob.With(setup, "restore")); string run = format.RunText(); - Assert.Contains("dotnet format whitespace . --folder --verify-no-changes --exclude artifacts", run, StringComparison.Ordinal); + Assert.Contains("dotnet format whitespace . --folder --verify-no-changes --exclude artifacts", run, + StringComparison.Ordinal); Assert.DoesNotContain("dotnet restore", run, StringComparison.Ordinal); Assert.DoesNotContain("dotnet build", run, StringComparison.Ordinal); // Style rules are enforced by the build (EnforceCodeStyleInBuild, warnings as errors), not by this job. @@ -102,12 +103,12 @@ public void Format_job_verifies_whitespace_without_restore() Assert.Contains("end_of_line = crlf", ReadRepositoryText(".editorconfig"), StringComparison.Ordinal); } - [GeneratedRegex(@"#\s*zizmor:\s*ignore\[[^\]]+\](?[^\n]*)", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"#\s*zizmor:\s*ignore\[[^\]]+\](?[^\n]*)", RegexOptions.CultureInvariant, 1000)] private static partial Regex InlineZizmorIgnore(); - [GeneratedRegex(@"^\d+\.\d+\.\d+$", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^\d+\.\d+\.\d+$", RegexOptions.CultureInvariant, 1000)] private static partial Regex ExactVersion(); - [GeneratedRegex(@"^[0-9a-f]{64}$", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"^[0-9a-f]{64}$", RegexOptions.CultureInvariant, 1000)] private static partial Regex Sha256(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Restore.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Restore.cs index c194d59b..ac011c8f 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Restore.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Restore.cs @@ -15,12 +15,16 @@ public void Composite_setup_restores_in_locked_mode() WorkflowFile action = SetupAction(); YamlMappingNode inputs = Assert.IsType(WorkflowFile.Mapping(action.Root, "inputs")); - Assert.Equal("false", WorkflowFile.Scalar(Assert.IsType(WorkflowFile.Mapping(inputs, "cache")), "default")); - Assert.Equal("", WorkflowFile.Scalar(Assert.IsType(WorkflowFile.Mapping(inputs, "restore")), "default")); + Assert.Equal("false", + WorkflowFile.Scalar(Assert.IsType(WorkflowFile.Mapping(inputs, "cache")), "default")); + Assert.Equal("", + WorkflowFile.Scalar(Assert.IsType(WorkflowFile.Mapping(inputs, "restore")), "default")); IReadOnlyList steps = action.ActionSteps(); YamlMappingNode install = Assert.Single(steps, - static step => (WorkflowFile.Scalar(step, "uses") ?? "").StartsWith("actions/setup-dotnet@", StringComparison.Ordinal)); + static step => + (WorkflowFile.Scalar(step, "uses") ?? "").StartsWith("actions/setup-dotnet@", + StringComparison.Ordinal)); Assert.Equal("global.json", WorkflowJob.With(install, "global-json-file")); Assert.Equal("${{ inputs.cache }}", WorkflowJob.With(install, "cache")); Assert.Equal("**/packages.lock.json", WorkflowJob.With(install, "cache-dependency-path")); @@ -57,7 +61,8 @@ public void Every_restore_in_the_pipeline_is_locked() } Assert.True(unlocked.Count == 0, - "Restore with --locked-mode, or through the composite action's restore input: " + string.Join("; ", unlocked)); + "Restore with --locked-mode, or through the composite action's restore input: " + + string.Join("; ", unlocked)); } [Fact] @@ -100,7 +105,8 @@ public void Every_dotnet_job_uses_the_composite_setup_action() for (int index = 0; index < steps.Count; index++) { if (setupStep < 0 && - string.Equals(WorkflowFile.Scalar(steps[index], "uses"), WorkflowContract.SetupAction, StringComparison.Ordinal)) + string.Equals(WorkflowFile.Scalar(steps[index], "uses"), WorkflowContract.SetupAction, + StringComparison.Ordinal)) { setupStep = index; } @@ -162,12 +168,12 @@ private static bool RunsDotnet(string run) return false; } - [GeneratedRegex(@"(?m)(?:^|[\s;(|{&])dotnet\s", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"(?m)(?:^|[\s;(|{&])dotnet\s", RegexOptions.CultureInvariant, 1000)] private static partial Regex DotnetInvocation(); - [GeneratedRegex(@"\bdotnet\s+restore\b", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"\bdotnet\s+restore\b", RegexOptions.CultureInvariant, 1000)] private static partial Regex DotnetRestore(); - [GeneratedRegex(@"(?:^|[\s(])\.?/?(?(?:eng|tests)/[\w./-]+\.ps1)\b", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"(?:^|[\s(])\.?/?(?(?:eng|tests)/[\w./-]+\.ps1)\b", RegexOptions.CultureInvariant, 1000)] private static partial Regex ScriptReference(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Supply.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Supply.cs index fba26c96..afcc5714 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Supply.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Supply.cs @@ -15,7 +15,8 @@ public void Dependency_review_job_always_runs_and_reviews_only_pull_requests() // The gate requires success: the job itself never skips, only its steps choose by event (contract 1.11). Assert.Null(job.Condition); Assert.Empty(job.Needs()); - Assert.False(WorkflowFile.Has(job.Node, "permissions"), "dependency-review keeps the read-only top-level permissions."); + Assert.False(WorkflowFile.Has(job.Node, "permissions"), + "dependency-review keeps the read-only top-level permissions."); YamlMappingNode review = Assert.Single(job.StepsUsing("actions/dependency-review-action@")); Assert.Equal("github.event_name == 'pull_request'", WorkflowFile.Scalar(review, "if")); @@ -45,11 +46,13 @@ public void Dependency_review_configuration_blocks_advisories_and_unreviewed_lic Assert.Equal("moderate", WorkflowFile.Scalar(config, "fail-on-severity")); Assert.Equal(["runtime", "development"], - WorkflowFile.ScalarValues(Assert.IsType(WorkflowFile.Sequence(config, "fail-on-scopes")))); + WorkflowFile.ScalarValues( + Assert.IsType(WorkflowFile.Sequence(config, "fail-on-scopes")))); Assert.Contains("MIT", WorkflowFile.ScalarValues(Assert.IsType(WorkflowFile.Sequence(config, "allow-licenses"))), StringComparer.Ordinal); - foreach (string purl in WorkflowFile.ScalarValues(Assert.IsType(WorkflowFile.Sequence(config, "allow-dependencies-licenses")))) + foreach (string purl in WorkflowFile.ScalarValues( + Assert.IsType(WorkflowFile.Sequence(config, "allow-dependencies-licenses")))) { Assert.StartsWith("pkg:nuget/", purl, StringComparison.Ordinal); } @@ -57,7 +60,8 @@ public void Dependency_review_configuration_blocks_advisories_and_unreviewed_lic // The workflow sets these inline (contract 1.6); a second value here could silently disagree. foreach (string inline in new[] { "comment-summary-in-pr", "retry-on-snapshot-warnings", "config-file" }) { - Assert.False(WorkflowFile.Has(config, inline), $"{DependencyReviewConfig} must not repeat '{inline}', which ci.yml sets."); + Assert.False(WorkflowFile.Has(config, inline), + $"{DependencyReviewConfig} must not repeat '{inline}', which ci.yml sets."); } } @@ -76,6 +80,7 @@ public void Lock_file_job_restores_the_solution_and_every_out_of_solution_projec YamlMappingNode setup = Assert.Single(job.StepsUsing(WorkflowContract.SetupAction)); List targets = RestoreTargets(setup); Assert.Contains("CheatEngine.SDK.slnx", targets, StringComparer.Ordinal); - Assert.Contains("tests/CheatEngine.SDK.AotProbe/CheatEngine.SDK.AotProbe.csproj", targets, StringComparer.Ordinal); + Assert.Contains("tests/CheatEngine.SDK.AotProbe/CheatEngine.SDK.AotProbe.csproj", targets, + StringComparer.Ordinal); } } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.cs index 8f679c45..feaa13b9 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.cs @@ -92,6 +92,6 @@ private static string StripComments(string script) return string.Join('\n', lines); } - [GeneratedRegex(@"<#.*?#>", RegexOptions.Singleline | RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex(@"<#.*?#>", RegexOptions.Singleline | RegexOptions.CultureInvariant, 1000)] private static partial Regex CommentBlock(); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/DiagnosticsTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/DiagnosticsTests.cs index e989c604..a63a0b21 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/DiagnosticsTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/DiagnosticsTests.cs @@ -14,7 +14,8 @@ public sealed class DiagnosticsTests(RoslynFixture roslyn) : IClassFixture string.Equals(diagnostic.Id, "CESDK3002", StringComparison.Ordinal) - && diagnostic.GetMessage(CultureInfo.InvariantCulture) - .Contains("member", StringComparison.Ordinal)); + && diagnostic.GetMessage(CultureInfo.InvariantCulture) + .Contains("member", StringComparison.Ordinal)); Assert.Contains(run.GeneratorDiagnostics, static diagnostic => string.Equals(diagnostic.Id, "CESDK3002", StringComparison.Ordinal) - && diagnostic.GetMessage(CultureInfo.InvariantCulture) - .Contains("cache field", StringComparison.Ordinal)); + && diagnostic.GetMessage(CultureInfo.InvariantCulture) + .Contains("cache field", StringComparison.Ordinal)); AssertConflictLocation(run, "Generated member", "Specs/first.cheatengine-sdk-api.txt", 10, 10); AssertConflictLocation(run, "Generated member", "Specs/second.cheatengine-sdk-api.txt", 10, 10); AssertConflictLocation(run, "Generated cache field", "Specs/first.cheatengine-sdk-api.txt", 9, 10); @@ -117,11 +122,14 @@ public void Conflicting_member_and_cache_identities_are_diagnosed_on_both_spec_f public void Three_same_named_spec_files_receive_unique_case_insensitive_hint_names() { const string First = - "namespace: Demo\ntype: First\n" + SpecSources.Ce77 + "\nglobal: first\nmethod: LoadFirst\nform: throwing\nnil: none\ndoc: first.\n"; + "namespace: Demo\ntype: First\n" + SpecSources.Ce77 + + "\nglobal: first\nmethod: LoadFirst\nform: throwing\nnil: none\ndoc: first.\n"; const string Second = - "namespace: Demo\ntype: Second\n" + SpecSources.Ce77 + "\nglobal: second\nmethod: LoadSecond\nform: throwing\nnil: none\ndoc: second.\n"; + "namespace: Demo\ntype: Second\n" + SpecSources.Ce77 + + "\nglobal: second\nmethod: LoadSecond\nform: throwing\nnil: none\ndoc: second.\n"; const string Third = - "namespace: Demo\ntype: Third\n" + SpecSources.Ce77 + "\nglobal: third\nmethod: LoadThird\nform: throwing\nnil: none\ndoc: third.\n"; + "namespace: Demo\ntype: Third\n" + SpecSources.Ce77 + + "\nglobal: third\nmethod: LoadThird\nform: throwing\nnil: none\ndoc: third.\n"; GeneratorRun run = roslyn.Run( ("One/shared.cheatengine-sdk-api.txt", First), @@ -152,7 +160,7 @@ public void An_argument_after_an_optional_one_reports_CESDK3004_at_the_argument( { const string Path = "Specs/optional.cheatengine-sdk-api.txt"; string text = SpecSources.Ce77Header("Demo", "Optional") + - "global: g\nmethod: G\nform: throwing\nopt: a:int32\narg: b:int64\nnil: none\ndoc: d.\n"; + "global: g\nmethod: G\nform: throwing\nopt: a:int32\narg: b:int64\nnil: none\ndoc: d.\n"; GeneratorRun run = roslyn.Run(Path, text); @@ -165,7 +173,7 @@ public void A_required_result_after_an_optional_one_reports_CESDK3005_at_the_res { const string Path = "Specs/results.cheatengine-sdk-api.txt"; string text = SpecSources.Ce77Header("Demo", "Results") + - "global: g\nmethod: G\nform: outcome\nopt-result: a:int32\nresult: b:int64\nnil: none\ndoc: d.\n"; + "global: g\nmethod: G\nform: outcome\nopt-result: a:int32\nresult: b:int64\nnil: none\ndoc: d.\n"; GeneratorRun run = roslyn.Run(Path, text); @@ -193,7 +201,7 @@ private static void AssertConflictLocation(GeneratorRun run, string messageFragm foreach (Diagnostic diagnostic in run.GeneratorDiagnostics) { if (!diagnostic.GetMessage(CultureInfo.InvariantCulture) - .Contains(messageFragment, StringComparison.Ordinal)) + .Contains(messageFragment, StringComparison.Ordinal)) { continue; } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EmissionTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EmissionTests.cs index c1a398b3..0bce01d0 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EmissionTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EmissionTests.cs @@ -169,7 +169,8 @@ public void The_global_namespace_is_emitted_without_a_namespace_block() public void An_address_try_result_is_exposed_as_Address_and_converted_from_the_raw_core() { const string Text = - "namespace: Demo\ntype: Addresses\n" + SpecSources.Ce77 + "\nglobal: getAddress\nmethod: TryGetAddress\nform: try\nresult: value:address\nnil: none\ndoc: Gets a target address.\n"; + "namespace: Demo\ntype: Addresses\n" + SpecSources.Ce77 + + "\nglobal: getAddress\nmethod: TryGetAddress\nform: try\nresult: value:address\nnil: none\ndoc: Gets a target address.\n"; GeneratorRun run = roslyn.Run("address-result.cheatengine-sdk-api.txt", Text); @@ -190,7 +191,8 @@ public void An_address_try_result_is_exposed_as_Address_and_converted_from_the_r public void An_address_throwing_return_is_exposed_as_Address_and_converted_from_the_raw_core() { const string Text = - "namespace: Demo\ntype: Addresses\n" + SpecSources.Ce77 + "\nglobal: getAddress\nmethod: GetAddress\nform: throwing\nreturn: address\nnil: none\ndoc: Gets a target address.\n"; + "namespace: Demo\ntype: Addresses\n" + SpecSources.Ce77 + + "\nglobal: getAddress\nmethod: GetAddress\nform: throwing\nreturn: address\nnil: none\ndoc: Gets a target address.\n"; GeneratorRun run = roslyn.Run("address-return.cheatengine-sdk-api.txt", Text); @@ -210,7 +212,8 @@ public void An_address_throwing_return_is_exposed_as_Address_and_converted_from_ public void Address_arguments_and_try_results_keep_the_complete_public_signature_strongly_typed() { const string Text = - "namespace: Demo\ntype: Addresses\n" + SpecSources.Ce77 + "\nglobal: resolvePointer\nmethod: TryResolvePointer\nform: try\narg: address:address\nresult: result:address\nnil: none\ndoc: Resolves a target pointer.\n"; + "namespace: Demo\ntype: Addresses\n" + SpecSources.Ce77 + + "\nglobal: resolvePointer\nmethod: TryResolvePointer\nform: try\narg: address:address\nresult: result:address\nnil: none\ndoc: Resolves a target pointer.\n"; GeneratorRun run = roslyn.Run("address-argument-and-result.cheatengine-sdk-api.txt", Text); @@ -227,7 +230,7 @@ public void Address_arguments_and_try_results_keep_the_complete_public_signature public void Optional_address_argument_is_converted_by_the_facade_without_losing_its_state() { string text = SpecSources.Ce77Header("Demo", "Allocation") + - "global: allocateMemory\nmethod: TryAllocate\nform: try\narg: size:int64\nopt: preferredBaseAddress:address\nopt: protection:int32\nresult: address:address\nnil: expected-failure\ndoc: Allocates.\n"; + "global: allocateMemory\nmethod: TryAllocate\nform: try\narg: size:int64\nopt: preferredBaseAddress:address\nopt: protection:int32\nresult: address:address\nnil: expected-failure\ndoc: Allocates.\n"; GeneratorRun run = roslyn.Run("allocation.cheatengine-sdk-api.txt", text); @@ -253,7 +256,7 @@ public void Optional_address_argument_is_converted_by_the_facade_without_losing_ public void Outcome_form_with_address_results_is_exposed_through_the_facade() { string text = SpecSources.Ce77Header("Demo", "Symbols") + - "global: getAddressSafe\nmethod: ResolveAddress\nform: outcome\narg: expression:string\nresult: address:address\nopt-result: alternate:address\nnil: absence\ndoc: Resolves.\n"; + "global: getAddressSafe\nmethod: ResolveAddress\nform: outcome\narg: expression:string\nresult: address:address\nopt-result: alternate:address\nnil: absence\ndoc: Resolves.\n"; GeneratorRun run = roslyn.Run("symbols.cheatengine-sdk-api.txt", text); @@ -272,15 +275,17 @@ public void Outcome_form_with_address_results_is_exposed_through_the_facade() "alternate = __engineApiRawResult1.HasValue ? global::CheatEngine.SDK.Lua.Marshalling.LuaOptional.Of(new global::CheatEngine.SDK.Engine.Values.Address(unchecked((ulong)__engineApiRawResult1.Value))) : __engineApiRawResult1.IsNil ? global::CheatEngine.SDK.Lua.Marshalling.LuaOptional.Nil() : default;", generated, StringComparison.Ordinal); Assert.Contains("return __engineApiStatus;", generated, StringComparison.Ordinal); - Assert.Contains("return: LuaOperationStatus with out results; nil: absence;", generated, StringComparison.Ordinal); - Assert.Contains("global::CheatEngine.SDK.Lua.State.LuaState.MultipleResults", generated, StringComparison.Ordinal); + Assert.Contains("return: LuaOperationStatus with out results; nil: absence;", generated, + StringComparison.Ordinal); + Assert.Contains("global::CheatEngine.SDK.Lua.State.LuaState.MultipleResults", generated, + StringComparison.Ordinal); } [Fact] public void Rest_result_is_a_span_and_a_count_in_the_outcome_form() { string text = SpecSources.Ce77Header("Demo", "Bytes") + - "global: readBytes\nmethod: ReadBytes\nform: outcome\narg: address:address\narg: count:int32\nrest: values:int32\nnil: expected-failure\ndoc: Reads bytes.\n"; + "global: readBytes\nmethod: ReadBytes\nform: outcome\narg: address:address\narg: count:int32\nrest: values:int32\nnil: expected-failure\ndoc: Reads bytes.\n"; GeneratorRun run = roslyn.Run("bytes.cheatengine-sdk-api.txt", text); @@ -327,8 +332,8 @@ public void Memory_scalars_output_is_unchanged_by_the_new_grammar() private static string ExpectedText(string fileName) { using Stream stream = typeof(EmissionTests).Assembly.GetManifestResourceStream( - "CheatEngine.SDK.EngineApi.Tests.Expected." + fileName) - ?? throw new InvalidOperationException("Missing expected text " + fileName + "."); + "CheatEngine.SDK.EngineApi.Tests.Expected." + fileName) + ?? throw new InvalidOperationException("Missing expected text " + fileName + "."); using StreamReader reader = new(stream); return reader.ReadToEnd().ReplaceLineEndings("\n"); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EngineApiDiagnosticCatalogTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EngineApiDiagnosticCatalogTests.cs index cb4eae1c..b4c9682b 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EngineApiDiagnosticCatalogTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EngineApiDiagnosticCatalogTests.cs @@ -32,7 +32,8 @@ public void Every_engine_api_descriptor_has_a_page_a_help_link_and_a_release_row Assert.Equal(DiagnosticSeverity.Error, descriptor.DefaultSeverity); Assert.Equal(HelpLinkBase + descriptor.Id + ".md", descriptor.HelpLinkUri); Assert.DoesNotMatch(@"\.$", title); - Assert.EndsWith(".", descriptor.Description.ToString(CultureInfo.InvariantCulture), StringComparison.Ordinal); + Assert.EndsWith(".", descriptor.Description.ToString(CultureInfo.InvariantCulture), + StringComparison.Ordinal); string page = Path.Combine(root, "analyzers", "docs", descriptor.Id + ".md"); Assert.True(File.Exists(page), "Missing documentation page " + page + "."); @@ -48,7 +49,8 @@ private static DiagnosticDescriptor[] Descriptors() { return [ - .. typeof(EngineApiGenerator).Assembly.GetType("CheatEngine.SDK.SourceGenerators.EngineApi.EngineApiDiagnostics", + .. typeof(EngineApiGenerator).Assembly.GetType( + "CheatEngine.SDK.SourceGenerators.EngineApi.EngineApiDiagnostics", true)! .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static) .Where(static field => field.FieldType == typeof(DiagnosticDescriptor)) @@ -59,7 +61,9 @@ .. typeof(EngineApiGenerator).Assembly.GetType("CheatEngine.SDK.SourceGenerators // The directory that holds CheatEngine.SDK.slnx, found from the test binaries upwards. private static string RepositoryRoot() { - for (DirectoryInfo? directory = new(AppContext.BaseDirectory); directory is not null; directory = directory.Parent) + for (DirectoryInfo? directory = new(AppContext.BaseDirectory); + directory is not null; + directory = directory.Parent) { if (File.Exists(Path.Combine(directory.FullName, "CheatEngine.SDK.slnx"))) { @@ -67,6 +71,7 @@ private static string RepositoryRoot() } } - throw new InvalidOperationException("CheatEngine.SDK.slnx was not found above " + AppContext.BaseDirectory + "."); + throw new InvalidOperationException( + "CheatEngine.SDK.slnx was not found above " + AppContext.BaseDirectory + "."); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/IncrementalityTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/IncrementalityTests.cs index def3f8ca..e4934c3b 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/IncrementalityTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/IncrementalityTests.cs @@ -121,7 +121,7 @@ public void Pipeline_removing_a_spec_file_removes_only_its_output() public void Pipeline_editing_an_optional_argument_reruns_only_that_files_output() { string optional = SpecSources.Ce77Header("Demo.Optional", "Optional") + - "global: load\nmethod: Load\nform: throwing\narg: path:string\nopt: merge:boolean\nnil: none\ndoc: Loads.\n"; + "global: load\nmethod: Load\nform: throwing\narg: path:string\nopt: merge:boolean\nnil: none\ndoc: Loads.\n"; InMemoryAdditionalText original = new("a.cheatengine-sdk-api.txt", optional); InMemoryAdditionalText other = new("b.cheatengine-sdk-api.txt", SpecSources.BeepOnly); CSharpCompilation compilation = roslyn.CreateCompilation(); @@ -146,7 +146,7 @@ public void Pipeline_editing_an_optional_argument_reruns_only_that_files_output( public void Pipeline_step_values_hold_no_roslyn_objects() { string optional = SpecSources.Ce77Header("Demo.Optional", "Optional") + - "global: g\nmethod: G\nform: outcome\narg: a:address\nopt: b:int32\nresult: r:int64\nopt-result: s:address\nrest: values:double\nnil: absence\ndoc: d.\n"; + "global: g\nmethod: G\nform: outcome\narg: a:address\nopt: b:int32\nresult: r:int64\nopt-result: s:address\nrest: values:double\nnil: absence\ndoc: d.\n"; GeneratorRun run = roslyn.Run(("a.cheatengine-sdk-api.txt", SpecSources.Memory), ("b.cheatengine-sdk-api.txt", optional)); Assert.Equal(2, run.GeneratedSources.Length); @@ -155,7 +155,7 @@ public void Pipeline_step_values_hold_no_roslyn_objects() foreach (string stepName in EngineApiTrackingNames.All) { if (string.Equals(stepName, EngineApiTrackingNames.SpecTextFile, StringComparison.Ordinal)) - // Legitimately holds the raw AdditionalText: that is the point of this filter step. + // Legitimately holds the raw AdditionalText: that is the point of this filter step. { continue; } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/GeneratedAssembly.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/GeneratedAssembly.cs index 49ab4a53..99962168 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/GeneratedAssembly.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/GeneratedAssembly.cs @@ -43,7 +43,7 @@ public static GeneratedAssembly Load(GeneratorRun run) image.Position = 0; string assemblyName = "CheatEngine.SDK.EngineApi.Tests." + - Interlocked.Increment(ref s_counter).ToString(CultureInfo.InvariantCulture); + Interlocked.Increment(ref s_counter).ToString(CultureInfo.InvariantCulture); AssemblyLoadContext context = new(assemblyName); return new GeneratedAssembly(context.LoadFromStream(image)); } @@ -56,7 +56,7 @@ public TDelegate Delegate(string typeName, string methodName) Type[] parameterTypes = [.. parameters.Select(static parameter => parameter.ParameterType)]; Type type = Assembly.GetType(typeName, true)!; MethodInfo method = type.GetMethod(methodName, StaticMembers, parameterTypes) ?? - throw new MissingMethodException(typeName, methodName); + throw new MissingMethodException(typeName, methodName); return method.CreateDelegate(); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/LocalFrameworkReferences.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/LocalFrameworkReferences.cs index 0a34b77d..b9de061c 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/LocalFrameworkReferences.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/LocalFrameworkReferences.cs @@ -61,8 +61,8 @@ public static ImmutableArray FromTargetingPack() { string candidate = Path.Combine(pack, "ref", TargetFrameworkFolder); if (Directory.Exists(candidate) - && TryParsePackVersion(Path.GetFileName(pack), out Version? version) - && (bestVersion is null || version > bestVersion)) + && TryParsePackVersion(Path.GetFileName(pack), out Version? version) + && (bestVersion is null || version > bestVersion)) { best = candidate; bestVersion = version; diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ModelGraph.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ModelGraph.cs index 3a7c5c80..a4030574 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ModelGraph.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ModelGraph.cs @@ -69,7 +69,7 @@ private static void Visit(object? value, string path, HashSet visited, i } foreach (FieldInfo field in - type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { Visit(field.GetValue(value), $"{path}.{field.Name}", visited, depth + 1); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ProductionSpecs.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ProductionSpecs.cs index e64aef7a..a445f854 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ProductionSpecs.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ProductionSpecs.cs @@ -61,7 +61,7 @@ public static IReadOnlySet WiredFileNames() private static string Read(string resourceName) { using Stream stream = Resources.GetManifestResourceStream(resourceName) - ?? throw new InvalidOperationException("Missing embedded resource " + resourceName + "."); + ?? throw new InvalidOperationException("Missing embedded resource " + resourceName + "."); using StreamReader reader = new(stream); return reader.ReadToEnd(); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/SpecSources.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/SpecSources.cs index 904eece5..7a5d7538 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/SpecSources.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/SpecSources.cs @@ -10,12 +10,6 @@ internal static class SpecSources public const string Ce77 = "contract: ce77\nprovenance: ExactInstalledFile: CE 7.7 celua.txt test fixture\nminimum-ce: 7.7.0.10621\narchitecture: x64\nthread: unknown\nownership: none\n"; - /// A ce77 header block for and , blank line included. - public static string Ce77Header(string ns, string type) - { - return "namespace: " + ns + "\ntype: " + type + "\n" + Ce77 + "\n"; - } - /// /// The nominal case: two scalar reads (Try form) and two scalar writes (throwing form, boolean return), sharing /// no global. @@ -187,4 +181,10 @@ public static string Ce77Header(string ns, string type) nil: none doc: Calls a global with no arguments and no result. """; + + /// A ce77 header block for and , blank line included. + public static string Ce77Header(string ns, string type) + { + return "namespace: " + ns + "\ntype: " + type + "\n" + Ce77 + "\n"; + } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/ProductionSpecsTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/ProductionSpecsTests.cs index b3c1c3f4..be8cd508 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/ProductionSpecsTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/ProductionSpecsTests.cs @@ -32,7 +32,8 @@ public void Every_production_spec_parses_without_issues() SpecFileModel spec = SpecFileParser.Parse(fileName, text); Assert.True(spec.Issues.IsEmpty, - fileName + ": " + string.Join(" | ", spec.Issues.AsImmutableArray().Select(static i => i.Line + ": " + i.Message))); + fileName + ": " + string.Join(" | ", + spec.Issues.AsImmutableArray().Select(static i => i.Line + ": " + i.Message))); Assert.NotEqual(string.Empty, spec.TypeName, StringComparer.Ordinal); } } @@ -62,7 +63,8 @@ public void Every_production_spec_cites_the_pinned_celua_sha256() { SpecFileContract contract = Assert.IsType(SpecFileParser.Parse(fileName, text).Contract); - Assert.StartsWith("ExactInstalledFile: CE 7.7.0.10621 celua.txt", contract.Provenance, StringComparison.Ordinal); + Assert.StartsWith("ExactInstalledFile: CE 7.7.0.10621 celua.txt", contract.Provenance, + StringComparison.Ordinal); Assert.EndsWith("SHA-256 " + CeluaSha256, contract.Provenance, StringComparison.Ordinal); } } @@ -95,7 +97,8 @@ public void Unwired_specs_with_entries_are_reviewed_reservations() } Assert.True(ReviewedUnwiredSpecs.Contains(fileName), - fileName + " declares entries but is neither wired into CheatEngine.SDK.Engine nor a reviewed reservation."); + fileName + + " declares entries but is neither wired into CheatEngine.SDK.Engine nor a reviewed reservation."); } } @@ -107,7 +110,8 @@ public void Production_specs_never_claim_main_thread_affinity_without_evidence() SpecFileContract contract = Assert.IsType(SpecFileParser.Parse(fileName, text).Contract); Assert.True(contract.ThreadAffinity is "unknown" or "any", - fileName + " claims thread '" + contract.ThreadAffinity + "' without CE 7.7 evidence (audit SRC02-02)."); + fileName + " claims thread '" + contract.ThreadAffinity + + "' without CE 7.7 evidence (audit SRC02-02)."); } } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/SpecFileParserTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/SpecFileParserTests.cs index 37a52a68..67fc81bc 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/SpecFileParserTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/SpecFileParserTests.cs @@ -106,8 +106,8 @@ public void Indentation_and_CRLF_line_endings_are_tolerated() string text = SpecSources.SingleTry.Replace("\r\n", "\n", StringComparison.Ordinal) .Replace("\n", "\r\n", StringComparison.Ordinal); text = " namespace: Demo.One\r\n type: One\r\n" + - SpecSources.Ce77.Replace("\n", "\r\n ", StringComparison.Ordinal) + "\r\n" + - text[text.IndexOf("global:", StringComparison.Ordinal)..]; + SpecSources.Ce77.Replace("\n", "\r\n ", StringComparison.Ordinal) + "\r\n" + + text[text.IndexOf("global:", StringComparison.Ordinal)..]; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -278,7 +278,8 @@ public void An_entry_missing_a_required_key_is_dropped(string missingKey) '\n', entry.Split('\n').Where(line => !line.StartsWith(missingKey + ":", StringComparison.Ordinal))); - SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", SpecSources.Ce77Header("Demo", "T") + edited); + SpecFileModel spec = + SpecFileParser.Parse("x.cheatengine-sdk-api.txt", SpecSources.Ce77Header("Demo", "T") + edited); Assert.Empty(spec.Calls.AsSpan().ToArray()); Assert.Contains(spec.Issues, issue => issue.Message.Contains("'" + missingKey + "'", StringComparison.Ordinal)); @@ -351,7 +352,7 @@ public void A_duplicate_entry_key_drops_the_entry() public void An_invalid_lua_global_name_drops_the_entry(string badName) { string text = "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + "\nglobal: " + badName + - "\nmethod: M\nform: try\narg: address:address\nresult: value:int32\nnil: none\ndoc: d.\n"; + "\nmethod: M\nform: try\narg: address:address\nresult: value:int32\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -567,8 +568,9 @@ public void A_throwing_entry_without_a_return_is_a_void_wrapper() [InlineData("arg: 1bad:address")] public void A_malformed_or_unknown_kind_argument_drops_the_entry(string argLine) { - string text = "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + "\nglobal: readInteger\nmethod: M\nform: try\n" + argLine + - "\nresult: value:int32\nnil: none\ndoc: d.\n"; + string text = "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + + "\nglobal: readInteger\nmethod: M\nform: try\n" + argLine + + "\nresult: value:int32\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -582,8 +584,9 @@ public void A_malformed_or_unknown_kind_argument_drops_the_entry(string argLine) [InlineData("fixed: boolean:true; System.Console.WriteLine()")] public void A_fixed_argument_accepts_only_boolean_literals(string fixedLine) { - string text = "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + "\nglobal: readInteger\nmethod: M\nform: try\narg: address:address\n" + - fixedLine + "\nresult: value:int32\nnil: none\ndoc: d.\n"; + string text = "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + + "\nglobal: readInteger\nmethod: M\nform: try\narg: address:address\n" + + fixedLine + "\nresult: value:int32\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -864,7 +867,8 @@ public void Invalid_ce77_contract_facts_report_each_exact_value_location() public void An_invalid_argument_kind_records_its_value_column() { const string Text = - "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + "\n global: readInteger\n method: M\n form: try\n arg: address:notakind\n result: value:int32\n nil: none\n doc: d.\n"; + "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + + "\n global: readInteger\n method: M\n form: try\n arg: address:notakind\n result: value:int32\n nil: none\n doc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", Text); @@ -878,7 +882,8 @@ public void An_invalid_argument_kind_records_its_value_column() public void Parameter_and_generated_member_identity_collisions_drop_the_affected_entries() { const string Text = - "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + "\nglobal: readInteger\nmethod: BadParameter\nform: try\narg: __L:int32\nresult: value:int32\nnil: none\ndoc: bad.\n\nglobal: readInteger\nmethod: Read\nform: try\narg: address:address\nresult: value:int32\nnil: none\ndoc: raw core.\n\nglobal: readQword\nmethod: __ReadRaw\nform: try\nresult: value:int64\nnil: none\ndoc: collision.\n"; + "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + + "\nglobal: readInteger\nmethod: BadParameter\nform: try\narg: __L:int32\nresult: value:int32\nnil: none\ndoc: bad.\n\nglobal: readInteger\nmethod: Read\nform: try\narg: address:address\nresult: value:int32\nnil: none\ndoc: raw core.\n\nglobal: readQword\nmethod: __ReadRaw\nform: try\nresult: value:int64\nnil: none\ndoc: collision.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", Text); @@ -893,7 +898,8 @@ public void Parameter_and_generated_member_identity_collisions_drop_the_affected public void A_parameter_named_operation_is_rejected_as_an_emitter_local_collision() { const string Text = - "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + "\nglobal: readInteger\nmethod: BadOperation\nform: try\narg: __operation:int32\nresult: value:int32\nnil: none\ndoc: bad.\n"; + "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + + "\nglobal: readInteger\nmethod: BadOperation\nform: try\narg: __operation:int32\nresult: value:int32\nnil: none\ndoc: bad.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", Text); @@ -919,7 +925,8 @@ public void Spec_with_entries_without_contract_reports_the_missing_ce77_contract Assert.Contains("'contract: ce77'", issue.Message, StringComparison.Ordinal); // A header-only reservation stays readable without the contract: it generates nothing either way. - SpecFileModel reservation = SpecFileParser.Parse("reservation.cheatengine-sdk-api.txt", "namespace: Demo\ntype: T\n"); + SpecFileModel reservation = + SpecFileParser.Parse("reservation.cheatengine-sdk-api.txt", "namespace: Demo\ntype: T\n"); Assert.True(reservation.Issues.IsEmpty); Assert.Null(reservation.Contract); } @@ -928,7 +935,7 @@ public void Spec_with_entries_without_contract_reports_the_missing_ce77_contract public void Fixed_and_optional_arguments_keep_their_declaration_order() { string text = SpecSources.Ce77Header("Demo", "T") + - "global: g\nmethod: G\nform: throwing\narg: a:int32\nfixed: boolean:true\narg: b:int64\nopt: c:address\nopt: d:string\nnil: none\ndoc: d.\n"; + "global: g\nmethod: G\nform: throwing\narg: a:int32\nfixed: boolean:true\narg: b:int64\nopt: c:address\nopt: d:string\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -949,7 +956,7 @@ public void Fixed_and_optional_arguments_keep_their_declaration_order() public void Argument_after_an_optional_argument_is_refused(string arguments, string message) { string text = SpecSources.Ce77Header("Demo", "T") + "global: g\nmethod: G\nform: throwing\n" + arguments + - "nil: none\ndoc: d.\n"; + "nil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -960,7 +967,8 @@ public void Argument_after_an_optional_argument_is_refused(string arguments, str } [Theory] - [InlineData("try", "opt-result: a:int32\nresult: b:int32\n", "'b:int32' is a required 'result' after an 'opt-result'")] + [InlineData("try", "opt-result: a:int32\nresult: b:int32\n", + "'b:int32' is a required 'result' after an 'opt-result'")] [InlineData("outcome", "rest: a:int64\nresult: b:int32\n", "'b:int32' must be declared before the 'rest' result")] [InlineData("outcome", "opt-result: a:string?\n", "'string?' cannot be an 'opt-result' kind")] [InlineData("outcome", "rest: a:address\n", "'address' cannot be a 'rest' kind")] @@ -968,7 +976,7 @@ public void Argument_after_an_optional_argument_is_refused(string arguments, str public void Optional_result_before_a_required_result_is_refused(string form, string results, string message) { string text = SpecSources.Ce77Header("Demo", "T") + "global: g\nmethod: G\nform: " + form + "\n" + results + - "nil: none\ndoc: d.\n"; + "nil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -982,8 +990,8 @@ public void Optional_result_before_a_required_result_is_refused(string form, str public void Outcome_form_is_parsed() { string text = SpecSources.Ce77Header("Demo", "T") + - "global: g\nmethod: G\nform: outcome\narg: a:address\nresult: first:int64\nopt-result: second:address\nrest: values:double\nnil: absence\ndoc: d.\n\n" + - "global: beep\nmethod: Beep\nform: outcome\nnil: none\ndoc: d.\n"; + "global: g\nmethod: G\nform: outcome\narg: a:address\nresult: first:int64\nopt-result: second:address\nrest: values:double\nnil: absence\ndoc: d.\n\n" + + "global: beep\nmethod: Beep\nform: outcome\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -1004,7 +1012,7 @@ public void Outcome_form_is_parsed() public void Rest_result_requires_the_outcome_form() { string text = SpecSources.Ce77Header("Demo", "T") + - "global: g\nmethod: TryG\nform: try\nresult: first:int32\nrest: values:int32\nnil: none\ndoc: d.\n"; + "global: g\nmethod: TryG\nform: try\nresult: first:int32\nrest: values:int32\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -1020,12 +1028,13 @@ public void Rest_result_requires_the_outcome_form() public void Reformatting_a_spec_keeps_its_contract_and_call_model() { string compact = SpecSources.Ce77Header("Demo", "T") + - "global: g\nmethod: G\nform: outcome\narg: a:int32\nopt: b:address\nresult: r:int64\nopt-result: s:string\nnil: absence\ndoc: Reads.\n"; + "global: g\nmethod: G\nform: outcome\narg: a:int32\nopt: b:address\nresult: r:int64\nopt-result: s:string\nnil: absence\ndoc: Reads.\n"; string reformatted = "# reformatted\r\n namespace: Demo \r\n\ttype: T\r\n" + - SpecSources.Ce77.Replace("\n", "\r\n # a comment inside the header\r\n", StringComparison.Ordinal) + - "\r\n\r\n # a comment before the entry\r\n global: g\r\n method: G\r\n # a comment inside the entry\r\n" + - " form:outcome\r\n arg: a:int32\r\n opt: b:address \r\n result: r:int64\r\n opt-result: s:string\r\n" + - " nil: absence\r\n doc: Reads.\r\n\r\n"; + SpecSources.Ce77.Replace("\n", "\r\n # a comment inside the header\r\n", + StringComparison.Ordinal) + + "\r\n\r\n # a comment before the entry\r\n global: g\r\n method: G\r\n # a comment inside the entry\r\n" + + " form:outcome\r\n arg: a:int32\r\n opt: b:address \r\n result: r:int64\r\n opt-result: s:string\r\n" + + " nil: absence\r\n doc: Reads.\r\n\r\n"; SpecFileModel first = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", compact); SpecFileModel second = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", reformatted); diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/ContractIdentityTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/ContractIdentityTests.cs index eb0bdbdc..5399c285 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/ContractIdentityTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/ContractIdentityTests.cs @@ -187,8 +187,8 @@ private static void AssertNoSourceErrors(GeneratorRun run) Assert.DoesNotContain( run.OutputCompilation.GetDiagnostics(TestContext.Current.CancellationToken), static diagnostic => diagnostic.Severity == DiagnosticSeverity.Error - && (diagnostic.Location.SourceTree is null - || !diagnostic.Location.SourceTree.FilePath.EndsWith(".g.cs", - StringComparison.Ordinal))); + && (diagnostic.Location.SourceTree is null + || !diagnostic.Location.SourceTree.FilePath.EndsWith(".g.cs", + StringComparison.Ordinal))); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs index e4cb4d9d..2803321c 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs @@ -61,7 +61,7 @@ public void Generator_display_name_is_escaped_into_a_u8_literal(string caseKey) // Holds because the plugin type of these cases (Demo.DemoPlugin) is ASCII: whatever the display name is, the // literal adds no other character. Identifiers are written as declared (PluginLocationTests, non-ASCII case). Assert.All(generated, - static c => Assert.True(c is '\n' or (>= ' ' and <= '~'), + static c => Assert.True(c is '\n' or >= ' ' and <= '~', $"Non-ASCII character U+{(int) c:X4} in generated text.")); run.AssertCompilesClean(); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NominalOutputTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NominalOutputTests.cs index e4c12e78..4ff28570 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NominalOutputTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NominalOutputTests.cs @@ -105,8 +105,11 @@ public void Generator_bootstrap_constructs_the_plugin_without_reflection() GeneratorRun run = roslyn.Run(PluginSources.Nominal); string text = run.SingleGeneratedText; - foreach (string reflective in (string[]) ["Activator", "CreateInstance", "GetTypes", "GetType(", "typeof(", - "System.Reflection", "Assembly."]) + foreach (string reflective in (string[]) + [ + "Activator", "CreateInstance", "GetTypes", "GetType(", "typeof(", + "System.Reflection", "Assembly." + ]) { Assert.DoesNotContain(reflective, text, StringComparison.Ordinal); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/RealAssemblyCompilationTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/RealAssemblyCompilationTests.cs index 025f7679..d6c8333c 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/RealAssemblyCompilationTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/RealAssemblyCompilationTests.cs @@ -87,7 +87,7 @@ [new EntryPointGenerator().AsSourceGenerator()], .. outputCompilation .GetDiagnostics(TestContext.Current.CancellationToken) .Where(static diagnostic => diagnostic.Severity >= DiagnosticSeverity.Warning && - !IsMissingDocumentationInTestInput(diagnostic)) + !IsMissingDocumentationInTestInput(diagnostic)) ]; Assert.True( @@ -101,7 +101,7 @@ .. outputCompilation private static bool IsMissingDocumentationInTestInput(Diagnostic diagnostic) { return string.Equals(diagnostic.Id, "CS1591", StringComparison.Ordinal) - && diagnostic.Location.SourceTree is { FilePath: string path } - && !path.EndsWith(".g.cs", StringComparison.Ordinal); + && diagnostic.Location.SourceTree is { FilePath: string path } + && !path.EndsWith(".g.cs", StringComparison.Ordinal); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/GeneratorRun.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/GeneratorRun.cs index fcf3ffe4..ff87ce3a 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/GeneratorRun.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/GeneratorRun.cs @@ -76,7 +76,7 @@ public void AssertCompilesClean() .. OutputCompilation .GetDiagnostics(TestContext.Current.CancellationToken) .Where(static diagnostic => diagnostic.Severity >= DiagnosticSeverity.Warning && - !IsMissingDocumentationInTestInput(diagnostic)) + !IsMissingDocumentationInTestInput(diagnostic)) ]; Assert.True(problems.Length == 0, @@ -88,7 +88,7 @@ .. OutputCompilation private static bool IsMissingDocumentationInTestInput(Diagnostic diagnostic) { return string.Equals(diagnostic.Id, "CS1591", StringComparison.Ordinal) - && diagnostic.Location.SourceTree is { FilePath: string path } - && !path.EndsWith(".g.cs", StringComparison.Ordinal); + && diagnostic.Location.SourceTree is { FilePath: string path } + && !path.EndsWith(".g.cs", StringComparison.Ordinal); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LoadedBootstrap.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LoadedBootstrap.cs index 3a6d4aa7..138fd492 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LoadedBootstrap.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LoadedBootstrap.cs @@ -25,7 +25,7 @@ private LoadedBootstrap(AssemblyLoadContext context, Assembly hosting, Assembly // Same lookup as the host: type 'CESDK.CESDK' in the plugin assembly, static method 'CEPluginInitialize'. Type entryPoint = plugin.GetType("CESDK.CESDK", true)!; MethodInfo method = entryPoint.GetMethod("CEPluginInitialize", BindingFlags.Public | BindingFlags.Static) - ?? throw new MissingMethodException("CESDK.CESDK", "CEPluginInitialize"); + ?? throw new MissingMethodException("CESDK.CESDK", "CEPluginInitialize"); _initialize = method.CreateDelegate>(); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LocalFrameworkReferences.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LocalFrameworkReferences.cs index 678a7dff..5cb4b2ef 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LocalFrameworkReferences.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LocalFrameworkReferences.cs @@ -63,8 +63,8 @@ public static ImmutableArray FromTargetingPack() { string candidate = Path.Combine(pack, "ref", TargetFrameworkFolder); if (Directory.Exists(candidate) - && TryParsePackVersion(Path.GetFileName(pack), out Version? version) - && (bestVersion is null || version > bestVersion)) + && TryParsePackVersion(Path.GetFileName(pack), out Version? version) + && (bestVersion is null || version > bestVersion)) { best = candidate; bestVersion = version; diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/ModelGraph.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/ModelGraph.cs index 357f5c77..ee75bfd1 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/ModelGraph.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/ModelGraph.cs @@ -69,7 +69,7 @@ private static void Visit(object? value, string path, HashSet visited, i } foreach (FieldInfo field in - type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { Visit(field.GetValue(value), $"{path}.{field.Name}", visited, depth + 1); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Model/BootstrapModelTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Model/BootstrapModelTests.cs index cbb2c58a..eaf158ee 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Model/BootstrapModelTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Model/BootstrapModelTests.cs @@ -68,32 +68,17 @@ public void PluginModel_is_valid_only_without_issues() { Assert.True(ValidA.IsValid); Assert.False(Invalid.IsValid); - Assert.False((ValidA with - { - Issues = PluginShapeIssues.InvalidName - }).IsValid); + Assert.False((ValidA with { Issues = PluginShapeIssues.InvalidName }).IsValid); } [Fact] public void Models_compare_by_value() { Assert.Equal(new PluginModel("global::A", "Plugin A", "", PluginShapeIssues.None), ValidA); - Assert.NotEqual(ValidA with - { - DisplayName = "other" - }, ValidA); - Assert.NotEqual(ValidA with - { - FullyQualifiedTypeName = "global::Z" - }, ValidA); - Assert.NotEqual(ValidA with - { - DeclaredDiagnosticIds = "EXP001" - }, ValidA); - Assert.NotEqual(ValidA with - { - Issues = PluginShapeIssues.Static - }, ValidA); + Assert.NotEqual(ValidA with { DisplayName = "other" }, ValidA); + Assert.NotEqual(ValidA with { FullyQualifiedTypeName = "global::Z" }, ValidA); + Assert.NotEqual(ValidA with { DeclaredDiagnosticIds = "EXP001" }, ValidA); + Assert.NotEqual(ValidA with { Issues = PluginShapeIssues.Static }, ValidA); Assert.Equal(new EntryPointOptions(true), On); Assert.NotEqual(Off, On); Assert.Equal( diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalOptionalArgumentEndToEndTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalOptionalArgumentEndToEndTests.cs index d127e7b0..4b1dfc51 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalOptionalArgumentEndToEndTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalOptionalArgumentEndToEndTests.cs @@ -133,8 +133,11 @@ public void Warm_optional_argument_form_allocates_nothing() AllocationGate.AssertZero(() => { if (!tryArity(1, LuaOptional.Of(2L), out long present) || present != 2 - || !tryArity(1, default, out long omitted) || omitted != 1 - || !detailed(1, LuaOptional.Nil(), LuaOptional.Of(true), out long nil).IsSuccess || nil != 3) + || !tryArity(1, default, out long omitted) || + omitted != 1 + || !detailed(1, LuaOptional.Nil(), + LuaOptional.Of(true), out long nil).IsSuccess || + nil != 3) { throw new InvalidOperationException("wrong count"); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalQ22MatrixEndToEndTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalQ22MatrixEndToEndTests.cs index 0110fc75..c0da154c 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalQ22MatrixEndToEndTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalQ22MatrixEndToEndTests.cs @@ -296,7 +296,8 @@ public void Custom_marshaller_exception_after_a_successful_call_propagates_with_ EvenDelegate even = assembly.Delegate(Q22Type, "Even"); // A marshaller's own exception is not a Lua failure: no form swallows or reclassifies it. - Assert.Equal("negative token", Assert.Throws(() => tryEven("negative", out _)).Message); + Assert.Equal("negative token", + Assert.Throws(() => tryEven("negative", out _)).Message); Assert.Equal(0, L.Top); Assert.Throws(() => outcome("negative", out _)); Assert.Equal(0, L.Top); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalResultCountEndToEndTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalResultCountEndToEndTests.cs index 09f6ebef..bde33255 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalResultCountEndToEndTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalResultCountEndToEndTests.cs @@ -59,7 +59,8 @@ public void Missing_required_result_before_an_optional_one_is_missing_not_nil() Assert.Equal(LuaOperationStatusKind.MissingResult, detailed(0, out long missing, out _).Kind); Assert.Equal(0, missing); Assert.Equal(LuaOperationStatusKind.NilResult, detailed(1, out _, out _).Kind); - Assert.Equal(LuaOperationStatusKind.Success, detailed(2, out long onlyFirst, out LuaOptional absent).Kind); + Assert.Equal(LuaOperationStatusKind.Success, + detailed(2, out long onlyFirst, out LuaOptional absent).Kind); Assert.Equal(7, onlyFirst); Assert.True(absent.IsOmitted); Assert.Equal(LuaOperationStatusKind.Success, detailed(3, out long first, out LuaOptional second).Kind); @@ -67,7 +68,8 @@ public void Missing_required_result_before_an_optional_one_is_missing_not_nil() Assert.Equal(LuaOptional.Of(8L), second); Assert.Equal(LuaOperationStatusKind.Success, detailed(8, out _, out LuaOptional explicitNil).Kind); Assert.True(explicitNil.IsNil); - Assert.Equal(LuaOperationStatusKind.InvalidResult, detailed(7, out long defaulted, out LuaOptional bad).Kind); + Assert.Equal(LuaOperationStatusKind.InvalidResult, + detailed(7, out long defaulted, out LuaOptional bad).Kind); Assert.Equal(0, defaulted); Assert.True(bad.IsOmitted); @@ -129,7 +131,8 @@ public void Variadic_result_copies_every_value_and_reports_the_count() LuaTest.Run(L, OptionalBindingSources.StandIns); GeneratedAssembly assembly = LoadSuite(roslyn); SequenceDelegate sequence = assembly.Delegate(OptionalsType, "Sequence"); - SequenceAfterOneDelegate afterOne = assembly.Delegate(OptionalsType, "SequenceAfterOne"); + SequenceAfterOneDelegate afterOne = + assembly.Delegate(OptionalsType, "SequenceAfterOne"); Span values = stackalloc long[8]; Assert.Equal(LuaOperationStatusKind.Success, sequence(3, default, values, out int count).Kind); @@ -165,7 +168,8 @@ public void Variadic_result_above_capacity_is_refused_with_the_needed_count_and_ LuaTest.Run(L, OptionalBindingSources.StandIns); GeneratedAssembly assembly = LoadSuite(roslyn); SequenceDelegate sequence = assembly.Delegate(OptionalsType, "Sequence"); - SequenceAfterOneDelegate afterOne = assembly.Delegate(OptionalsType, "SequenceAfterOne"); + SequenceAfterOneDelegate afterOne = + assembly.Delegate(OptionalsType, "SequenceAfterOne"); Span small = stackalloc long[2]; Assert.Equal(LuaOperationStatusKind.ResultCapacityExceeded, sequence(5, default, small, out int needed).Kind); @@ -249,7 +253,7 @@ public void Warm_optional_result_and_variadic_forms_allocate_nothing() AllocationGate.AssertZero(() => { if (!pair(3, out long first, out LuaOptional second).IsSuccess || !second.TryGetValue(out long value) - || !sequence(3, default, buffer, out int count).IsSuccess || count != 3) + || !sequence(3, default, buffer, out int count).IsSuccess || count != 3) { throw new InvalidOperationException("wrong results"); } @@ -279,6 +283,7 @@ private static GeneratedAssembly LoadSuite(RoslynFixture roslyn) private delegate LuaOperationStatus SequenceDelegate(int count, LuaOptional bad, Span values, out int valueCount); - private delegate LuaOperationStatus SequenceAfterOneDelegate(int count, out long first, out LuaOptional second, + private delegate LuaOperationStatus SequenceAfterOneDelegate(int count, out long first, + out LuaOptional second, Span rest, out int restCount); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/ContainingTypeTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/ContainingTypeTests.cs index 26790695..19d9becc 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/ContainingTypeTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/ContainingTypeTests.cs @@ -45,7 +45,7 @@ internal static partial class Bindings public void Generator_global_namespace_has_no_namespace_block() { GeneratorRun run = roslyn.Run(Usings + - "public static partial class Top { [LuaFunction(\"f\")] public static int F(int a) => a; }"); + "public static partial class Top { [LuaFunction(\"f\")] public static int F(int a) => a; }"); run.AssertCompilesClean(); string text = run.GeneratedText("Top.LuaFunctions.g.cs"); @@ -66,7 +66,7 @@ public void Generator_global_namespace_has_no_namespace_block() public void Generator_type_kinds_are_reopened_with_their_keyword(string declaration, string expectedPart) { GeneratorRun run = roslyn.Run(Usings + "namespace Demo; " + declaration + - " Holder { [LuaFunction(\"f\")] public static int F(int a) => a; [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, out int v); }"); + " Holder { [LuaFunction(\"f\")] public static int F(int a) => a; [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, out int v); }"); run.AssertCompilesClean(); Assert.Contains("\n " + expectedPart + " Holder\n {\n", @@ -109,7 +109,7 @@ public void Generator_types_differing_only_by_case_get_distinct_hint_names() // cannot tell "DemoType" and "demoType" apart (neither has a replaced character), so without disambiguation // AddSource throws ArgumentException on the second one and the whole generation pass crashes. const string Source = Usings + - "namespace Demo; public static partial class DemoType { [LuaFunction(\"f1\")] public static int F(int a) => a; } public static partial class demoType { [LuaFunction(\"f2\")] public static int F(int a) => a; }"; + "namespace Demo; public static partial class DemoType { [LuaFunction(\"f1\")] public static int F(int a) => a; } public static partial class demoType { [LuaFunction(\"f2\")] public static int F(int a) => a; }"; GeneratorRun run = roslyn.Run(Source); @@ -124,7 +124,7 @@ public void Generator_types_differing_only_by_case_get_distinct_hint_names() public void Generator_non_ascii_type_name_gets_a_hashed_hint_name_and_an_unescaped_declaration() { GeneratorRun run = roslyn.Run(Usings + - "namespace Demo; public static partial class Caf\u00E9 { [LuaFunction(\"f\")] public static int F(int a) => a; }"); + "namespace Demo; public static partial class Caf\u00E9 { [LuaFunction(\"f\")] public static int F(int a) => a; }"); run.AssertCompilesClean(); string hintName = Assert.Single(run.HintNames); @@ -186,8 +186,8 @@ public void Generator_type_split_across_files_gets_one_file() public void Generator_repeats_the_defining_declarations_modifiers(string declared, string emitted) { GeneratorRun run = roslyn.Run(Usings + "namespace Demo; public partial class Holder { [LuaGlobal(\"g\")] " + - declared + - " bool TryG(nuint a, out int v); }"); + declared + + " bool TryG(nuint a, out int v); }"); run.AssertCompilesClean(); Assert.Contains("\n " + emitted + " bool TryG(nuint a, out int v)\n", run.SingleGeneratedText, @@ -214,7 +214,7 @@ namespace Demo; public void Generator_old_style_partial_void_without_accessibility_is_implemented_without_one() { GeneratorRun run = roslyn.Run(Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"beep\")] static partial void Beep(); }"); + "namespace Demo; public static partial class Holder { [LuaGlobal(\"beep\")] static partial void Beep(); }"); run.AssertCompilesClean(); Assert.Contains("\n static partial void Beep()\n", run.SingleGeneratedText, StringComparison.Ordinal); @@ -224,7 +224,7 @@ public void Generator_old_style_partial_void_without_accessibility_is_implemente public void Generator_private_target_is_reachable_from_the_thunk() { GeneratorRun run = roslyn.Run(Usings + - "namespace Demo; internal static partial class Holder { [LuaFunction(\"f\")] private static int F(int a) => a; }"); + "namespace Demo; internal static partial class Holder { [LuaFunction(\"f\")] private static int F(int a) => a; }"); run.AssertCompilesClean(); Assert.Contains("global::Demo.Holder.F(__arg0)", run.SingleGeneratedText, StringComparison.Ordinal); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/DefaultVerifierTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/DefaultVerifierTests.cs index 53a0bcc1..b6415ec7 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/DefaultVerifierTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/DefaultVerifierTests.cs @@ -50,8 +50,7 @@ private static CSharpSourceGeneratorTest { // A framework moniker WITHOUT a reference-assembly package: nothing is resolved through NuGet; the // framework and the SDK come from the local installation and this process (no network). - ReferenceAssemblies = new ReferenceAssemblies("net10.0"), - CompilerDiagnostics = CompilerDiagnostics.Warnings + ReferenceAssemblies = new ReferenceAssemblies("net10.0"), CompilerDiagnostics = CompilerDiagnostics.Warnings }; // The test declarations are undocumented public members: CS1591 is theirs, not the generated file's. diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/IncrementalityTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/IncrementalityTests.cs index 38f3dd4b..6a038773 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/IncrementalityTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/IncrementalityTests.cs @@ -37,8 +37,8 @@ public void Pipeline_first_run_tracks_every_named_step() GeneratorRun run = roslyn.Run(BindingSources.Functions, BindingSources.Globals, ObjectBindings); foreach (string stepName in run.Result.TrackedSteps.Keys - .Where(TrackingNames.IsCheatEngineSdkStep) - .Order(StringComparer.Ordinal)) + .Where(TrackingNames.IsCheatEngineSdkStep) + .Order(StringComparer.Ordinal)) { Assert.All(StepAssert.Reasons(run.Result, stepName), static reason => Assert.Equal(IncrementalStepRunReason.New, reason)); @@ -329,8 +329,8 @@ public void Pipeline_step_values_hold_no_roslyn_objects() int visited = 0; foreach (string stepName in run.Result.TrackedSteps.Keys - .Where(TrackingNames.IsCheatEngineSdkStep) - .Order(StringComparer.Ordinal)) + .Where(TrackingNames.IsCheatEngineSdkStep) + .Order(StringComparer.Ordinal)) { Assert.True( run.Result.TrackedSteps.TryGetValue(stepName, out ImmutableArray steps), @@ -352,7 +352,8 @@ public void Pipeline_step_values_hold_no_roslyn_objects() private static string[] OptionalMembers() { string body = OptionalBindingSources.GlobalSuite.ReplaceLineEndings("\n"); - int open = body.IndexOf("{\n", body.IndexOf("class Optionals", StringComparison.Ordinal), StringComparison.Ordinal); + int open = body.IndexOf("{\n", body.IndexOf("class Optionals", StringComparison.Ordinal), + StringComparison.Ordinal); int close = body.LastIndexOf('}'); return [ diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaFunctionOutputTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaFunctionOutputTests.cs index abc96665..3c2d7e43 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaFunctionOutputTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaFunctionOutputTests.cs @@ -49,10 +49,10 @@ public void Generator_function_suite_compiles_clean_and_declares_one_thunk_per_f run.AssertCompilesClean(); string text = run.SingleGeneratedText; foreach (string name in new[] - { - "add", "greet", "ping", "isint", "boom", "echo", "half", "negate", "step", "small", "scale", - "maybe" - }) + { + "add", "greet", "ping", "isint", "boom", "echo", "half", "negate", "step", "small", "scale", + "maybe" + }) { Assert.Contains("private static int __LuaThunk_" + name + "(nint __handle)", text, StringComparison.Ordinal); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaGlobalOutputTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaGlobalOutputTests.cs index 94b32321..8b65c81e 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaGlobalOutputTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaGlobalOutputTests.cs @@ -238,9 +238,9 @@ public void Generator_unannotated_out_string_result_gets_exactly_cs8601_the_docu .. run.OutputCompilation .GetDiagnostics(TestContext.Current.CancellationToken) .Where(static diagnostic => diagnostic.Severity >= DiagnosticSeverity.Warning - && !(string.Equals(diagnostic.Id, "CS1591", StringComparison.Ordinal) - && diagnostic.Location.SourceTree is { FilePath: string path } && - !path.EndsWith(".g.cs", StringComparison.Ordinal))) + && !(string.Equals(diagnostic.Id, "CS1591", StringComparison.Ordinal) + && diagnostic.Location.SourceTree is { FilePath: string path } && + !path.EndsWith(".g.cs", StringComparison.Ordinal))) ]; Diagnostic problem = Assert.Single(problems); Assert.Equal("CS8601", problem.Id); @@ -337,7 +337,8 @@ public void Generator_variadic_pair_is_emitted_only_for_the_outcome_form() Assert.Contains("return global::CheatEngine.SDK.Lua.CompilerServices.LuaCallSupport.Fail(__L, __top, __rest);", body, StringComparison.Ordinal); - const string TryForm = "using System;\nusing CheatEngine.SDK.Annotations.Lua;\nnamespace Demo; public static partial class Holder { [LuaGlobal(\"seq\")] public static partial bool TrySeq(int n, Span values, out int count); }"; + const string TryForm = + "using System;\nusing CheatEngine.SDK.Annotations.Lua;\nnamespace Demo; public static partial class Holder { [LuaGlobal(\"seq\")] public static partial bool TrySeq(int n, Span values, out int count); }"; roslyn.Run(TryForm).AssertNoOutput(); } @@ -351,9 +352,11 @@ public void Generator_outcome_form_with_several_results_defaults_every_other_res run.AssertCompilesClean(); string body = Section(run.SingleGeneratedText, "Divide(long a, long b", "\n }\n"); - Assert.Contains("remainder = default!;\n return global::CheatEngine.SDK.Lua.CompilerServices.LuaCallSupport.Fail(__L, __top, __L.IsNil(-2)", + Assert.Contains( + "remainder = default!;\n return global::CheatEngine.SDK.Lua.CompilerServices.LuaCallSupport.Fail(__L, __top, __L.IsNil(-2)", body, StringComparison.Ordinal); - Assert.Contains("quotient = default;\n return global::CheatEngine.SDK.Lua.CompilerServices.LuaCallSupport.Fail(__L, __top, __L.IsNil(-1)", + Assert.Contains( + "quotient = default;\n return global::CheatEngine.SDK.Lua.CompilerServices.LuaCallSupport.Fail(__L, __top, __L.IsNil(-1)", body, StringComparison.Ordinal); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaObjectOutputTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaObjectOutputTests.cs index d8e451f5..7a50be69 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaObjectOutputTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaObjectOutputTests.cs @@ -615,7 +615,7 @@ private static MethodDeclarationSyntax FindGeneratedMethod(CompilationUnitSyntax foreach (SyntaxNode node in root.DescendantNodes()) { if (node is MethodDeclarationSyntax candidate - && string.Equals(candidate.Identifier.ValueText, methodName, StringComparison.Ordinal)) + && string.Equals(candidate.Identifier.ValueText, methodName, StringComparison.Ordinal)) { Assert.Null(result); result = candidate; diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/NoOutputTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/NoOutputTests.cs index cd59d095..e9bcce09 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/NoOutputTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/NoOutputTests.cs @@ -385,13 +385,16 @@ public static TheoryData InvalidGlobals const string Status = "CheatEngine.SDK.Lua.Calls.LuaOperationStatus"; yield return ( "required argument after an optional one", - "public static partial class T { [LuaGlobal(\"g\")] public static partial int G(" + Optional + " a, int b); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial int G(" + Optional + + " a, int b); }"); yield return ( "required result after an optional one", - "public static partial class T { [LuaGlobal(\"g\")] public static partial bool TryG(out " + Optional + " a, out int b); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial bool TryG(out " + Optional + + " a, out int b); }"); yield return ( "copy-out result after an optional one", - "public static partial class T { [LuaGlobal(\"g\")] public static partial bool TryG(out " + Optional + " a, Span d, out int w); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial bool TryG(out " + Optional + + " a, Span d, out int w); }"); yield return ( "variadic pair in the Try form", "public static partial class T { [LuaGlobal(\"g\")] public static partial bool TryG(Span v, out int c); }"); @@ -400,31 +403,40 @@ public static TheoryData InvalidGlobals "public static partial class T { [LuaGlobal(\"g\")] public static partial void G(Span v, out int c); }"); yield return ( "result after the variadic pair", - "public static partial class T { [LuaGlobal(\"g\")] public static partial " + Status + " G(Span v, out int c, out int d); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial " + Status + + " G(Span v, out int c, out int d); }"); yield return ( "two variadic pairs", - "public static partial class T { [LuaGlobal(\"g\")] public static partial " + Status + " G(Span v, out int c, Span w, out int e); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial " + Status + + " G(Span v, out int c, Span w, out int e); }"); yield return ( "variadic string element", - "public static partial class T { [LuaGlobal(\"g\")] public static partial " + Status + " G(Span v, out int c); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial " + Status + + " G(Span v, out int c); }"); yield return ( "variadic span without a count", - "public static partial class T { [LuaGlobal(\"g\")] public static partial " + Status + " G(Span v); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial " + Status + + " G(Span v); }"); yield return ( "optional nullable string", - "public static partial class T { [LuaGlobal(\"g\")] public static partial int G(" + Optional + " a); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial int G(" + Optional + + " a); }"); yield return ( "optional object", - "public static partial class T { [LuaGlobal(\"g\")] public static partial int G(" + Optional + " a); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial int G(" + Optional + + " a); }"); yield return ( "nested optional", - "public static partial class T { [LuaGlobal(\"g\")] public static partial int G(" + Optional + "<" + Optional + "> a); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial int G(" + Optional + "<" + + Optional + "> a); }"); yield return ( "optional throwing return", - "public static partial class T { [LuaGlobal(\"g\")] public static partial " + Optional + " G(int a); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial " + Optional + + " G(int a); }"); yield return ( "optional with a C# default value", - "public static partial class T { [LuaGlobal(\"g\")] public static partial int G(" + Optional + " a = default); }"); + "public static partial class T { [LuaGlobal(\"g\")] public static partial int G(" + Optional + + " a = default); }"); } // CESDK2010 and CESDK2013 shapes of an exported function. @@ -433,21 +445,24 @@ public static TheoryData InvalidGlobals const string Optional = "CheatEngine.SDK.Lua.Marshalling.LuaOptional"; yield return ( "required parameter after an optional one", - "public static partial class T { [LuaFunction(\"f\")] public static int F(" + Optional + " a, int b) => b; }"); + "public static partial class T { [LuaFunction(\"f\")] public static int F(" + Optional + + " a, int b) => b; }"); yield return ( "optional return", - "public static partial class T { [LuaFunction(\"f\")] public static " + Optional + " F(int a) => default; }"); + "public static partial class T { [LuaFunction(\"f\")] public static " + Optional + + " F(int a) => default; }"); yield return ( "optional nullable string parameter", - "public static partial class T { [LuaFunction(\"f\")] public static int F(" + Optional + " a) => 0; }"); + "public static partial class T { [LuaFunction(\"f\")] public static int F(" + Optional + + " a) => 0; }"); } [Fact] public void Generator_non_trailing_optional_argument_emits_nothing() { const string Source = "using CheatEngine.SDK.Annotations.Lua;\nusing CheatEngine.SDK.Lua.Marshalling;\n" + - "namespace Demo; public static partial class T { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a, int b); " + - "[LuaFunction(\"f\")] public static int F(LuaOptional a, long b) => 0; }"; + "namespace Demo; public static partial class T { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a, int b); " + + "[LuaFunction(\"f\")] public static int F(LuaOptional a, long b) => 0; }"; roslyn.Run(Source).AssertNoOutput(); } @@ -547,7 +562,7 @@ public void Generator_invalid_global_shape_emits_nothing(string shape, string so public void Generator_no_attribute_emits_nothing() { GeneratorRun run = roslyn.Run(Usings + - "public static partial class T { public static int F(int a) => a; public static partial int G(int a); public static partial int G(int a) => a; }"); + "public static partial class T { public static int F(int a) => a; public static partial int G(int a); public static partial int G(int a) => a; }"); run.AssertNoOutput(); } @@ -560,7 +575,7 @@ public void Generator_same_name_source_LuaState_without_the_sdk_runtime_emits_no foreach (MetadataReference reference in roslyn.Environment.SdkReferences) { if (string.Equals(reference.Display, typeof(LuaState).Assembly.Location, - StringComparison.OrdinalIgnoreCase)) + StringComparison.OrdinalIgnoreCase)) { continue; } @@ -714,8 +729,8 @@ private static int Count(string text, string needle) { int count = 0; for (int index = text.IndexOf(needle, StringComparison.Ordinal); - index >= 0; - index = text.IndexOf(needle, index + needle.Length, StringComparison.Ordinal)) + index >= 0; + index = text.IndexOf(needle, index + needle.Length, StringComparison.Ordinal)) { count++; } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/PartialMethodSignatureTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/PartialMethodSignatureTests.cs index 9f641df7..7b214cb6 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/PartialMethodSignatureTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/PartialMethodSignatureTests.cs @@ -15,7 +15,7 @@ public sealed class PartialMethodSignatureTests(RoslynFixture roslyn) : IClassFi public void Generator_repeats_an_explicit_scoped_readonlyspan_argument() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(scoped System.ReadOnlySpan data, out int v); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(scoped System.ReadOnlySpan data, out int v); }"; GeneratorRun run = roslyn.Run(Source); @@ -31,8 +31,8 @@ public void Generator_repeats_an_explicit_scoped_readonlyspan_argument() public void Generator_repeats_optional_argument_and_result_types_exactly(string declared, string generated) { string source = Usings + "using CheatEngine.SDK.Lua.Calls;\nusing CheatEngine.SDK.Lua.Marshalling;\n" + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(int first, " + - declared + ", out LuaOptional result); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(int first, " + + declared + ", out LuaOptional result); }"; GeneratorRun run = roslyn.Run(source); @@ -47,7 +47,7 @@ public void Generator_repeats_optional_argument_and_result_types_exactly(string public void Generator_repeats_an_explicit_scoped_variadic_span() { const string Source = Usings + "using CheatEngine.SDK.Lua.Calls;\n" + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial LuaOperationStatus G(scoped System.Span values, out int count); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial LuaOperationStatus G(scoped System.Span values, out int count); }"; GeneratorRun run = roslyn.Run(Source); @@ -61,7 +61,7 @@ public void Generator_repeats_an_explicit_scoped_variadic_span() public void Generator_omits_scoped_when_the_defining_declaration_did() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(System.ReadOnlySpan data, out int v); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(System.ReadOnlySpan data, out int v); }"; GeneratorRun run = roslyn.Run(Source); @@ -76,7 +76,7 @@ public void Generator_omits_scoped_when_the_defining_declaration_did() public void Generator_repeats_an_explicit_scoped_copyout_destination() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, scoped System.Span destination, out int written); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, scoped System.Span destination, out int written); }"; GeneratorRun run = roslyn.Run(Source); @@ -89,7 +89,7 @@ public void Generator_repeats_an_explicit_scoped_copyout_destination() public void Generator_omits_scoped_on_the_copyout_destination_when_the_defining_declaration_did() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, System.Span destination, out int written); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, System.Span destination, out int written); }"; GeneratorRun run = roslyn.Run(Source); @@ -105,7 +105,7 @@ public void Generator_scoped_out_result_of_a_non_ref_struct_type_needs_no_specia // 'scoped' on an 'out' parameter of a non-ref-struct type does not affect partial-signature matching (the // compiler accepts a mismatch there), so the emitter never needs to repeat it; this pins that down. const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, scoped out int v); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, scoped out int v); }"; GeneratorRun run = roslyn.Run(Source); @@ -118,7 +118,7 @@ public void Generator_scoped_out_result_of_a_non_ref_struct_type_needs_no_specia public void Generator_preserves_the_extension_receiver_in_the_implementing_declaration() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(this nuint address, out int value); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(this nuint address, out int value); }"; GeneratorRun run = roslyn.Run(Source); @@ -131,7 +131,7 @@ public void Generator_preserves_the_extension_receiver_in_the_implementing_decla public void Generator_preserves_the_extension_receiver_on_a_copyout_destination() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(this System.Span destination, out int written); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(this System.Span destination, out int written); }"; GeneratorRun run = roslyn.Run(Source); @@ -144,7 +144,7 @@ public void Generator_preserves_the_extension_receiver_on_a_copyout_destination( public void Generator_qualifies_the_cache_when_a_parameter_uses_its_name() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial void G(int s_luaGlobal_g); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial void G(int s_luaGlobal_g); }"; GeneratorRun run = roslyn.Run(Source); @@ -159,7 +159,7 @@ public void Generator_parameter_named_like_a_generated_local_is_skipped_without_ // A generated partial body shares its parameter scope with the defining declaration. Do not emit CS0136 and // leave the analyzer to report the precise CESDK2007 collision at the author declaration. const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint __L, out int v); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint __L, out int v); }"; GeneratorRun run = roslyn.Run(Source); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/FidelityBindingSources.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/FidelityBindingSources.cs index a36ffa8a..7fa9d116 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/FidelityBindingSources.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/FidelityBindingSources.cs @@ -8,30 +8,6 @@ namespace CheatEngine.SDK.SourceGenerators.LuaBindings.Tests.Infrastructure; /// internal static class FidelityBindingSources { - /// - /// q22(kind) returns one shape per kind: nil, false, true, 0, 42, 7 (odd), -2 - /// (negative), '', {}, no value at all, a string error and a table error whose __tostring - /// raises. - /// - public static ReadOnlySpan Q22StandIns => """ - local raising = setmetatable({}, { __tostring = function() error('tostring boom') end }) - local cases = { - ['nil'] = function() return nil end, - ['false'] = function() return false end, - ['true'] = function() return true end, - zero = function() return 0 end, - value = function() return 42 end, - odd = function() return 7 end, - negative = function() return -2 end, - empty = function() return '' end, - table = function() return {} end, - none = function() end, - raise = function() error('boom') end, - raise_table = function() error(raising) end, - } - function q22(kind) return cases[kind]() end - """u8; - /// Every Q22 form: Try, Outcome and Throwing over integer, boolean, string, optional and custom results. public const string Q22Suite = """ using System; @@ -110,11 +86,6 @@ public static partial class Q22 } """; - /// boundary(expression) evaluates a Lua expression, so each row is a value Lua itself produced. - public static ReadOnlySpan NumericStandIns => """ - function boundary(expression) return assert(load('return ' .. expression))() end - """u8; - /// Integer, 64-bit and address results in every form, and the same kinds as exported function arguments. public const string NumericSuite = """ using CheatEngine.SDK.Annotations.Lua; @@ -162,18 +133,6 @@ public static partial class Numbers } """; - /// - /// s_value(key) returns a string with embedded NULs, multibyte UTF-8, invalid UTF-8 or the empty string; - /// s_len returns the byte length Lua received, s_echo the string itself, s_type its type. - /// - public static ReadOnlySpan StringStandIns => """ - local values = { nul = 'a\0b\0', multibyte = '\u{E9}\u{6F22}\u{1F600}', invalid = '\255\254A', empty = '' } - function s_value(key) return values[key] end - function s_len(s) return #s end - function s_echo(s) return s end - function s_type(s) return type(s) end - """u8; - /// String and UTF-8 arguments and results in every shape, and a nullable string function argument. public const string StringSuite = """ using System; @@ -212,4 +171,45 @@ public static partial class Strings public static string Describe(string? text) => text is null ? "null" : "text:" + text.Length; } """; + + /// + /// q22(kind) returns one shape per kind: nil, false, true, 0, 42, 7 (odd), -2 + /// (negative), '', {}, no value at all, a string error and a table error whose __tostring + /// raises. + /// + public static ReadOnlySpan Q22StandIns => """ + local raising = setmetatable({}, { __tostring = function() error('tostring boom') end }) + local cases = { + ['nil'] = function() return nil end, + ['false'] = function() return false end, + ['true'] = function() return true end, + zero = function() return 0 end, + value = function() return 42 end, + odd = function() return 7 end, + negative = function() return -2 end, + empty = function() return '' end, + table = function() return {} end, + none = function() end, + raise = function() error('boom') end, + raise_table = function() error(raising) end, + } + function q22(kind) return cases[kind]() end + """u8; + + /// boundary(expression) evaluates a Lua expression, so each row is a value Lua itself produced. + public static ReadOnlySpan NumericStandIns => """ + function boundary(expression) return assert(load('return ' .. expression))() end + """u8; + + /// + /// s_value(key) returns a string with embedded NULs, multibyte UTF-8, invalid UTF-8 or the empty string; + /// s_len returns the byte length Lua received, s_echo the string itself, s_type its type. + /// + public static ReadOnlySpan StringStandIns => """ + local values = { nul = 'a\0b\0', multibyte = '\u{E9}\u{6F22}\u{1F600}', invalid = '\255\254A', empty = '' } + function s_value(key) return values[key] end + function s_len(s) return #s end + function s_echo(s) return s end + function s_type(s) return type(s) end + """u8; } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/GeneratorRun.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/GeneratorRun.cs index 959c4c4f..72cd2bc4 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/GeneratorRun.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/GeneratorRun.cs @@ -94,7 +94,7 @@ public void AssertCompilesClean() .. OutputCompilation .GetDiagnostics(TestContext.Current.CancellationToken) .Where(static diagnostic => diagnostic.Severity >= DiagnosticSeverity.Warning && - !IsMissingDocumentationInTestInput(diagnostic)) + !IsMissingDocumentationInTestInput(diagnostic)) ]; Assert.True(problems.Length == 0, @@ -106,7 +106,7 @@ .. OutputCompilation private static bool IsMissingDocumentationInTestInput(Diagnostic diagnostic) { return string.Equals(diagnostic.Id, "CS1591", StringComparison.Ordinal) - && diagnostic.Location.SourceTree is { FilePath: string path } - && !path.EndsWith(".g.cs", StringComparison.Ordinal); + && diagnostic.Location.SourceTree is { FilePath: string path } + && !path.EndsWith(".g.cs", StringComparison.Ordinal); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/LocalFrameworkReferences.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/LocalFrameworkReferences.cs index b179ad3a..8b157554 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/LocalFrameworkReferences.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/LocalFrameworkReferences.cs @@ -63,8 +63,8 @@ public static ImmutableArray FromTargetingPack() { string candidate = Path.Combine(pack, "ref", TargetFrameworkFolder); if (Directory.Exists(candidate) - && TryParsePackVersion(Path.GetFileName(pack), out Version? version) - && (bestVersion is null || version > bestVersion)) + && TryParsePackVersion(Path.GetFileName(pack), out Version? version) + && (bestVersion is null || version > bestVersion)) { best = candidate; bestVersion = version; diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/ModelGraph.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/ModelGraph.cs index 4517cfd2..27df8352 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/ModelGraph.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/ModelGraph.cs @@ -70,7 +70,7 @@ private static void Visit(object? value, string path, HashSet visited, i } foreach (FieldInfo field in - type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { Visit(field.GetValue(value), $"{path}.{field.Name}", visited, depth + 1); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/OptionalBindingSources.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/OptionalBindingSources.cs index 77977459..18f8d6b6 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/OptionalBindingSources.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/OptionalBindingSources.cs @@ -7,47 +7,6 @@ namespace CheatEngine.SDK.SourceGenerators.LuaBindings.Tests.Infrastructure; /// internal static class OptionalBindingSources { - /// The stand-in globals every optional suite runs against. - public static ReadOnlySpan StandIns => """ - calls = 0 - function arity(...) calls = calls + 1 return select('#', ...) end - function kinds(...) - local t = table.pack(...) - local out = {} - for i = 1, t.n do out[#out + 1] = type(t[i]) end - return table.concat(out, ',') - end - function readBytesLike(...) - local n = select('#', ...) - local address, count, asTable = ... - if n == 1 then return 'one byte' end - if n == 2 then return 'values' end - if asTable == nil then return 'nil flag' end - if asTable then return 'table' end - return 'values' - end - function shape(mode) - if mode == 0 then return end - if mode == 1 then return nil end - if mode == 2 then return 7 end - if mode == 3 then return 7, 8 end - if mode == 4 then return true, 'warn' end - if mode == 5 then return 1970354901756285, {} end - if mode == 6 then return 'text' end - if mode == 7 then return 7, 'x' end - if mode == 8 then return 7, nil end - error('boom') - end - function seq(n, bad) - if bad == 1 then return 1, nil, 3 end - if bad == 2 then return 1, 'x', 3 end - if n < 0 then error('negative') end - local t = {} - for i = 1, n do t[i] = i * 10 end - return table.unpack(t, 1, n) - end - """u8; - /// Every supported optional argument, optional result and variadic shape of a bound global. public const string GlobalSuite = """ using System; @@ -123,4 +82,45 @@ private static string State(LuaOptional value) value.IsOmitted ? "omitted" : value.IsNil ? "nil" : value.Value.ToString()!; } """; + + /// The stand-in globals every optional suite runs against. + public static ReadOnlySpan StandIns => """ + calls = 0 + function arity(...) calls = calls + 1 return select('#', ...) end + function kinds(...) + local t = table.pack(...) + local out = {} + for i = 1, t.n do out[#out + 1] = type(t[i]) end + return table.concat(out, ',') + end + function readBytesLike(...) + local n = select('#', ...) + local address, count, asTable = ... + if n == 1 then return 'one byte' end + if n == 2 then return 'values' end + if asTable == nil then return 'nil flag' end + if asTable then return 'table' end + return 'values' + end + function shape(mode) + if mode == 0 then return end + if mode == 1 then return nil end + if mode == 2 then return 7 end + if mode == 3 then return 7, 8 end + if mode == 4 then return true, 'warn' end + if mode == 5 then return 1970354901756285, {} end + if mode == 6 then return 'text' end + if mode == 7 then return 7, 'x' end + if mode == 8 then return 7, nil end + error('boom') + end + function seq(n, bad) + if bad == 1 then return 1, nil, 3 end + if bad == 2 then return 1, 'x', 3 end + if n < 0 then error('negative') end + local t = {} + for i = 1, n do t[i] = i * 10 end + return table.unpack(t, 1, n) + end + """u8; } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaFunctionTablesTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaFunctionTablesTests.cs index 21d707fa..2b56bfe2 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaFunctionTablesTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaFunctionTablesTests.cs @@ -58,14 +58,10 @@ public void Group_skips_invalid_members_and_types_left_without_a_valid_one() { LuaFunctionModel invalid = Function(Alpha, "bad") with { - Issues = LuaFunctionShapeIssues.NotStatic, - Thunk = null + Issues = LuaFunctionShapeIssues.NotStatic, Thunk = null }; LuaFunctionModel invalidType = - Function(Zeta, "ok") with - { - ContainingTypeIssues = ContainingTypeIssues.NotPartial - }; + Function(Zeta, "ok") with { ContainingTypeIssues = ContainingTypeIssues.NotPartial }; EquatableArray tables = LuaFunctionTables.Group([invalid, invalidType, Function(Alpha, "good")]); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaGlobalTablesTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaGlobalTablesTests.cs index a4ecba71..b990fdae 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaGlobalTablesTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaGlobalTablesTests.cs @@ -38,8 +38,7 @@ public void Group_skips_invalid_members_and_empty_inputs() { LuaGlobalModel invalid = Global("g", "G()") with { - Issues = LuaGlobalShapeIssues.NotPartialDefinition, - Call = null + Issues = LuaGlobalShapeIssues.NotPartialDefinition, Call = null }; Assert.True(LuaGlobalTables.Group([invalid]).IsEmpty); @@ -95,10 +94,11 @@ public void Optional_argument_model_is_value_equal_across_runs() new LuaArgumentModel("count", LuaValueKind.Int32, false) ]) }); - Assert.NotEqual(first, first with - { - Results = new EquatableArray([LuaResultModel.Value(LuaValueKind.Int64, "value")]) - }); + Assert.NotEqual(first, + first with + { + Results = new EquatableArray([LuaResultModel.Value(LuaValueKind.Int64, "value")]) + }); Assert.Equal( new LuaArgumentModel("count", LuaValueKind.Int32, false, false, null, null), new LuaArgumentModel("count", LuaValueKind.Int32, false)); @@ -107,7 +107,8 @@ public void Optional_argument_model_is_value_equal_across_runs() private static LuaGlobalCallModel OptionalCall() { - return new LuaGlobalCallModel("readBytes", LuaGlobalCallModel.CacheFieldFor("readBytes"), "public static partial", + return new LuaGlobalCallModel("readBytes", LuaGlobalCallModel.CacheFieldFor("readBytes"), + "public static partial", "ReadBytes", string.Empty, new EquatableArray([ new LuaArgumentModel("address", LuaValueKind.Address, false), diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/HintNamesTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/HintNamesTests.cs index 49049442..27ecdc26 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/HintNamesTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/HintNamesTests.cs @@ -91,6 +91,6 @@ public void AllocateUnique_rejects_a_case_sensitive_reservation_set() private static string WithOrdinal(string hintName, string suffix, int ordinal) { return hintName[..^suffix.Length] + "_" + ordinal.ToString(CultureInfo.InvariantCulture) + - suffix; + suffix; } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaApiNamesTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaApiNamesTests.cs index 38aac32d..732aa358 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaApiNamesTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaApiNamesTests.cs @@ -42,7 +42,7 @@ public void Every_CheatEngine_SDK_name_written_into_generated_code_denotes_a_rea { int dot = text.LastIndexOf('.'); Type owner = FindType(text[..dot]) - ?? throw new InvalidOperationException($"{name}: no such type in the SDK assemblies."); + ?? throw new InvalidOperationException($"{name}: no such type in the SDK assemblies."); Assert.NotEmpty(owner.GetMember( text[(dot + 1)..^2], MemberTypes.Method, @@ -51,7 +51,7 @@ public void Every_CheatEngine_SDK_name_written_into_generated_code_denotes_a_rea else { _ = FindType(text) - ?? throw new InvalidOperationException($"{name}: no such type in the SDK assemblies."); + ?? throw new InvalidOperationException($"{name}: no such type in the SDK assemblies."); } } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaGlobalCallEmitterTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaGlobalCallEmitterTests.cs index 9cbb8d14..6f8ed9d2 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaGlobalCallEmitterTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaGlobalCallEmitterTests.cs @@ -187,10 +187,7 @@ public void ResultCount_follows_the_form() LuaGlobalCallModel throwingVoid = new("g", "s", "static", "G", string.Empty, EquatableArray.Empty, LuaCallForm.Throwing, EquatableArray.Empty, null, false); - LuaGlobalCallModel throwingValue = throwingVoid with - { - ReturnKind = LuaValueKind.Double - }; + LuaGlobalCallModel throwingValue = throwingVoid with { ReturnKind = LuaValueKind.Double }; Assert.Equal(0, throwingVoid.ResultCount); Assert.Equal(1, throwingValue.ResultCount); @@ -289,8 +286,11 @@ public void Optional_and_variadic_shapes_are_reported_by_the_model_and_their_loc "(global::CheatEngine.SDK.Lua.Marshalling.LuaOptional n, out long first, out global::CheatEngine.SDK.Lua.Marshalling.LuaOptional second, scoped global::System.Span values, out int count)", writer.ToString()); - foreach (string local in (string[]) ["__L", "__operation", "__top", "__ok", "__status", "__result", - "__resolution", "__exception", "__argc", "__rest"]) + foreach (string local in (string[]) + [ + "__L", "__operation", "__top", "__ok", "__status", "__result", + "__resolution", "__exception", "__argc", "__rest" + ]) { Assert.True(LuaGlobalCallEmitter.IsReservedLocal(local), local); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaThunkEmitterTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaThunkEmitterTests.cs index d4a38e64..dd241522 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaThunkEmitterTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaThunkEmitterTests.cs @@ -190,8 +190,8 @@ private static int CountOccurrences(string text, string value) { int count = 0; for (int index = text.IndexOf(value, StringComparison.Ordinal); - index >= 0; - index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) + index >= 0; + index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) { count++; } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogDiagnosticsTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogDiagnosticsTests.cs index 2ad33941..13f7de22 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogDiagnosticsTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogDiagnosticsTests.cs @@ -34,7 +34,8 @@ public void Duplicate_opcode_reports_both_external_file_entries_and_emits_nothin string text = CatalogSources.ReverseOpcodeOrder .Replace("\"opcode\": 10", "\"opcode\": 0", StringComparison.Ordinal) .Replace("0x0000000000000401", "0x0000000000000001", StringComparison.Ordinal); - GeneratorRun run = RoslynFixture.Run("libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json", text); + GeneratorRun run = + RoslynFixture.Run("libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json", text); Assert.Empty(run.GeneratedSources); Assert.Equal(2, run.GeneratorDiagnostics.Length); @@ -75,16 +76,16 @@ public void A_valid_and_malformed_catalogue_both_receive_the_ambiguity_diagnosti Assert.Equal(3, run.GeneratorDiagnostics.Length); Assert.Contains(run.GeneratorDiagnostics, static diagnostic => string.Equals(diagnostic.Id, "CESDK4001", StringComparison.Ordinal) - && string.Equals(diagnostic.Location.GetLineSpan().Path, InvalidPath, - StringComparison.Ordinal)); + && string.Equals(diagnostic.Location.GetLineSpan().Path, InvalidPath, + StringComparison.Ordinal)); Assert.Contains(run.GeneratorDiagnostics, static diagnostic => string.Equals(diagnostic.Id, "CESDK4002", StringComparison.Ordinal) - && string.Equals(diagnostic.Location.GetLineSpan().Path, ValidPath, - StringComparison.Ordinal)); + && string.Equals(diagnostic.Location.GetLineSpan().Path, ValidPath, + StringComparison.Ordinal)); Assert.Contains(run.GeneratorDiagnostics, static diagnostic => string.Equals(diagnostic.Id, "CESDK4002", StringComparison.Ordinal) - && string.Equals(diagnostic.Location.GetLineSpan().Path, InvalidPath, - StringComparison.Ordinal)); + && string.Equals(diagnostic.Location.GetLineSpan().Path, InvalidPath, + StringComparison.Ordinal)); } [Fact] diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogEmissionTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogEmissionTests.cs index 0ced0481..25ee0184 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogEmissionTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogEmissionTests.cs @@ -12,7 +12,8 @@ public sealed class CatalogEmissionTests public void Catalog_operations_emit_a_numeric_sorted_enum_and_required_bitmap() { GeneratorRun run = - RoslynFixture.Run("libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json", CatalogSources.ReverseOpcodeOrder); + RoslynFixture.Run("libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json", + CatalogSources.ReverseOpcodeOrder); run.AssertCompilesClean(); string generated = run.SingleGeneratedText; @@ -20,7 +21,7 @@ public void Catalog_operations_emit_a_numeric_sorted_enum_and_required_bitmap() Assert.Contains("PushBytes = 0", generated, StringComparison.Ordinal); Assert.Contains("PushHostObject = 10", generated, StringComparison.Ordinal); Assert.True(generated.IndexOf("PushBytes = 0", StringComparison.Ordinal) - < generated.IndexOf("PushHostObject = 10", StringComparison.Ordinal)); + < generated.IndexOf("PushHostObject = 10", StringComparison.Ordinal)); Assert.Contains("internal const int Count = 2;", generated, StringComparison.Ordinal); Assert.Contains("internal const ulong RequiredBitmap = 0x0000000000000401UL;", generated, StringComparison.Ordinal); @@ -30,7 +31,8 @@ public void Catalog_operations_emit_a_numeric_sorted_enum_and_required_bitmap() [Fact] public void Production_catalog_emits_all_C11_operations_and_the_exact_required_bitmap() { - GeneratorRun run = RoslynFixture.Run("libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json", ProductionCatalog.Read()); + GeneratorRun run = RoslynFixture.Run("libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json", + ProductionCatalog.Read()); run.AssertCompilesClean(); string generated = run.SingleGeneratedText; @@ -62,7 +64,8 @@ public void Production_catalog_emits_all_C11_operations_and_the_exact_required_b [Fact] public void Catalog_an_identical_rerun_is_deterministic() { - InMemoryAdditionalText additionalText = new("libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json", + InMemoryAdditionalText additionalText = new( + "libs/CheatEngine.SDK.Lua.Interop/Protected/protected-operations.json", CatalogSources.ReverseOpcodeOrder); CSharpCompilation compilation = RoslynFixture.CreateCompilation(); GeneratorRun first = GeneratorRun.Execute(RoslynFixture.CreateDriver(additionalText), compilation); @@ -122,7 +125,8 @@ public void Replacing_a_valid_catalogue_with_an_invalid_one_removes_generated_so [Fact] public void An_unrelated_additional_file_is_silent() { - GeneratorRun run = RoslynFixture.Run("libs/CheatEngine.SDK.Lua.Interop/Protected/notes.json", CatalogSources.ReverseOpcodeOrder); + GeneratorRun run = RoslynFixture.Run("libs/CheatEngine.SDK.Lua.Interop/Protected/notes.json", + CatalogSources.ReverseOpcodeOrder); Assert.Empty(run.GeneratedSources); Assert.Empty(run.GeneratorDiagnostics); diff --git a/tests/CheatEngine.SDK.Tests.Shared/NativeLua/NativeLuaProbe.cs b/tests/CheatEngine.SDK.Tests.Shared/NativeLua/NativeLuaProbe.cs index 5f3393ed..eb90ba44 100644 --- a/tests/CheatEngine.SDK.Tests.Shared/NativeLua/NativeLuaProbe.cs +++ b/tests/CheatEngine.SDK.Tests.Shared/NativeLua/NativeLuaProbe.cs @@ -65,7 +65,7 @@ private static bool TryGetFullPath(string candidate, out string fullPath) return true; } catch (Exception exception) when (exception is ArgumentException or NotSupportedException - or PathTooLongException or SecurityException) + or PathTooLongException or SecurityException) { fullPath = string.Empty; return false; diff --git a/tests/CheatEngine.SDK.Tests.Shared/NativeLua/PartialLuaModule.cs b/tests/CheatEngine.SDK.Tests.Shared/NativeLua/PartialLuaModule.cs index 1541a551..f1b74d74 100644 --- a/tests/CheatEngine.SDK.Tests.Shared/NativeLua/PartialLuaModule.cs +++ b/tests/CheatEngine.SDK.Tests.Shared/NativeLua/PartialLuaModule.cs @@ -46,20 +46,6 @@ public nint Handle private set; } - /// Copies , removes from the copy and loads it. - /// The image is not PE32+ or does not export . - public static PartialLuaModule Load(string fixturePath) - { - byte[] image = File.ReadAllBytes(fixturePath); - RenameExport(image, RemovedExport, ReplacementName); - string directory = Path.Combine(Path.GetTempPath(), "CheatEngine.SDK.Tests", - "partial-lua-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(directory); - string path = Path.Combine(directory, "lua53-partial.dll"); - File.WriteAllBytes(path, image); - return new PartialLuaModule(directory, NativeLibrary.Load(path)); - } - /// Frees the copy and deletes its folder. public void Dispose() { @@ -83,6 +69,20 @@ public void Dispose() } } + /// Copies , removes from the copy and loads it. + /// The image is not PE32+ or does not export . + public static PartialLuaModule Load(string fixturePath) + { + byte[] image = File.ReadAllBytes(fixturePath); + RenameExport(image, RemovedExport, ReplacementName); + string directory = Path.Combine(Path.GetTempPath(), "CheatEngine.SDK.Tests", + "partial-lua-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + string path = Path.Combine(directory, "lua53-partial.dll"); + File.WriteAllBytes(path, image); + return new PartialLuaModule(directory, NativeLibrary.Load(path)); + } + /// /// Overwrites the export name of a PE32+ in place with /// , found through the export directory rather than by searching the bytes. @@ -94,20 +94,23 @@ internal static void RenameExport(byte[] image, string existing, string replacem { if (replacement.Length != existing.Length) { - throw new ArgumentException("The replacement must have the length of the original name.", nameof(replacement)); + throw new ArgumentException("The replacement must have the length of the original name.", + nameof(replacement)); } int signature = BinaryPrimitives.ReadInt32LittleEndian(image.AsSpan(PeHeaderPointerOffset)); int optionalHeader = signature + OptionalHeaderOffsetFromSignature; if (BinaryPrimitives.ReadUInt32LittleEndian(image.AsSpan(signature)) != 0x4550 || - BinaryPrimitives.ReadUInt16LittleEndian(image.AsSpan(optionalHeader)) != Pe32PlusMagic) + BinaryPrimitives.ReadUInt16LittleEndian(image.AsSpan(optionalHeader)) != Pe32PlusMagic) { throw new InvalidOperationException("The Lua fixture is not a PE32+ image."); } int sectionCount = BinaryPrimitives.ReadUInt16LittleEndian(image.AsSpan(signature + 6)); int sections = optionalHeader + BinaryPrimitives.ReadUInt16LittleEndian(image.AsSpan(signature + 20)); - uint exportRva = BinaryPrimitives.ReadUInt32LittleEndian(image.AsSpan(optionalHeader + ExportDirectoryOffsetInOptionalHeader)); + uint exportRva = + BinaryPrimitives.ReadUInt32LittleEndian( + image.AsSpan(optionalHeader + ExportDirectoryOffsetInOptionalHeader)); int exportDirectory = ToFileOffset(image, sections, sectionCount, exportRva); int nameCount = BinaryPrimitives.ReadInt32LittleEndian(image.AsSpan(exportDirectory + 24)); int nameTable = ToFileOffset(image, sections, sectionCount, @@ -129,7 +132,8 @@ internal static void RenameExport(byte[] image, string existing, string replacem } bool staysSorted = (target == 0 || string.CompareOrdinal(names[target - 1].Name, replacement) < 0) && - (target == names.Count - 1 || string.CompareOrdinal(replacement, names[target + 1].Name) < 0); + (target == names.Count - 1 || + string.CompareOrdinal(replacement, names[target + 1].Name) < 0); if (!staysSorted) { throw new InvalidOperationException($"'{replacement}' would leave the export name table unsorted."); diff --git a/tests/CheatEngine.SDK.Tests/Architecture/ProjectDependencyDirectionTests.cs b/tests/CheatEngine.SDK.Tests/Architecture/ProjectDependencyDirectionTests.cs index 39c8ddd6..733381ad 100644 --- a/tests/CheatEngine.SDK.Tests/Architecture/ProjectDependencyDirectionTests.cs +++ b/tests/CheatEngine.SDK.Tests/Architecture/ProjectDependencyDirectionTests.cs @@ -80,7 +80,7 @@ public void Shipping_libraries_keep_the_declared_lower_layer_runtime_graph() discoveredLibraryProjects.Add(projectRelativePath); if (!ExpectedLibraryRuntimeDependencies.TryGetValue(projectRelativePath, - out string[]? expectedDependencies)) + out string[]? expectedDependencies)) { violations.Add($"{projectRelativePath}: is not declared in the shipping library graph."); continue; @@ -266,7 +266,7 @@ private static void AddForbiddenDependencyViolations(List violations, st } if (value.Contains("CheatEngine.Client", StringComparison.OrdinalIgnoreCase) || - value.Contains("CheatEngine.Mcp", StringComparison.OrdinalIgnoreCase)) + value.Contains("CheatEngine.Mcp", StringComparison.OrdinalIgnoreCase)) { violations.Add( $"{GetRepositoryRelativePath(metadataPath)}: {node.LocalName} {attributeName}='{value}' references a higher layer."); @@ -329,7 +329,7 @@ private static IEnumerable EnumerateBuildMetadataFiles() private static IEnumerable EnumerateRepositoryFiles(string searchPattern) { foreach (string path in - Directory.EnumerateFiles(RepositoryLayout.Root, searchPattern, SearchOption.AllDirectories)) + Directory.EnumerateFiles(RepositoryLayout.Root, searchPattern, SearchOption.AllDirectories)) { string relativePath = GetRepositoryRelativePath(path); if (!IsGeneratedPath(relativePath)) @@ -353,20 +353,20 @@ private static string GetRepositoryRelativePath(string fullPath) private static bool IsGeneratedPath(string relativePath) { return relativePath.StartsWith("artifacts/", StringComparison.Ordinal) || - relativePath.Contains("/bin/", StringComparison.Ordinal) || - relativePath.Contains("/obj/", StringComparison.Ordinal); + relativePath.Contains("/bin/", StringComparison.Ordinal) || + relativePath.Contains("/obj/", StringComparison.Ordinal); } private static bool IsRoslynComponent(string projectRelativePath) { return projectRelativePath.StartsWith("analyzers/", StringComparison.Ordinal) || - projectRelativePath.StartsWith("source-generators/", StringComparison.Ordinal); + projectRelativePath.StartsWith("source-generators/", StringComparison.Ordinal); } private static bool IsShippingProject(string projectRelativePath) { return projectRelativePath.StartsWith("libs/", StringComparison.Ordinal) || - string.Equals(projectRelativePath, UmbrellaProject, StringComparison.Ordinal); + string.Equals(projectRelativePath, UmbrellaProject, StringComparison.Ordinal); } private static XmlDocument LoadProjectDocument(string projectPath) diff --git a/tests/CheatEngine.SDK.Tests/Build/NativeAotProfileTargetTests.cs b/tests/CheatEngine.SDK.Tests/Build/NativeAotProfileTargetTests.cs index 4cecb7ff..f9cd2616 100644 --- a/tests/CheatEngine.SDK.Tests/Build/NativeAotProfileTargetTests.cs +++ b/tests/CheatEngine.SDK.Tests/Build/NativeAotProfileTargetTests.cs @@ -5,7 +5,8 @@ namespace CheatEngine.SDK.Tests.Build; /// -/// The packaged build target CheatEngineSdkWarnNativeAotPluginProfile (src/CheatEngine.SDK/build/CheatEngine.SDK.targets) +/// The packaged build target CheatEngineSdkWarnNativeAotPluginProfile ( +/// src/CheatEngine.SDK/build/CheatEngine.SDK.targets) /// warns with CESDK9102 when a direct consumer library sets PublishAot=true: a NativeAOT plugin /// DLL cannot be unloaded by Cheat Engine's FreeLibrary (audit F02, EXT-01), so the only supported plugin /// profile is the managed hostfxr route. An executable publishing with NativeAOT is not warned. @@ -30,7 +31,7 @@ public sealed class NativeAotProfileTargetTests [Trait("Qualification", "Q41")] public async Task PublishAot_library_consumer_gets_CESDK9102(string nativeLib) { - ProcessResult result = await RunTargetAsync("Library", publishAot: "true", nativeLib, noWarn: false); + ProcessResult result = await RunTargetAsync("Library", "true", nativeLib, false); Assert.True(result.ExitCode == 0, result.CombinedOutput); Assert.Contains("warning CESDK9102", result.StandardOutput, StringComparison.Ordinal); @@ -41,7 +42,8 @@ public async Task PublishAot_library_consumer_gets_CESDK9102(string nativeLib) [Fact] public void CESDK9102_warning_links_its_rule_page_and_runs_before_the_build() { - XDocument targets = XDocument.Load(RepositoryLayout.PathOf("src/CheatEngine.SDK/build/CheatEngine.SDK.targets")); + XDocument targets = + XDocument.Load(RepositoryLayout.PathOf("src/CheatEngine.SDK/build/CheatEngine.SDK.targets")); XElement target = Assert.Single(targets.Root!.Elements("Target"), static element => string.Equals((string?) element.Attribute("Name"), TargetName, StringComparison.Ordinal)); @@ -59,7 +61,7 @@ public void CESDK9102_warning_links_its_rule_page_and_runs_before_the_build() [Trait("Qualification", "Q41")] public async Task PublishAot_executable_consumer_gets_no_CESDK9102(string outputType) { - ProcessResult result = await RunTargetAsync(outputType, publishAot: "true", nativeLib: "", noWarn: false); + ProcessResult result = await RunTargetAsync(outputType, "true", "", false); Assert.True(result.ExitCode == 0, result.CombinedOutput); Assert.DoesNotContain("CESDK9102", result.CombinedOutput, StringComparison.Ordinal); @@ -71,7 +73,7 @@ public async Task PublishAot_executable_consumer_gets_no_CESDK9102(string output [Trait("Qualification", "Q41")] public async Task Consumer_without_PublishAot_gets_no_CESDK9102(string publishAot) { - ProcessResult result = await RunTargetAsync("Library", publishAot, nativeLib: "Shared", noWarn: false); + ProcessResult result = await RunTargetAsync("Library", publishAot, "Shared", false); Assert.True(result.ExitCode == 0, result.CombinedOutput); Assert.DoesNotContain("CESDK9102", result.CombinedOutput, StringComparison.Ordinal); @@ -81,7 +83,7 @@ public async Task Consumer_without_PublishAot_gets_no_CESDK9102(string publishAo [Trait("Qualification", "Q41")] public async Task NoWarn_demotes_CESDK9102_to_a_message() { - ProcessResult result = await RunTargetAsync("Library", publishAot: "true", nativeLib: "Shared", noWarn: true); + ProcessResult result = await RunTargetAsync("Library", "true", "Shared", true); // Detailed verbosity: MSBuild logs a warning demoted by NoWarn as a low-importance message. Assert.True(result.ExitCode == 0, result.CombinedOutput); @@ -101,18 +103,18 @@ private static async Task RunTargetAsync(string outputType, strin string project = Path.Combine(directory, "NativeAotProfileConsumer.csproj"); File.Copy(RepositoryLayout.PathOf("global.json"), Path.Combine(directory, "global.json")); await File.WriteAllTextAsync(project, $""" - - - - net10.0 - {outputType} - {publishAot} - {nativeLib} - $(NoWarn);CESDK9102 - - - - """, TestContext.Current.CancellationToken); + + + + net10.0 + {outputType} + {publishAot} + {nativeLib} + $(NoWarn);CESDK9102 + + + + """, TestContext.Current.CancellationToken); string arguments = string.Create(CultureInfo.InvariantCulture, $"msbuild \"{project}\" -t:{TargetName} -nologo -v:{(noWarn ? "d" : "n")} -p:ImportDirectoryBuildProps=false -p:ImportDirectoryBuildTargets=false -p:ImportDirectoryPackagesProps=false"); diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/CommittedFile.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/CommittedFile.cs index ab9744bb..66f50e93 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/CommittedFile.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/CommittedFile.cs @@ -15,7 +15,10 @@ internal static class CommittedFile /// The exact bytes of HEAD:<repoRelativePath>. /// A repository-relative path with forward slashes. - /// git is missing, the tree is not a git checkout, or the path is not committed. + /// + /// git is missing, the tree is not a git checkout, or the path is not + /// committed. + /// public static async Task ReadBytesAsync(string repoRelativePath) { ArgumentException.ThrowIfNullOrWhiteSpace(repoRelativePath); @@ -33,10 +36,7 @@ public static async Task ReadBytesAsync(string repoRelativePath) startInfo.ArgumentList.Add("blob"); startInfo.ArgumentList.Add($"HEAD:{repoRelativePath}"); - using Process process = new() - { - StartInfo = startInfo - }; + using Process process = new() { StartInfo = startInfo }; try { process.Start(); @@ -61,7 +61,8 @@ public static async Task ReadBytesAsync(string repoRelativePath) catch (OperationCanceledException exception) when (cancellation.IsCancellationRequested) { process.Kill(true); - throw new TimeoutException($"'git cat-file blob HEAD:{repoRelativePath}' did not exit within {Timeout}.", exception); + throw new TimeoutException($"'git cat-file blob HEAD:{repoRelativePath}' did not exit within {Timeout}.", + exception); } if (process.ExitCode != 0) diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/EntryPointProbe.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/EntryPointProbe.cs index 2997b0f7..ac57aa94 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/EntryPointProbe.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/EntryPointProbe.cs @@ -27,7 +27,7 @@ public static (bool TypeExists, bool MethodExists) Probe(string assemblyPath) { TypeDefinition type = reader.GetTypeDefinition(typeHandle); if (!string.Equals(reader.GetString(type.Namespace), TypeNamespace, StringComparison.Ordinal) - || !string.Equals(reader.GetString(type.Name), TypeName, StringComparison.Ordinal)) + || !string.Equals(reader.GetString(type.Name), TypeName, StringComparison.Ordinal)) { continue; } @@ -36,7 +36,7 @@ public static (bool TypeExists, bool MethodExists) Probe(string assemblyPath) { MethodDefinition method = reader.GetMethodDefinition(methodHandle); if (string.Equals(reader.GetString(method.Name), MethodName, StringComparison.Ordinal) && - method.GetParameters().Count == 2) + method.GetParameters().Count == 2) { return (TypeExists: true, MethodExists: true); } diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/PackagedUmbrellaFixture.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/PackagedUmbrellaFixture.cs index d23b845e..40d63157 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/PackagedUmbrellaFixture.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/PackagedUmbrellaFixture.cs @@ -21,21 +21,23 @@ namespace CheatEngine.SDK.Tests.Infrastructure; /// its feed and never packs: in the CI Release leg it is the .nupkg that is uploaded as /// nuget-package, attested and published, so these tests are evidence about the shipped file. Otherwise, /// outside CI, it packs src/CheatEngine.SDK/CheatEngine.SDK.csproj itself: the facts then describe the -/// working tree, not a shipped file. Under CI=true a missing variable is an error, never a silent self-pack. +/// working tree, not a shipped file. Under CI=true a missing variable is an error, never a silent +/// self-pack. /// /// -/// Every consumer restore is pointed (dotnet restore --packages) at , a -/// directory scoped to this fixture's own _tempRoot, never the machine-wide global-packages folder -/// (typically %USERPROFILE%\.nuget\packages). This matters because every pack in one session gets the SAME -/// MinVer-derived version (git commit height only changes on a new commit), and NuGet treats a package id+version -/// already extracted in the global-packages folder as immutable: a later restore against a freshly re-packed -/// .nupkg with different content but the same version would silently reuse whatever was extracted there by -/// an earlier run - this fixture's own previous run, a developer's manual restore, or another parallel build on -/// the same machine - with no error or warning. That would defeat this project's whole point (verifying the -/// freshly packed umbrella, not some earlier one) for every consumer-based assertion -/// (EntryPointTests, BuildPropertyDefaultsTests); only the nuspec/file-list tests, which read the -/// .nupkg directly via , would be unaffected. Starting every fixture run from an -/// empty, run-scoped packages directory removes the sharing that makes that possible. +/// Every consumer restore is pointed (dotnet restore --packages) at , a +/// directory scoped to this fixture's own _tempRoot, never the machine-wide global-packages folder +/// (typically %USERPROFILE%\.nuget\packages). This matters because every pack in one session gets the SAME +/// MinVer-derived version (git commit height only changes on a new commit), and NuGet treats a package id+version +/// already extracted in the global-packages folder as immutable: a later restore against a freshly re-packed +/// .nupkg with different content but the same version would silently reuse whatever was extracted there by +/// an earlier run - this fixture's own previous run, a developer's manual restore, or another parallel build on +/// the same machine - with no error or warning. That would defeat this project's whole point (verifying the +/// freshly packed umbrella, not some earlier one) for every consumer-based assertion +/// (EntryPointTests, BuildPropertyDefaultsTests); only the nuspec/file-list tests, which read the +/// .nupkg directly via , would be unaffected. Starting every fixture run from +/// an +/// empty, run-scoped packages directory removes the sharing that makes that possible. /// /// public sealed class PackagedUmbrellaFixture : IAsyncLifetime @@ -547,10 +549,10 @@ await Task.Delay(TimeSpan.FromSeconds(20 * attempt), TestContext.Current.Cancell private static bool LooksLikeFileLockContention(string output) { return output.Contains("being used by another process", StringComparison.OrdinalIgnoreCase) - || output.Contains("cannot access the file", StringComparison.OrdinalIgnoreCase) - || output.Contains("MSB3021", StringComparison.Ordinal) - || output.Contains("MSB3027", StringComparison.Ordinal) - || output.Contains("MSB3061", StringComparison.Ordinal); + || output.Contains("cannot access the file", StringComparison.OrdinalIgnoreCase) + || output.Contains("MSB3021", StringComparison.Ordinal) + || output.Contains("MSB3027", StringComparison.Ordinal) + || output.Contains("MSB3061", StringComparison.Ordinal); } private async Task InitializeDefaultConsumerAsync(string tempRoot, string feedDirectory, string packagesDirectory) @@ -628,8 +630,7 @@ private async Task InitializeLuaFunctionConsumersAsync(string tempRoot, string f feedDirectory, new ThrowawayConsumer.CreateOptions { - ExtraProperties = " true\n", - IncludeLuaFunction = true + ExtraProperties = " true\n", IncludeLuaFunction = true }); ProcessResult optInRestore = await optInConsumer.RestoreAsync(RestoreTimeout, packagesDirectory).ConfigureAwait(false); diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/ProcessRunner.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/ProcessRunner.cs index 7e82eff5..81c02f55 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/ProcessRunner.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/ProcessRunner.cs @@ -24,10 +24,7 @@ public static async Task RunAsync(string fileName, string argumen CreateNoWindow = true }; - using Process process = new() - { - StartInfo = startInfo - }; + using Process process = new() { StartInfo = startInfo }; StringBuilder standardOutput = new(); StringBuilder standardError = new(); process.OutputDataReceived += (_, e) => diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/RepositoryLayout.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/RepositoryLayout.cs index 2ad3cdfc..fbb0c418 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/RepositoryLayout.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/RepositoryLayout.cs @@ -20,8 +20,8 @@ public static string PathOf(string relativePath) private static string FindRoot() { for (DirectoryInfo? directory = new(AppContext.BaseDirectory); - directory is not null; - directory = directory.Parent) + directory is not null; + directory = directory.Parent) { if (File.Exists(Path.Combine(directory.FullName, SolutionFileName))) { diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/UmbrellaPackageSource.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/UmbrellaPackageSource.cs index 7d9d82ae..0c2d6341 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/UmbrellaPackageSource.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/UmbrellaPackageSource.cs @@ -75,9 +75,9 @@ public static bool IsUmbrellaPackageFileName(string fileName) ArgumentNullException.ThrowIfNull(fileName); string prefix = UmbrellaPackage.Id + "."; return fileName.StartsWith(prefix, StringComparison.Ordinal) - && fileName.EndsWith(NupkgExtension, StringComparison.Ordinal) - && fileName.Length > prefix.Length + NupkgExtension.Length - && SemanticVersion().IsMatch(fileName[prefix.Length..^NupkgExtension.Length]); + && fileName.EndsWith(NupkgExtension, StringComparison.Ordinal) + && fileName.Length > prefix.Length + NupkgExtension.Length + && SemanticVersion().IsMatch(fileName[prefix.Length..^NupkgExtension.Length]); } private static InvalidOperationException Rejected(string value, string reason) diff --git a/tests/CheatEngine.SDK.Tests/Packaging/BridgeAuditManifestTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/BridgeAuditManifestTests.cs index 560a965b..c743736d 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/BridgeAuditManifestTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/BridgeAuditManifestTests.cs @@ -9,7 +9,8 @@ namespace CheatEngine.SDK.Tests.Packaging; /// -/// native/cheatengine-sdk-lua-bridge/bridge-audit-manifest.json records the audited bridge: the SHA-256 of its two +/// native/cheatengine-sdk-lua-bridge/bridge-audit-manifest.json records the audited bridge: the SHA-256 of its +/// two /// LF-pinned build inputs, the fingerprint embedded in the DLL, the DLL SHA-256, its PE facts and the pinned xmake /// version. The DLL facts are read from the committed blob (git cat-file), never from the working tree: /// CI overwrites the working-tree DLL with the one it builds, and a byte difference between the two is drift that CI @@ -26,9 +27,7 @@ public sealed partial class BridgeAuditManifestTests private static readonly JsonSerializerOptions s_manifestFormat = new() { - WriteIndented = true, - IndentSize = 2, - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + WriteIndented = true, IndentSize = 2, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; [Fact] @@ -39,9 +38,11 @@ public async Task Bridge_audit_manifest_records_the_current_source_hashes_and_fi string buildSha256 = Sha256(File.ReadAllBytes(BridgeInput(BuildFile))); string message = await StaleMessageAsync().ConfigureAwait(true); - Assert.True(string.Equals(sourceSha256, (string?) manifest["source"]?["hashes"]?[SourceFile], StringComparison.Ordinal), + Assert.True( + string.Equals(sourceSha256, (string?) manifest["source"]?["hashes"]?[SourceFile], StringComparison.Ordinal), message); - Assert.True(string.Equals(buildSha256, (string?) manifest["source"]?["hashes"]?[BuildFile], StringComparison.Ordinal), + Assert.True( + string.Equals(buildSha256, (string?) manifest["source"]?["hashes"]?[BuildFile], StringComparison.Ordinal), message); Assert.True(string.Equals($"{sourceSha256}:{buildSha256}", (string?) manifest["source"]?["fingerprint"], StringComparison.Ordinal), message); @@ -56,8 +57,10 @@ public async Task Bridge_audit_manifest_matches_the_committed_bridge_blob() JsonNode? asset = manifest["nativeAsset"]; Assert.True(string.Equals(committed.Sha256, (string?) asset?["sha256"], StringComparison.Ordinal), message); - Assert.True(string.Equals(committed.Format, (string?) asset?["pe"]?["format"], StringComparison.Ordinal), message); - Assert.True(string.Equals(committed.Machine, (string?) asset?["pe"]?["machine"], StringComparison.Ordinal), message); + Assert.True(string.Equals(committed.Format, (string?) asset?["pe"]?["format"], StringComparison.Ordinal), + message); + Assert.True(string.Equals(committed.Machine, (string?) asset?["pe"]?["machine"], StringComparison.Ordinal), + message); Assert.True(committed.IsDll && (bool?) asset?["pe"]?["isDll"] == true, message); Assert.True(SetEquals(committed.Exports, Strings(asset?["exports"])), message); Assert.True(SetEquals(committed.Imports, Strings(asset?["imports"])), message); @@ -99,7 +102,8 @@ public void Bridge_audit_manifest_asset_path_exists_with_exact_case() } } - Assert.True(match is not null, $"'{segment}' of asset '{asset}' does not exist with that exact case in '{current}'."); + Assert.True(match is not null, + $"'{segment}' of asset '{asset}' does not exist with that exact case in '{current}'."); current = match!; } @@ -146,7 +150,7 @@ private static async Task ExpectedManifestJsonAsync() private static async Task StaleMessageAsync() { return $"{ManifestPath} does not describe the committed bridge. Replace it with:{Environment.NewLine}" + - await ExpectedManifestJsonAsync().ConfigureAwait(false); + await ExpectedManifestJsonAsync().ConfigureAwait(false); } private static async Task ReadCommittedBridgeAsync() @@ -211,7 +215,7 @@ private static async Task ReadCommittedBridgeAsync() private static JsonNode ReadManifest() { return JsonNode.Parse(File.ReadAllText(RepositoryLayout.PathOf(ManifestPath))) - ?? throw new InvalidDataException($"{ManifestPath} is empty."); + ?? throw new InvalidDataException($"{ManifestPath} is empty."); } private static string BridgeInput(string fileName) @@ -222,7 +226,7 @@ private static string BridgeInput(string fileName) private static JsonObject Object(JsonNode parent, string name) { return parent[name] as JsonObject - ?? throw new InvalidDataException($"{ManifestPath} has no '{name}' object."); + ?? throw new InvalidDataException($"{ManifestPath} has no '{name}' object."); } private static JsonArray JsonStrings(IReadOnlyList values) @@ -253,7 +257,7 @@ private static List Strings(JsonNode? node) private static bool SetEquals(IReadOnlyList expected, List actual) { return expected.Count == actual.Count - && new HashSet(expected, StringComparer.Ordinal).SetEquals(actual); + && new HashSet(expected, StringComparer.Ordinal).SetEquals(actual); } private static string Sha256(byte[] content) diff --git a/tests/CheatEngine.SDK.Tests/Packaging/CleanConsumerIsolationTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/CleanConsumerIsolationTests.cs index 53e8f75e..8d186494 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/CleanConsumerIsolationTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/CleanConsumerIsolationTests.cs @@ -51,7 +51,8 @@ public void Consumer_manifests_contain_no_repository_or_developer_path() { string path = Path.Combine(folder, manifest); Assert.True(File.Exists(path), $"'{path}' was not produced."); - foreach (string leak in ConsumerManifestRules.WorkspaceLeaks(File.ReadAllText(path), RepositoryLayout.Root)) + foreach (string leak in ConsumerManifestRules.WorkspaceLeaks(File.ReadAllText(path), + RepositoryLayout.Root)) { offenders.Add($"{path}: {leak}"); } @@ -74,7 +75,7 @@ public void Every_deployed_sdk_assembly_is_byte_identical_to_its_packed_lib_entr foreach (string entry in fixture.PackageEntries) { if (!entry.StartsWith(LibraryPrefix, StringComparison.Ordinal) - || !entry.EndsWith(".dll", StringComparison.Ordinal)) + || !entry.EndsWith(".dll", StringComparison.Ordinal)) { continue; } diff --git a/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRuleTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRuleTests.cs index 2b440d4e..aff6c4f3 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRuleTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRuleTests.cs @@ -3,13 +3,17 @@ namespace CheatEngine.SDK.Tests.Packaging; /// -/// Proves, on synthetic manifests and without the packaging fixture, that each rule +/// Proves, on synthetic manifests and without the packaging fixture, that each +/// rule /// accepts a clean package consumer and rejects the workspace leak it exists for. Runs in both CI legs. /// public sealed class ConsumerManifestRuleTests { private const string Version = "2.0.0-alpha.0.18"; - private const string Sha512 = "n7nHqZ8vzo7Vf20jF0fkh/jUtR3yo1TwRGpXE7ERxZeJ4C5S/Nsft4lqOg7zGwfsD5Nh9tTVgdw4PrybJRF0gA=="; + + private const string Sha512 = + "n7nHqZ8vzo7Vf20jF0fkh/jUtR3yo1TwRGpXE7ERxZeJ4C5S/Nsft4lqOg7zGwfsD5Nh9tTVgdw4PrybJRF0gA=="; + private const string Root = @"D:\a\CheatEngine.SDK\CheatEngine.SDK"; [Fact] diff --git a/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRules.cs b/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRules.cs index 0fdc6775..021ebd00 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRules.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRules.cs @@ -3,10 +3,12 @@ namespace CheatEngine.SDK.Tests.Packaging; /// -/// What a clean package consumer's manifests must and must not say (audit ch.21: a consumer that works thanks to a file +/// What a clean package consumer's manifests must and must not say (audit ch.21: a consumer that works thanks to a +/// file /// found in the development folder is not a qualified consumer). Pure functions of the manifest text, each returning /// one message per problem, so applies them to the real consumer and -/// proves on synthetic manifests that each rule fails on the leak it exists for. +/// proves on synthetic manifests that each rule fails on the leak it exists +/// for. /// internal static class ConsumerManifestRules { @@ -23,7 +25,7 @@ public static List SdkLibraryProblems(string depsJson, string packageVer string key = $"{UmbrellaPackage.Id}/{packageVersion}"; using JsonDocument document = JsonDocument.Parse(depsJson); if (!document.RootElement.TryGetProperty("libraries", out JsonElement libraries) - || !libraries.TryGetProperty(key, out JsonElement library)) + || !libraries.TryGetProperty(key, out JsonElement library)) { problems.Add($"library '{key}' is absent"); return problems; @@ -46,7 +48,8 @@ public static List SdkLibraryProblems(string depsJson, string packageVer if (!string.Equals(sha512, expectedSha512, StringComparison.Ordinal)) { - problems.Add($"library '{key}' has sha512 '{sha512}', expected '{expectedSha512}' (the package under test)"); + problems.Add( + $"library '{key}' has sha512 '{sha512}', expected '{expectedSha512}' (the package under test)"); } return problems; @@ -65,7 +68,7 @@ public static List ProjectTypedSdkLibraries(string depsJson) foreach (JsonProperty library in libraries.EnumerateObject()) { if (library.Name.StartsWith(UmbrellaPackage.Id, StringComparison.OrdinalIgnoreCase) - && string.Equals(StringProperty(library.Value, "type"), "project", StringComparison.Ordinal)) + && string.Equals(StringProperty(library.Value, "type"), "project", StringComparison.Ordinal)) { offenders.Add($"library '{library.Name}' is project-typed"); } @@ -112,14 +115,14 @@ public static List WorkspaceLeaks(string manifestText, string repository public static bool IsLuaRuntimeFileName(string fileName) { return fileName.StartsWith("lua", StringComparison.OrdinalIgnoreCase) - && fileName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase); + && fileName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase); } private static string StringProperty(JsonElement element, string name) { return element.ValueKind == JsonValueKind.Object - && element.TryGetProperty(name, out JsonElement value) - && value.ValueKind == JsonValueKind.String + && element.TryGetProperty(name, out JsonElement value) + && value.ValueKind == JsonValueKind.String ? value.GetString()! : ""; } diff --git a/tests/CheatEngine.SDK.Tests/Packaging/LivePluginClosureTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/LivePluginClosureTests.cs index 75e41954..9e51e227 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/LivePluginClosureTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/LivePluginClosureTests.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Globalization; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; @@ -59,7 +60,8 @@ public void Live_plugin_output_closure_matches_the_workspace_bridge(string proje foreach (JsonProperty library in target.EnumerateObject()) { string name = library.Name[..library.Name.IndexOf('/', StringComparison.Ordinal)]; - if (name.StartsWith("CheatEngine.SDK.", StringComparison.Ordinal) && !string.Equals(name, project, StringComparison.Ordinal)) + if (name.StartsWith("CheatEngine.SDK.", StringComparison.Ordinal) && + !string.Equals(name, project, StringComparison.Ordinal)) { sdkLibraries.Add(name); } @@ -76,7 +78,8 @@ public void Live_plugin_output_closure_matches_the_workspace_bridge(string proje Assert.Superset(new HashSet(s_bootstrapLibraries, StringComparer.Ordinal), sdkLibraries); foreach (string file in promised) { - Assert.True(File.Exists(Path.Combine(folder, file)), $"{project}.deps.json promises {file}, which is not in {folder}."); + Assert.True(File.Exists(Path.Combine(folder, file)), + $"{project}.deps.json promises {file}, which is not in {folder}."); } foreach (string assembly in Directory.EnumerateFiles(folder, "CheatEngine.SDK.*.dll")) @@ -86,7 +89,8 @@ public void Live_plugin_output_closure_matches_the_workspace_bridge(string proje } // The runtime policy is the one the managed hostfxr profile loads: net10.0 on the shared Microsoft.NETCore.App. - using JsonDocument runtimeConfig = JsonDocument.Parse(File.ReadAllBytes(Path.Combine(folder, project + ".runtimeconfig.json"))); + using JsonDocument runtimeConfig = + JsonDocument.Parse(File.ReadAllBytes(Path.Combine(folder, project + ".runtimeconfig.json"))); JsonElement options = runtimeConfig.RootElement.GetProperty("runtimeOptions"); Assert.Equal("net10.0", options.GetProperty("tfm").GetString()); Assert.Equal("Microsoft.NETCore.App", options.GetProperty("framework").GetProperty("name").GetString()); @@ -99,7 +103,8 @@ public void Live_plugin_output_closure_matches_the_workspace_bridge(string proje foreach (string file in Directory.EnumerateFiles(folder, "*.dll")) { string name = Path.GetFileName(file); - Assert.False(name.StartsWith("lua", StringComparison.OrdinalIgnoreCase), $"{folder} deploys a Lua runtime, {name}."); + Assert.False(name.StartsWith("lua", StringComparison.OrdinalIgnoreCase), + $"{folder} deploys a Lua runtime, {name}."); } } @@ -129,7 +134,9 @@ public void Live_plugin_entry_point_is_present_unless_listed_as_a_pending_fix(st /// private static string BundleFolder(string project) { - string configuration = new DirectoryInfo(AppContext.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)).Name; + string configuration = + new DirectoryInfo(AppContext.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar, + Path.AltDirectorySeparatorChar)).Name; string folder = RepositoryLayout.PathOf($"artifacts/bin/{project}/{configuration}"); Assert.True(File.Exists(Path.Combine(folder, project + ".dll")), $"{project} has no {configuration} output in {folder}: build CheatEngine.SDK.slnx -c {configuration} first."); @@ -146,7 +153,7 @@ private static string BundleFolder(string project) { TypeDefinition type = reader.GetTypeDefinition(typeHandle); if (!string.Equals(reader.GetString(type.Namespace), "CESDK", StringComparison.Ordinal) - || !string.Equals(reader.GetString(type.Name), "CESDK", StringComparison.Ordinal)) + || !string.Equals(reader.GetString(type.Name), "CESDK", StringComparison.Ordinal)) { continue; } @@ -159,10 +166,15 @@ private static string BundleFolder(string project) continue; } - MethodSignature decoded = method.DecodeSignature(SignatureNames.Instance, genericContext: null); - string access = (method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public ? "public" : "non-public"; - string binding = (method.Attributes & MethodAttributes.Static) != MethodAttributes.PrivateScope ? "static" : "instance"; - return $"{access} {binding} {decoded.ReturnType} CEPluginInitialize({string.Join(", ", decoded.ParameterTypes)})"; + MethodSignature decoded = method.DecodeSignature(SignatureNames.Instance, null); + string access = (method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public + ? "public" + : "non-public"; + string binding = (method.Attributes & MethodAttributes.Static) != MethodAttributes.PrivateScope + ? "static" + : "instance"; + return + $"{access} {binding} {decoded.ReturnType} CEPluginInitialize({string.Join(", ", decoded.ParameterTypes)})"; } } @@ -202,7 +214,8 @@ public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle ha return reader.GetString(reference.Namespace) + "." + reader.GetString(reference.Name); } - public string GetTypeFromSpecification(MetadataReader reader, object? genericContext, TypeSpecificationHandle handle, byte rawTypeKind) + public string GetTypeFromSpecification(MetadataReader reader, object? genericContext, + TypeSpecificationHandle handle, byte rawTypeKind) { return "typespec"; } @@ -234,12 +247,12 @@ public string GetGenericInstantiation(string genericType, ImmutableArray public string GetGenericMethodParameter(object? genericContext, int index) { - return "!!" + index.ToString(System.Globalization.CultureInfo.InvariantCulture); + return "!!" + index.ToString(CultureInfo.InvariantCulture); } public string GetGenericTypeParameter(object? genericContext, int index) { - return "!" + index.ToString(System.Globalization.CultureInfo.InvariantCulture); + return "!" + index.ToString(CultureInfo.InvariantCulture); } public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired) diff --git a/tests/CheatEngine.SDK.Tests/Packaging/PackageProvenanceTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/PackageProvenanceTests.cs index f970bf89..e743833b 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/PackageProvenanceTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/PackageProvenanceTests.cs @@ -7,7 +7,8 @@ namespace CheatEngine.SDK.Tests.Packaging; /// /// Which file every other packaging fact is about. In the CI Release leg the fixture must consume the exact /// .nupkg named by (the file uploaded as -/// nuget-package, attested and published) and never pack; only a local run outside CI may pack the working tree. +/// nuget-package, attested and published) and never pack; only a local run outside CI may pack the working +/// tree. /// The identity of the consumed file is written to the test output, so it lands in the TRX next to the results. /// [Collection(PackagedUmbrellaSuite.Name)] diff --git a/tests/CheatEngine.SDK.Tests/Packaging/PackagedUmbrellaTraitTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/PackagedUmbrellaTraitTests.cs index 18b1de83..6e6f0d14 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/PackagedUmbrellaTraitTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/PackagedUmbrellaTraitTests.cs @@ -5,7 +5,8 @@ namespace CheatEngine.SDK.Tests.Packaging; /// -/// The Debug CI leg excludes the packaging fixture with --filter-not-trait "Category=Packaging", and the Release +/// The Debug CI leg excludes the packaging fixture with --filter-not-trait "Category=Packaging", and the +/// Release /// leg hands it the exact package. That only works if the trait and the collection coincide: a collection class /// without the trait would start a pack in the Debug leg (or fail it under CI=true), and a traited class /// outside the collection would silently drop out of the Debug leg. Read through , @@ -29,13 +30,13 @@ public void Every_packaged_umbrella_collection_class_carries_the_packaging_trait if (!HasPackagingTrait(type)) { offenders.Add($"{type.FullName} joins '{PackagedUmbrellaSuite.Name}' without " + - $"[Trait(\"{CategoryTrait}\", UmbrellaPackage.PackagingCategory)]."); + $"[Trait(\"{CategoryTrait}\", UmbrellaPackage.PackagingCategory)]."); } } else if (ReceivesTheFixture(type)) { offenders.Add($"{type.FullName} receives {nameof(PackagedUmbrellaFixture)} outside collection " + - $"'{PackagedUmbrellaSuite.Name}', so it would get its own pack."); + $"'{PackagedUmbrellaSuite.Name}', so it would get its own pack."); } } @@ -87,8 +88,9 @@ private static List TestTypes() private static bool HasTestMethod(Type type) { - foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | - BindingFlags.DeclaredOnly)) + foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | + BindingFlags.Static | + BindingFlags.DeclaredOnly)) { foreach (CustomAttributeData attribute in method.GetCustomAttributesData()) { @@ -142,9 +144,9 @@ private static bool HasPackagingTrait(MemberInfo member) foreach (CustomAttributeData attribute in member.GetCustomAttributesData()) { if (attribute.AttributeType == typeof(TraitAttribute) - && attribute.ConstructorArguments.Count == 2 - && Equals(attribute.ConstructorArguments[0].Value, CategoryTrait) - && Equals(attribute.ConstructorArguments[1].Value, UmbrellaPackage.PackagingCategory)) + && attribute.ConstructorArguments.Count == 2 + && Equals(attribute.ConstructorArguments[0].Value, CategoryTrait) + && Equals(attribute.ConstructorArguments[1].Value, UmbrellaPackage.PackagingCategory)) { return true; } @@ -155,8 +157,9 @@ private static bool HasPackagingTrait(MemberInfo member) private static bool HasPackagingTraitOnAMethod(Type type) { - foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | - BindingFlags.DeclaredOnly)) + foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | + BindingFlags.Static | + BindingFlags.DeclaredOnly)) { if (HasPackagingTrait(method)) { diff --git a/tests/CheatEngine.SDK.Tests/Packaging/SupplyChainPackageTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/SupplyChainPackageTests.cs index f134c846..3958249b 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/SupplyChainPackageTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/SupplyChainPackageTests.cs @@ -46,11 +46,12 @@ public void Package_embeds_an_spdx_2_2_sbom_describing_itself() Assert.Equal(NuspecMetadata("id"), package.GetProperty("name").GetString()); Assert.Equal(fixture.PackageVersion, package.GetProperty("versionInfo").GetString()); Assert.Equal(fixture.PackageVersion, NuspecMetadata("version")); - Assert.StartsWith($"{RepositoryUrl}/", root.GetProperty("documentNamespace").GetString(), StringComparison.Ordinal); + Assert.StartsWith($"{RepositoryUrl}/", root.GetProperty("documentNamespace").GetString(), + StringComparison.Ordinal); // The sidecar checksum the SBOM tool writes next to the manifest matches it. string sidecar = Encoding.ASCII.GetString(ReadEntry(archive, SbomChecksumEntry)).Trim(); - Assert.Equal(Sha256(manifest), sidecar, ignoreCase: true); + Assert.Equal(Sha256(manifest), sidecar, true); } [Fact] @@ -63,18 +64,19 @@ public void Sbom_lists_every_shipped_assembly_and_the_native_bridge_with_its_sha foreach (string entry in fixture.PackageEntries) { if ((entry.StartsWith("lib/net10.0/", StringComparison.Ordinal) - || entry.StartsWith("analyzers/dotnet/cs/", StringComparison.Ordinal)) - && entry.EndsWith(".dll", StringComparison.Ordinal)) + || entry.StartsWith("analyzers/dotnet/cs/", StringComparison.Ordinal)) + && entry.EndsWith(".dll", StringComparison.Ordinal)) { shipped.Add(entry); } } - Assert.True(shipped.Count >= 13, $"Expected the 7 libraries, 5 components and the bridge, found {shipped.Count}."); + Assert.True(shipped.Count >= 13, + $"Expected the 7 libraries, 5 components and the bridge, found {shipped.Count}."); foreach (string entry in shipped) { Assert.True(sbomSha256.TryGetValue(entry, out string? declared), $"The SBOM does not list '{entry}'."); - Assert.Equal(Sha256(ReadEntry(archive, entry)), declared, ignoreCase: true); + Assert.Equal(Sha256(ReadEntry(archive, entry)), declared, true); } } @@ -156,7 +158,8 @@ public void Embedded_libraries_carry_source_link_to_the_repository_commit() MetadataReader pdb = pdbProvider.GetMetadataReader(); string? sourceLink = null; - foreach (CustomDebugInformationHandle handle in pdb.GetCustomDebugInformation(EntityHandle.ModuleDefinition)) + foreach (CustomDebugInformationHandle handle in + pdb.GetCustomDebugInformation(EntityHandle.ModuleDefinition)) { CustomDebugInformation information = pdb.GetCustomDebugInformation(handle); if (pdb.GetGuid(information.Kind) == s_sourceLinkKind) @@ -184,7 +187,7 @@ private List LibraryEntries() foreach (string entry in fixture.PackageEntries) { if (entry.StartsWith("lib/net10.0/CheatEngine.SDK", StringComparison.Ordinal) - && entry.EndsWith(".dll", StringComparison.Ordinal)) + && entry.EndsWith(".dll", StringComparison.Ordinal)) { libraries.Add(entry); } @@ -225,7 +228,7 @@ private static Dictionary SbomFileSha256(ZipArchive archive) private static byte[] ReadEntry(ZipArchive archive, string entryName) { ZipArchiveEntry entry = archive.GetEntry(entryName) - ?? throw new InvalidOperationException($"The package has no '{entryName}' entry."); + ?? throw new InvalidOperationException($"The package has no '{entryName}' entry."); using Stream stream = entry.Open(); using MemoryStream copy = new(); stream.CopyTo(copy); @@ -244,6 +247,6 @@ private static Version CoreVersion(string packageVersion) return Version.Parse(core); } - [GeneratedRegex("^[0-9a-f]{40}$", RegexOptions.CultureInvariant, matchTimeoutMilliseconds: 1000)] + [GeneratedRegex("^[0-9a-f]{40}$", RegexOptions.CultureInvariant, 1000)] private static partial Regex CommitSha(); } diff --git a/tests/CheatEngine.SDK.Tests/Packaging/UmbrellaPackageSourceTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/UmbrellaPackageSourceTests.cs index 427e3d57..e2f50a38 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/UmbrellaPackageSourceTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/UmbrellaPackageSourceTests.cs @@ -82,7 +82,8 @@ public void Missing_variable_under_ci_fails_with_an_actionable_message(string? v Assert.StartsWith(UmbrellaPackage.PrebuiltPackageVariable + " is not set while CI=true.", failure.Message, StringComparison.Ordinal); Assert.Contains("--filter-not-trait \"Category=Packaging\"", failure.Message, StringComparison.Ordinal); - Assert.Contains("tests/CheatEngine.SDK.Tests/README.md#run-the-tests", failure.Message, StringComparison.Ordinal); + Assert.Contains("tests/CheatEngine.SDK.Tests/README.md#run-the-tests", failure.Message, + StringComparison.Ordinal); } [Theory] diff --git a/tests/CheatEngine.SDK.Tests/README.md b/tests/CheatEngine.SDK.Tests/README.md index 6da39775..ef0aa524 100644 --- a/tests/CheatEngine.SDK.Tests/README.md +++ b/tests/CheatEngine.SDK.Tests/README.md @@ -16,14 +16,16 @@ A project reference proves that the source compiles, not that the installed pack 1. One collection fixture (`PackagedUmbrellaFixture`) puts one `CheatEngine.SDK` package into a temporary local feed. Its origin is decided first, by `UmbrellaPackageSource`: - - `CESDK_PACKAGED_UMBRELLA_NUPKG` set: it must be the absolute path of a `CheatEngine.SDK..nupkg` file. The - fixture copies exactly that file and never packs. This is the CI Release leg: it packs once, passes the packed file, - and the same file is uploaded as `nuget-package`, attested and published, so these tests are evidence about the - shipped file. - - Unset while `CI=true`: the fixture fails at once with an actionable message. A CI run must test the file it ships, - and the Debug leg excludes these tests with `--filter-not-trait "Category=Packaging"`. - - Unset outside CI: the fixture packs `src/CheatEngine.SDK/CheatEngine.SDK.csproj` in Release itself. That package is - built from your working tree; it is evidence about the source (C1/C2), not about a file that was ever shipped. + - `CESDK_PACKAGED_UMBRELLA_NUPKG` set: it must be the absolute path of a `CheatEngine.SDK..nupkg` file. The + fixture copies exactly that file and never packs. This is the CI Release leg: it packs once, passes the packed + file, + and the same file is uploaded as `nuget-package`, attested and published, so these tests are evidence about the + shipped file. + - Unset while `CI=true`: the fixture fails at once with an actionable message. A CI run must test the file it ships, + and the Debug leg excludes these tests with `--filter-not-trait "Category=Packaging"`. + - Unset outside CI: the fixture packs `src/CheatEngine.SDK/CheatEngine.SDK.csproj` in Release itself. That package + is + built from your working tree; it is evidence about the source (C1/C2), not about a file that was ever shipped. The package id, that project path, the variable name, the `Packaging` category and the lower-cased id NuGet uses as the extraction folder name live in one place, `UmbrellaPackage`. Every class of the `PackagedUmbrellaSuite` From 99950886802d2afb83f87a8d5c294f3bdd81c4e3 Mon Sep 17 00:00:00 2001 From: AriusII Date: Wed, 23 Sep 2026 23:32:24 +0200 Subject: [PATCH 3/4] Repair reformat regressions and restore build and test compliance The IDE-wide reformat commit (09df927) mixed genuine style fixes with several unrelated regressions: - Silently dropped the `partial` modifier from five classes hosting `[LuaFunction]`/`[LuaGlobal]` members (BenchFunctions, CoexistencePluginAFunctions, CoexistencePluginBFunctions, LiveFunctions, ProbeConsole), breaking the LuaBindings source generator's companion emission for each. - Renamed the CE 7.7 bootstrap's `CESDK` namespace to `LiveProbe` and dropped its `using LiveProbe;`, which would have broken Cheat Engine's hard-coded `CESDK.CESDK` host lookup. - Removed two `using CheatEngine.SDK.Engine.Generated;` directives that a source-generator-blind IDE inspection flagged as unused, and renamed a namespace in a LiveProbe.Tests stub that is intentionally paired with a source-linked file in the `LiveProbe` namespace. - Line-wrapped three `` entries in CompatibilitySuppressions.xml, breaking ApiCompat's exact-match lookup against already-approved 2.0.0 breaking changes on AddressResolutionOptions. - Padded a markdown table in src/CheatEngine.SDK/README.md past a doc-consistency test's exact substring check. - Swapped `static const char` for `static constexpr char` in the native Lua bridge, invalidating its pinned SHA-256 proof record. This commit reverts each regression and lets dotnet format finish applying the remaining, legitimate IDE0055/IDE0048 whitespace and clarity fixes across the tree. It also splits GovernanceWorkflowTests.Dependency_submit_step_submits_only_a_snapshot_of_this_run, which had grown past MA0051's 60-line limit, extracting BuildDependencySnapshot as a helper. The packages.lock.json refresh across projects reflects the Meziantou.Analyzer 3.0.290 pin already recorded in Directory.Packages.props by the reformat commit. Verified: dotnet build (0 warnings, 0 errors), dotnet format --verify-no-changes (clean), and dotnet test --solution CheatEngine.SDK.slnx --fail-skips on (4167/4168; the sole remaining failure is PackedConsumerBindingTests' Native AOT publish, which needs the MSVC/vswhere.exe linker toolchain this environment does not have and is unrelated to this change). --- .../Plugin/PluginClassRewriter.cs | 8 +- .../Plugin/PluginClassShapeCodeFixProvider.cs | 20 ++-- .../Usage/ExceptionGuardRewriter.cs | 2 +- ...nmanagedCallersOnlyGuardCodeFixProvider.cs | 36 +++---- .../packages.lock.json | 6 +- .../Generation/LuaBindingAnalyzer.cs | 4 +- .../Generation/LuaFunctionDuplicateState.cs | 2 +- .../Generation/LuaObjectBindingAnalyzer.cs | 52 ++++----- .../Plugin/CheatEnginePluginAnalyzer.cs | 40 +++---- .../Plugin/ClassicNativeExportAnalyzer.cs | 6 +- .../Plugin/PluginCompilationState.cs | 2 +- .../Usage/ExceptionGuard.cs | 50 ++++----- .../Usage/HostWidthPointerSizeAnalyzer.cs | 26 ++--- .../PluginLifecycleAndOwnershipAnalyzer.cs | 16 +-- .../UnmanagedCallersOnlyGuardAnalyzer.cs | 2 +- .../WellKnown/SdkSymbolResolver.cs | 2 +- .../packages.lock.json | 6 +- .../BoundedDebugEventObservationBuffer.cs | 2 +- .../Native/ClassicDebugEventDispatcher.cs | 6 +- libs/CheatEngine.SDK.Abi/packages.lock.json | 6 +- .../packages.lock.json | 6 +- .../AddressList/AddressListCalls.cs | 2 +- .../AddressList/AddressListMutations.cs | 2 +- .../Allocation/AllocatedRegion.cs | 4 +- .../Allocation/TargetMemoryAllocator.cs | 2 +- .../Assembly/AutoAssemblerPatcher.cs | 2 +- .../Assembly/InstructionDisassembler.cs | 6 +- .../Assembly/InstructionProfiles.cs | 4 +- .../Enums/CEEnumNames.cs | 4 +- .../EngineGlobalUnavailableException.cs | 2 +- .../Errors/EngineLuaException.cs | 2 +- .../Errors/EngineMarshallingException.cs | 4 +- .../Errors/EngineResourceHandoffException.cs | 4 +- .../Errors/EngineTargetIdentityException.cs | 2 +- .../Inspection/EngineInspection.cs | 42 ++++---- .../Inspection/SymbolLists.cs | 4 +- .../Inspection/SymbolRegistry.cs | 8 +- .../Inspection/SymbolTableReader.cs | 2 +- .../Memory/HostMemory.cs | 24 ++--- .../Memory/MemoryLua.cs | 4 +- .../Memory/TargetMemory.cs | 32 +++--- .../Objects/EngineResourceOrigin.cs | 2 +- .../Objects/StringLists.cs | 4 +- .../Processes/RuntimeHostOperations.cs | 4 +- .../Processes/RuntimeObservations.cs | 5 +- .../Processes/RuntimeProcessOperations.cs | 2 +- .../Processes/TargetArchitectureProbe.cs | 4 +- .../Runtime/CheatEngineVersion.cs | 6 +- .../Scanning/Aob/AobBoundedScan.cs | 8 +- .../Scanning/Aob/AobScanBounds.cs | 2 +- .../Scanning/Aob/AobScanOptions.cs | 4 +- .../Scanning/Values/MemoryScanSession.cs | 10 +- .../Scanning/Values/MemoryScanSessions.cs | 4 +- .../Values/MemoryScanStateException.cs | 2 +- .../Targets/TargetSelection.cs | 2 +- libs/CheatEngine.SDK.Engine/Values/Address.cs | 2 +- .../CheatEngine.SDK.Engine/packages.lock.json | 6 +- .../Bootstrap/PluginHost.Lifecycle.cs | 14 +-- .../Bootstrap/PluginHost.cs | 4 +- .../Diagnostics/LoadIdentification.cs | 10 +- .../Threading/MainThreadDispatcher.cs | 6 +- .../packages.lock.json | 6 +- .../Protected/LuaBridgeContract.cs | 20 ++-- .../packages.lock.json | 6 +- .../Callbacks/LuaCallback.cs | 4 +- .../Callbacks/LuaHostSubscription.cs | 10 +- .../Callbacks/LuaHostSubscriptionRegistry.cs | 4 +- .../CompilerServices/LuaCallSupport.cs | 2 +- .../Marshalling/LuaIntegerReader.cs | 6 +- .../Marshalling/LuaOptional.cs | 2 +- libs/CheatEngine.SDK.Lua/References/LuaRef.cs | 4 +- .../Registration/LuaRegistrationSet.cs | 2 +- .../Runtime/LuaHostBinding.cs | 2 +- .../CheatEngine.SDK.Lua/Runtime/LuaRuntime.cs | 10 +- .../State/LuaState.Tables.cs | 2 +- libs/CheatEngine.SDK.Lua/packages.lock.json | 6 +- .../cheatengine_sdk_lua_bridge.c | 2 +- .../Emit/EngineApiFileEmitter.cs | 3 +- .../Model/SpecFiles.cs | 15 ++- .../Parsing/SpecFileParser.cs | 80 +++++++------- .../Parsing/SpecIdentifiers.cs | 2 +- .../packages.lock.json | 6 +- .../Emit/BootstrapEmitter.cs | 4 +- .../Parsing/EntryPointContractSymbols.cs | 2 +- .../EntryPointDeclaredDiagnosticIds.cs | 22 ++-- .../Parsing/EntryPointGeneratedIdentity.cs | 4 +- .../packages.lock.json | 6 +- .../Emit/LuaObjectMembersFileEmitter.cs | 2 +- .../Model/LuaFunctionModel.cs | 2 +- .../Model/LuaFunctionTables.cs | 5 +- .../Model/LuaGlobalModel.cs | 2 +- .../Model/LuaGlobalTables.cs | 5 +- .../Model/LuaObjectMembersTables.cs | 5 +- .../Parsing/ContainingTypeParser.cs | 2 +- .../LuaBindingsDeclaredDiagnosticIds.cs | 18 ++-- .../Parsing/LuaClassParser.cs | 18 ++-- .../Parsing/LuaFunctionParser.cs | 6 +- .../Parsing/LuaGlobalParser.cs | 2 +- .../Parsing/LuaObjectMethodParser.cs | 48 +++++---- .../Parsing/LuaObjectPropertyParser.cs | 36 ++++--- .../packages.lock.json | 6 +- .../ProtectedOperationCatalogParser.cs | 10 +- .../packages.lock.json | 6 +- .../GeneratedCodeText.cs | 8 +- .../HintNames.cs | 4 +- .../Parsing/ContainingTypeShape.cs | 2 +- .../LuaBindings/Parsing/Identifiers.cs | 2 +- .../Parsing/LuaClassGeneratedNames.cs | 14 +-- .../LuaBindings/Parsing/LuaContractTypes.cs | 10 +- .../LuaBindings/Parsing/LuaFunctionShape.cs | 10 +- .../LuaBindings/Parsing/LuaGlobalShape.cs | 32 +++--- .../Parsing/LuaMarshallerResolver.cs | 24 ++--- .../LuaBindings/Parsing/LuaValueKindMapper.cs | 12 +-- .../LuaEmit/LuaGlobalCallEmitter.cs | 4 +- .../LuaEmit/LuaGlobalCallModel.cs | 6 +- .../LuaEmit/LuaNames.cs | 2 +- .../LuaEmit/LuaResultModel.cs | 2 +- .../LuaEmit/LuaThunkEmitter.cs | 2 +- .../LuaEmit/LuaThunkModel.cs | 2 +- .../Shapes/PluginShape.cs | 10 +- .../packages.lock.json | 6 +- .../CompatibilitySuppressions.xml | 10 +- src/CheatEngine.SDK/README.md | 14 +-- src/CheatEngine.SDK/packages.lock.json | 6 +- .../FieldLayout/FieldLayoutContractTests.cs | 6 +- .../Fixture/NativeAbiFixtureContractTests.cs | 4 +- .../NativeAbiFixtureManagedComparisonTests.cs | 2 +- .../Managed/PluginInitRecordTests.cs | 2 +- ...assicExportedFunctionsPrefixReaderTests.cs | 6 +- .../Native/ExportedFunctionsPrefixTests.cs | 12 +-- .../Native/PluginType0RecordTests.cs | 2 +- .../Native/SelectedRecordOracleTests.cs | 4 +- .../Support/ClassicSlotRegistry.cs | 4 +- .../Support/FieldLayoutGate.cs | 2 +- .../packages.lock.json | 6 +- .../LuaDirectApiBoundaryGuardTests.cs | 60 +++++------ .../Diagnostics/DiagnosticCatalogTests.cs | 6 +- .../Generation/LuaBindingAnalyzerTests.cs | 42 ++++---- .../Infrastructure/CodeFixVerifier.cs | 3 +- .../LocalFrameworkReferences.cs | 4 +- .../LocalFrameworkReferencesTests.cs | 2 +- .../Infrastructure/RepositoryLayout.cs | 4 +- .../packages.lock.json | 6 +- .../BenchFunctions.cs | 2 +- .../CallbackBenchmarks.cs | 2 +- .../EngineApiIncrementalBenchmarks.cs | 2 +- .../GlobalCallBenchmarks.cs | 2 +- .../MemoryScalarBenchmarks.cs | 10 +- .../Support/FakeHostRuntime.cs | 2 +- .../packages.lock.json | 6 +- .../AddressList/AddressListExitTests.cs | 10 +- .../Allocation/AllocatedRegionTests.cs | 40 +++++-- ...uaTargetMemoryAllocationOperationsTests.cs | 2 +- .../Allocation/TargetMemoryAllocatorTests.cs | 79 +++++++++++--- .../AutoAssemblerDisableInfoSnapshotTests.cs | 6 +- .../Assembly/InstructionOperationsTests.cs | 6 +- .../Inspection/EngineInspectionTests.cs | 10 +- .../Inspection/SymbolListTests.cs | 8 +- .../Memory/AddressTypeSeparationTests.cs | 2 +- .../Memory/MemoryScalarsFidelityTests.cs | 1 + .../Objects/OwnershipSurfaceTests.cs | 4 +- .../RuntimeProcessOperationsTests.cs | 2 +- .../Runtime/RuntimeCapabilityProbesTests.cs | 1 + .../Runtime/RuntimeContractsTests.cs | 10 +- .../Scanning/Aob/AobBoundedScanTests.cs | 8 +- .../Scanning/Aob/AobFirstFoundScanTests.cs | 6 +- .../Scanning/MemScanTestHost.cs | 6 +- .../Scanning/MemoryScanSessionFactoryTests.cs | 4 +- .../Scanning/MemoryScanSessionTests.cs | 20 ++-- .../Scanning/ScanExperimentalApiTests.cs | 4 +- .../Values/MemoryScanSessionDeadlineTests.cs | 4 +- .../Support/FakeHost.Rt.cs | 2 +- .../Support/FakeHost.SRes.cs | 8 +- .../Support/FakeHost.cs | 16 +-- .../Tables/CheatTableFilesTests.cs | 8 +- .../Targets/TargetSelectionTests.cs | 4 +- .../packages.lock.json | 6 +- .../Coexistence/CoexistencePluginLayout.cs | 2 +- .../Coexistence/NativeHostEmulatorRunner.cs | 5 +- .../Diagnostics/HostLogContainmentTests.cs | 2 +- .../Support/RecordingPlugin.cs | 8 +- .../packages.lock.json | 6 +- .../PluginA/CoexistencePluginAFunctions.cs | 2 +- .../PluginA/packages.lock.json | 6 +- .../PluginB/CoexistencePluginBFunctions.cs | 2 +- .../PluginB/packages.lock.json | 6 +- .../LiveFunctions.cs | 2 +- .../packages.lock.json | 6 +- .../LiveProbeStatusTests.cs | 6 +- .../ProbeHostGlobals.cs | 2 +- .../packages.lock.json | 6 +- .../CE77LiveProbeBootstrap.cs | 4 +- .../HostProfileObservation.cs | 6 +- .../LiveProbeAuthorization.cs | 28 ++--- .../LiveProbeFaultInjection.cs | 8 +- .../LiveProbeState.cs | 46 ++++++-- .../CheatEngine.SDK.LiveProbe/ProbeConsole.cs | 2 +- .../packages.lock.json | 6 +- .../Program.cs | 10 +- .../packages.lock.json | 6 +- .../Initialization/LuaApiBoundTableTests.cs | 2 +- .../Protected/LuaBridgeContractTests.cs | 2 +- .../LuaInteropPrimitiveMatrixTests.cs | 19 ++-- .../RoundTrips/CallTests.cs | 8 +- .../Support/IlReader.cs | 2 +- .../packages.lock.json | 6 +- .../Allocation/ZeroAllocationTests.cs | 6 +- .../Callbacks/LuaCallbackTests.cs | 5 +- .../Callbacks/LuaHostSubscriptionTests.cs | 24 ++--- .../LuaCallSupportOptionalTests.cs | 4 +- .../Generated/MemoryBindings.cs | 2 +- .../Protected/NativeFailureProcessTests.cs | 8 +- .../packages.lock.json | 6 +- .../packages.lock.json | 6 +- .../LibraryProbeContractTests.cs | 2 +- .../Support/BridgeImage.cs | 4 +- .../packages.lock.json | 6 +- .../LibraryProbeContract.cs | 4 +- .../Program.cs | 2 +- .../packages.lock.json | 6 +- .../ImageScanner.cs | 2 +- .../Program.cs | 4 +- .../packages.lock.json | 6 +- .../Abi/ClassicSlotRegistryDocumentTests.cs | 6 +- .../Abi/NativeAotProfileDocumentTests.cs | 8 +- .../Abi/RepositoryDocument.cs | 5 +- .../ApiGates/ApiGateDiagnosticTests.cs | 2 +- .../Diagnostics/ApiDiagnosticIdTests.cs | 6 +- .../Generation/GeneratorInventoryTests.cs | 4 +- .../DependabotConfigurationTests.cs | 10 +- .../Governance/GovernanceDocumentTests.cs | 6 +- .../Governance/GovernanceWorkflowTests.cs | 100 ++++++++++-------- .../Governance/PwshScript.cs | 4 +- .../ConcurrencyContractDocumentationTests.cs | 12 +-- .../Infrastructure/RepositoryRoot.cs | 4 +- .../LuaInteropPrimitiveMatrixDocumentTests.cs | 14 +-- .../ProtectedOperationCatalogTests.cs | 4 +- .../Ownership/OwnershipPolicyTests.cs | 8 +- .../PublicApi/EnumContractTests.cs | 4 +- .../PublicApi/PublicApiDeclarations.cs | 2 +- .../PublicApi/PublicApiLibrary.cs | 2 +- .../Release/ReleaseWorkflowContractTests.cs | 12 +-- .../Runtime/RuntimeCapabilitySpecTests.cs | 4 +- .../QualificationHarnessShapeTests.cs | 6 +- .../Toolchain/ToolchainPinTests.cs | 6 +- .../Workflows/WorkflowContract.cs | 4 +- .../WorkflowContractTests.BuildTest.cs | 28 ++--- .../Workflows/WorkflowContractTests.Gate.cs | 10 +- .../WorkflowContractTests.Hygiene.cs | 6 +- .../WorkflowContractTests.Restore.cs | 4 +- .../Workflows/WorkflowContractTests.Supply.cs | 2 +- .../packages.lock.json | 6 +- .../Generator/DiagnosticsTests.cs | 14 +-- .../Generator/EmissionTests.cs | 10 +- .../EngineApiDiagnosticCatalogTests.cs | 4 +- .../Generator/IncrementalityTests.cs | 6 +- .../Infrastructure/GeneratedAssembly.cs | 4 +- .../LocalFrameworkReferences.cs | 4 +- .../Infrastructure/ModelGraph.cs | 2 +- .../Infrastructure/ProductionSpecs.cs | 2 +- .../Parsing/SpecFileParserTests.cs | 38 +++---- .../packages.lock.json | 6 +- .../Generator/ContractIdentityTests.cs | 6 +- .../Generator/NameEscapingTests.cs | 2 +- .../Generator/NominalOutputTests.cs | 8 +- .../Generator/RealAssemblyCompilationTests.cs | 6 +- .../Infrastructure/GeneratorRun.cs | 6 +- .../Infrastructure/LoadedBootstrap.cs | 2 +- .../LocalFrameworkReferences.cs | 4 +- .../Infrastructure/ModelGraph.cs | 2 +- .../Model/BootstrapModelTests.cs | 25 ++++- .../packages.lock.json | 6 +- .../LuaGlobalOptionalArgumentEndToEndTests.cs | 10 +- .../LuaGlobalResultCountEndToEndTests.cs | 2 +- .../Generator/ContainingTypeTests.cs | 16 +-- .../Generator/DefaultVerifierTests.cs | 3 +- .../Generator/IncrementalityTests.cs | 8 +- .../Generator/LuaFunctionOutputTests.cs | 8 +- .../Generator/LuaGlobalOutputTests.cs | 6 +- .../Generator/LuaObjectOutputTests.cs | 2 +- .../Generator/NoOutputTests.cs | 12 +-- .../Generator/PartialMethodSignatureTests.cs | 24 ++--- .../Infrastructure/GeneratorRun.cs | 6 +- .../LocalFrameworkReferences.cs | 4 +- .../Infrastructure/ModelGraph.cs | 2 +- .../Model/LuaFunctionTablesTests.cs | 8 +- .../Model/LuaGlobalTablesTests.cs | 3 +- .../SharedCode/HintNamesTests.cs | 2 +- .../SharedCode/LuaApiNamesTests.cs | 4 +- .../SharedCode/LuaGlobalCallEmitterTests.cs | 13 ++- .../SharedCode/LuaThunkEmitterTests.cs | 4 +- .../packages.lock.json | 6 +- .../Generator/CatalogDiagnosticsTests.cs | 12 +-- .../Generator/CatalogEmissionTests.cs | 2 +- .../packages.lock.json | 6 +- .../NativeLua/NativeLuaProbe.cs | 2 +- .../NativeLua/PartialLuaModule.cs | 6 +- .../packages.lock.json | 6 +- .../ProjectDependencyDirectionTests.cs | 14 +-- .../Infrastructure/CommittedFile.cs | 5 +- .../Infrastructure/EntryPointProbe.cs | 4 +- .../Infrastructure/PackagedUmbrellaFixture.cs | 11 +- .../Infrastructure/ProcessRunner.cs | 5 +- .../Infrastructure/RepositoryLayout.cs | 4 +- .../Infrastructure/UmbrellaPackageSource.cs | 6 +- .../Packaging/BridgeAuditManifestTests.cs | 12 ++- .../Packaging/CleanConsumerIsolationTests.cs | 4 +- .../Packaging/ConsumerManifestRules.cs | 10 +- .../Packaging/LivePluginClosureTests.cs | 4 +- .../Packaging/PackagedUmbrellaTraitTests.cs | 18 ++-- .../Packaging/SupplyChainPackageTests.cs | 10 +- .../CheatEngine.SDK.Tests/packages.lock.json | 6 +- 312 files changed, 1446 insertions(+), 1227 deletions(-) diff --git a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassRewriter.cs b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassRewriter.cs index 20d04ff8..e0e532e4 100644 --- a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassRewriter.cs +++ b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassRewriter.cs @@ -57,8 +57,8 @@ public static ConstructorDeclarationSyntax MakePublic(ConstructorDeclarationSynt // 'private protected' and 'protected internal' are two keywords: drop the second one, but not what the // author wrote around it. Its comments move behind the modifier in front of it, which always exists. for (int next = IndexOfAccessibility(modifiers, first + 1); - next >= 0; - next = IndexOfAccessibility(modifiers, next)) + next >= 0; + next = IndexOfAccessibility(modifiers, next)) { SyntaxToken dropped = modifiers[next]; SyntaxToken previous = modifiers[next - 1]; @@ -79,7 +79,7 @@ private static SyntaxTriviaList FromFirstComment(SyntaxTriviaList trivia) foreach (SyntaxTrivia item in trivia) { if (kept.Count > 0 || - !(item.IsKind(SyntaxKind.WhitespaceTrivia) || item.IsKind(SyntaxKind.EndOfLineTrivia))) + !(item.IsKind(SyntaxKind.WhitespaceTrivia) || item.IsKind(SyntaxKind.EndOfLineTrivia))) { kept = kept.Add(item); } @@ -111,7 +111,7 @@ private static int IndexOfAccessibility(SyntaxTokenList modifiers, int start) for (int index = start; index < modifiers.Count; index++) { if (modifiers[index].Kind() is SyntaxKind.PublicKeyword or SyntaxKind.InternalKeyword - or SyntaxKind.ProtectedKeyword or SyntaxKind.PrivateKeyword) + or SyntaxKind.ProtectedKeyword or SyntaxKind.PrivateKeyword) { return index; } diff --git a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassShapeCodeFixProvider.cs b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassShapeCodeFixProvider.cs index 4926f9a2..589468a5 100644 --- a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassShapeCodeFixProvider.cs +++ b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Plugin/PluginClassShapeCodeFixProvider.cs @@ -80,10 +80,10 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) foreach (Diagnostic diagnostic in context.Diagnostics) { if (!diagnostic.Properties.TryGetValue(DiagnosticProperties.PluginClassProblem, out string? problemName) - || !Enum.TryParse(problemName, out PluginShapeIssues problem) - || root.FindToken(diagnostic.Location.SourceSpan.Start).Parent - ?.FirstAncestorOrSelf() is not { } declaration - || semanticModel.GetDeclaredSymbol(declaration, cancellationToken) is not { } type) + || !Enum.TryParse(problemName, out PluginShapeIssues problem) + || root.FindToken(diagnostic.Location.SourceSpan.Start).Parent + ?.FirstAncestorOrSelf() is not { } declaration + || semanticModel.GetDeclaredSymbol(declaration, cancellationToken) is not { } type) { continue; } @@ -117,7 +117,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) foreach (SyntaxReference reference in type.DeclaringSyntaxReferences) { if (reference.GetSyntax(cancellationToken) is not TypeDeclarationSyntax part - || solution.GetDocument(reference.SyntaxTree) is not { } document) + || solution.GetDocument(reference.SyntaxTree) is not { } document) { continue; } @@ -243,11 +243,11 @@ private static bool CanOmitEveryArgument(IMethodSymbol constructor) foreach (IMethodSymbol constructor in type.InstanceConstructors) { if (!constructor.Parameters.IsEmpty - || constructor.IsImplicitlyDeclared - || constructor.DeclaringSyntaxReferences.IsEmpty - || constructor.DeclaringSyntaxReferences[0] is not { } reference - || reference.GetSyntax(cancellationToken) is not ConstructorDeclarationSyntax syntax - || solution.GetDocument(reference.SyntaxTree) is not { } document) + || constructor.IsImplicitlyDeclared + || constructor.DeclaringSyntaxReferences.IsEmpty + || constructor.DeclaringSyntaxReferences[0] is not { } reference + || reference.GetSyntax(cancellationToken) is not ConstructorDeclarationSyntax syntax + || solution.GetDocument(reference.SyntaxTree) is not { } document) { continue; } diff --git a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/ExceptionGuardRewriter.cs b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/ExceptionGuardRewriter.cs index 345a5f11..b71d2474 100644 --- a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/ExceptionGuardRewriter.cs +++ b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/ExceptionGuardRewriter.cs @@ -57,7 +57,7 @@ public static BlockSyntax Guard(ArrowExpressionClauseSyntax expressionBody, Synt int statementPart = IndexAfterLastComment(afterSemicolon); SyntaxTriviaList withStatement = Slice(afterSemicolon, 0, statementPart); if (statementPart > 0 && afterSemicolon[statementPart - 1].IsKind(SyntaxKind.SingleLineCommentTrivia)) - // The closing brace of the try block follows: it must not end up inside the comment. + // The closing brace of the try block follows: it must not end up inside the comment. { withStatement = withStatement.Add(endOfLine); } diff --git a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/UnmanagedCallersOnlyGuardCodeFixProvider.cs b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/UnmanagedCallersOnlyGuardCodeFixProvider.cs index b95c46bb..46d12ee0 100644 --- a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/UnmanagedCallersOnlyGuardCodeFixProvider.cs +++ b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/Usage/UnmanagedCallersOnlyGuardCodeFixProvider.cs @@ -64,8 +64,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) { MethodDeclarationSyntax? declaration = FindDeclaration(root, diagnostic.Location.SourceSpan); if (declaration is null - || semanticModel.GetDeclaredSymbol(declaration, context.CancellationToken) is not IMethodSymbol method - || !HasKnownFailureConvention(method)) + || semanticModel.GetDeclaredSymbol(declaration, context.CancellationToken) is not IMethodSymbol method + || !HasKnownFailureConvention(method)) { continue; } @@ -107,8 +107,8 @@ private static async Task WrapAsync(Document document, MethodDeclarati SyntaxNode? root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SemanticModel? semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (root is null || - semanticModel?.GetDeclaredSymbol(declaration, cancellationToken) is not IMethodSymbol method - || !HasKnownFailureConvention(method)) + semanticModel?.GetDeclaredSymbol(declaration, cancellationToken) is not IMethodSymbol method + || !HasKnownFailureConvention(method)) { return document; } @@ -136,25 +136,25 @@ private static async Task WrapAsync(Document document, MethodDeclarati private static bool HasKnownFailureConvention(IMethodSymbol method) { if (!method.IsStatic - || method.IsGenericMethod - || method.DeclaredAccessibility != Accessibility.Public - || !string.Equals(method.Name, "CEPluginInitialize", StringComparison.Ordinal) - || method.ReturnsByRef - || method.ReturnsByRefReadonly - || method.ReturnType.SpecialType != SpecialType.System_Int32 - || method.Parameters.Length != 2 - || method.Parameters[0].RefKind != RefKind.None - || method.Parameters[0].Type.SpecialType != SpecialType.System_IntPtr - || method.Parameters[1].RefKind != RefKind.None - || method.Parameters[1].Type.SpecialType != SpecialType.System_Int32) + || method.IsGenericMethod + || method.DeclaredAccessibility != Accessibility.Public + || !string.Equals(method.Name, "CEPluginInitialize", StringComparison.Ordinal) + || method.ReturnsByRef + || method.ReturnsByRefReadonly + || method.ReturnType.SpecialType != SpecialType.System_Int32 + || method.Parameters.Length != 2 + || method.Parameters[0].RefKind != RefKind.None + || method.Parameters[0].Type.SpecialType != SpecialType.System_IntPtr + || method.Parameters[1].RefKind != RefKind.None + || method.Parameters[1].Type.SpecialType != SpecialType.System_Int32) { return false; } INamedTypeSymbol containingType = method.ContainingType; return string.Equals(containingType.Name, "CESDK", StringComparison.Ordinal) - && containingType.ContainingType is null - && string.Equals(containingType.ContainingNamespace.ToDisplayString(), "CESDK", - StringComparison.Ordinal); + && containingType.ContainingType is null + && string.Equals(containingType.ContainingNamespace.ToDisplayString(), "CESDK", + StringComparison.Ordinal); } } diff --git a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/packages.lock.json b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/packages.lock.json index e2c319fb..99041e08 100644 --- a/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/packages.lock.json +++ b/analyzers/CheatEngine.SDK.Analyzers.CodeFixes/packages.lock.json @@ -4,9 +4,9 @@ ".NETStandard,Version=v2.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.Analyzers": { "type": "Direct", diff --git a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaBindingAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaBindingAnalyzer.cs index a4e0e6bb..66d90b45 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaBindingAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaBindingAnalyzer.cs @@ -123,7 +123,7 @@ private static void AnalyzeObjectMember(SymbolAnalysisContext context, LuaBindin switch (context.Symbol) { case IMethodSymbol method when symbols.LuaMethodAttribute is not null - && FindAttribute(method, symbols.LuaMethodAttribute) is not null: + && FindAttribute(method, symbols.LuaMethodAttribute) is not null: usesOptional = LuaContractTypes.Is(method.ReturnType, symbols.LuaOptional); foreach (IParameterSymbol parameter in method.Parameters) { @@ -132,7 +132,7 @@ private static void AnalyzeObjectMember(SymbolAnalysisContext context, LuaBindin break; case IPropertySymbol property when symbols.LuaPropertyAttribute is not null - && FindAttribute(property, symbols.LuaPropertyAttribute) is not null: + && FindAttribute(property, symbols.LuaPropertyAttribute) is not null: usesOptional = LuaContractTypes.Is(property.Type, symbols.LuaOptional); break; default: diff --git a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaFunctionDuplicateState.cs b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaFunctionDuplicateState.cs index 5b73fe87..09327583 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaFunctionDuplicateState.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaFunctionDuplicateState.cs @@ -65,7 +65,7 @@ public void Report(CompilationAnalysisContext context) private string LuaNameFor(ConcurrentQueue<(string MethodName, Location Location)> members) { foreach (KeyValuePair<(string ContainingType, string LuaName), - ConcurrentQueue<(string MethodName, Location Location)>> pair in _candidates) + ConcurrentQueue<(string MethodName, Location Location)>> pair in _candidates) { if (ReferenceEquals(pair.Value, members)) { diff --git a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaObjectBindingAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaObjectBindingAnalyzer.cs index 5c94e14c..219c9730 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaObjectBindingAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Generation/LuaObjectBindingAnalyzer.cs @@ -77,7 +77,7 @@ private static void AnalyzeType(SymbolAnalysisContext context, LuaObjectContract { INamedTypeSymbol type = (INamedTypeSymbol) context.Symbol; if (symbols.LuaClassAttribute is not null - && FindAttribute(type, symbols.LuaClassAttribute) is { } luaClassAttribute) + && FindAttribute(type, symbols.LuaClassAttribute) is { } luaClassAttribute) { string problem = LuaClassProblem(type, luaClassAttribute, context.CancellationToken); if (problem.Length > 0) @@ -100,7 +100,7 @@ private static void AnalyzeMethod(SymbolAnalysisContext context, LuaObjectContra { IMethodSymbol method = (IMethodSymbol) context.Symbol; if (symbols.LuaMethodAttribute is not null - && FindAttribute(method, symbols.LuaMethodAttribute) is { } luaMethodAttribute) + && FindAttribute(method, symbols.LuaMethodAttribute) is { } luaMethodAttribute) { string problem = LuaMethodProblem(method, luaMethodAttribute, symbols, context.CancellationToken); if (problem.Length > 0) @@ -114,7 +114,7 @@ private static void AnalyzeProperty(SymbolAnalysisContext context, LuaObjectCont { IPropertySymbol property = (IPropertySymbol) context.Symbol; if (symbols.LuaPropertyAttribute is null - || FindAttribute(property, symbols.LuaPropertyAttribute) is not { } luaPropertyAttribute) + || FindAttribute(property, symbols.LuaPropertyAttribute) is not { } luaPropertyAttribute) { return; } @@ -150,12 +150,12 @@ private static void ReportLuaClassIdentityCollisions(SymbolAnalysisContext conte foreach (ISymbol member in type.GetMembers()) { if (member is IMethodSymbol { MethodKind: MethodKind.UserDefinedOperator } method - && method.Name is "op_Equality" or "op_Inequality") + && method.Name is "op_Equality" or "op_Inequality") { ReportCollision(context, member, "operator " + - (string.Equals(method.Name, "op_Equality", StringComparison.Ordinal) - ? "==" - : "!=")); + (string.Equals(method.Name, "op_Equality", StringComparison.Ordinal) + ? "==" + : "!=")); } } @@ -167,8 +167,8 @@ private static void ReportLuaClassIdentityCollisions(SymbolAnalysisContext conte foreach (IMethodSymbol constructor in type.InstanceConstructors) { if (constructor.Parameters.Length == 1 - && constructor.Parameters[0].RefKind == RefKind.None - && SymbolEqualityComparer.Default.Equals(constructor.Parameters[0].Type, ceObject)) + && constructor.Parameters[0].RefKind == RefKind.None + && SymbolEqualityComparer.Default.Equals(constructor.Parameters[0].Type, ceObject)) { ReportCollision(context, constructor, type.Name + "(CEObject)"); } @@ -203,7 +203,7 @@ private static void ReportLuaFunctionIdentityCollisions(SymbolAnalysisContext co foreach (ISymbol member in type.GetMembers()) { if (member is not IMethodSymbol method - || FindAttribute(method, symbols.LuaFunctionAttribute) is not { } attribute) + || FindAttribute(method, symbols.LuaFunctionAttribute) is not { } attribute) { continue; } @@ -252,7 +252,7 @@ private static void ReportLuaGlobalIdentityCollisions(SymbolAnalysisContext cont foreach (ISymbol member in type.GetMembers()) { if (member is not IMethodSymbol method - || FindAttribute(method, symbols.LuaGlobalAttribute) is not { } attribute) + || FindAttribute(method, symbols.LuaGlobalAttribute) is not { } attribute) { continue; } @@ -434,7 +434,7 @@ private static string LuaMethodParameterProblem(IMethodSymbol method, LuaObjectC { hasOutResult = true; if (!LuaContractTypes.Is(parameter.Type, symbols.LuaOptional) - && !IsScalar(parameter.Type, false, symbols.ReadOnlySpan)) + && !IsScalar(parameter.Type, false, symbols.ReadOnlySpan)) { return "out results must be supported scalar values"; } @@ -464,7 +464,7 @@ private static string LuaMethodParameterProblem(IMethodSymbol method, LuaObjectC // LuaOptional on an object member is CESDK2013 (LuaBindingAnalyzer), not a generic unsupported type. if (!LuaContractTypes.Is(parameter.Type, symbols.LuaOptional) - && !IsScalar(parameter.Type, true, symbols.ReadOnlySpan)) + && !IsScalar(parameter.Type, true, symbols.ReadOnlySpan)) { return "parameters must be supported scalar values"; } @@ -514,7 +514,7 @@ private static string LuaPropertyProblem(IPropertySymbol property, AttributeData } if (!LuaContractTypes.Is(property.Type, symbols.LuaOptional) - && !IsScalar(property.Type, false, symbols.ReadOnlySpan)) + && !IsScalar(property.Type, false, symbols.ReadOnlySpan)) { return "the property type must be a supported scalar value"; } @@ -531,7 +531,7 @@ private static string LuaClassProblemForMember(INamedTypeSymbol containingType, CancellationToken cancellationToken) { if (symbols.LuaClassAttribute is null - || FindAttribute(containingType, symbols.LuaClassAttribute) is not { } luaClassAttribute) + || FindAttribute(containingType, symbols.LuaClassAttribute) is not { } luaClassAttribute) { return "the containing type must carry [LuaClass]"; } @@ -593,7 +593,7 @@ private static bool IsBodylessPartialProperty(IPropertySymbol property, Cancella } if (!hasPartialModifier || declaration.AccessorList is null || - declaration.AccessorList.Accessors.Count == 0) + declaration.AccessorList.Accessors.Count == 0) { return false; } @@ -606,8 +606,8 @@ private static bool IsBodylessPartialProperty(IPropertySymbol property, Cancella foreach (AccessorDeclarationSyntax accessor in declaration.AccessorList.Accessors) { if (accessor.Kind() is not SyntaxKind.GetAccessorDeclaration and not SyntaxKind.SetAccessorDeclaration - || accessor.Body is not null || accessor.ExpressionBody is not null - || !HasSupportedAccessorModifiers(accessor)) + || accessor.Body is not null || accessor.ExpressionBody is not null + || !HasSupportedAccessorModifiers(accessor)) { return false; } @@ -622,7 +622,7 @@ private static bool HasSupportedAccessorModifiers(AccessorDeclarationSyntax acce foreach (SyntaxToken modifier in accessor.Modifiers) { if (modifier.Kind() is not (SyntaxKind.PublicKeyword or SyntaxKind.PrivateKeyword - or SyntaxKind.ProtectedKeyword or SyntaxKind.InternalKeyword)) + or SyntaxKind.ProtectedKeyword or SyntaxKind.InternalKeyword)) { return false; } @@ -634,15 +634,15 @@ private static bool HasSupportedAccessorModifiers(AccessorDeclarationSyntax acce private static bool IsScalar(ITypeSymbol type, bool allowReadOnlySpan, INamedTypeSymbol? readOnlySpan) { if (type.SpecialType is SpecialType.System_Int32 or SpecialType.System_Int64 or SpecialType.System_Single - or SpecialType.System_Double or SpecialType.System_Boolean or SpecialType.System_UIntPtr - or SpecialType.System_String) + or SpecialType.System_Double or SpecialType.System_Boolean or SpecialType.System_UIntPtr + or SpecialType.System_String) { return true; } if (!allowReadOnlySpan || readOnlySpan is null || type is not INamedTypeSymbol { IsGenericType: true } named - || !SymbolEqualityComparer.Default.Equals(named.OriginalDefinition, readOnlySpan) - || named.TypeArguments.Length != 1) + || !SymbolEqualityComparer.Default.Equals(named.OriginalDefinition, readOnlySpan) + || named.TypeArguments.Length != 1) { return false; } @@ -761,8 +761,8 @@ public INamedTypeSymbol? CEObject } = ceObject; public bool HasAnyLuaObjectAnnotation => LuaClassAttribute is not null || LuaMethodAttribute is not null - || LuaPropertyAttribute is not null || - LuaFunctionAttribute is not null - || LuaGlobalAttribute is not null; + || LuaPropertyAttribute is not null || + LuaFunctionAttribute is not null + || LuaGlobalAttribute is not null; } } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Plugin/CheatEnginePluginAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Plugin/CheatEnginePluginAnalyzer.cs index f7e998f0..65242eab 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Plugin/CheatEnginePluginAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Plugin/CheatEnginePluginAnalyzer.cs @@ -86,8 +86,8 @@ private static void OnCompilationStart(CompilationStartAnalysisContext context) // CESDK.CESDK to the author, which CESDK0003 validates at compilation end. bool? entryPointIsGenerated = null; if (context.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue(GenerateEntryPointKey, - out string? raw) - && bool.TryParse(raw, out bool generate)) + out string? raw) + && bool.TryParse(raw, out bool generate)) { entryPointIsGenerated = generate; } @@ -128,7 +128,7 @@ private static void AnalyzeNamedType( // The attribute targets classes only: on anything else the compiler already reports CS0592. if (type.TypeKind != TypeKind.Class || - FindAttribute(type, symbols.PluginAttribute) is not { } attribute) + FindAttribute(type, symbols.PluginAttribute) is not { } attribute) { return; } @@ -215,20 +215,20 @@ private static bool IsManualBootstrap(INamedTypeSymbol type) foreach (ISymbol member in type.GetMembers("CEPluginInitialize")) { if (member is not IMethodSymbol - { - MethodKind: MethodKind.Ordinary, - IsStatic: true, - IsGenericMethod: false, - DeclaredAccessibility: Accessibility.Public, - ReturnsByRef: false, - ReturnsByRefReadonly: false, - ReturnType.SpecialType: SpecialType.System_Int32, - Parameters: - [ - { RefKind: RefKind.None, Type.SpecialType: SpecialType.System_IntPtr }, - { RefKind: RefKind.None, Type.SpecialType: SpecialType.System_Int32 } - ] - }) + { + MethodKind: MethodKind.Ordinary, + IsStatic: true, + IsGenericMethod: false, + DeclaredAccessibility: Accessibility.Public, + ReturnsByRef: false, + ReturnsByRefReadonly: false, + ReturnType.SpecialType: SpecialType.System_Int32, + Parameters: + [ + { RefKind: RefKind.None, Type.SpecialType: SpecialType.System_IntPtr }, + { RefKind: RefKind.None, Type.SpecialType: SpecialType.System_Int32 } + ] + }) { continue; } @@ -265,9 +265,9 @@ private static void AnalyzeNamespaceDeclaration(SyntaxNodeAnalysisContext contex // A nested declaration is under 'CESDK' exactly when its outermost declaration is: one report per outermost one. if (declaration.Parent is not CompilationUnitSyntax - || context.SemanticModel.GetDeclaredSymbol(declaration, context.CancellationToken) is not INamespaceSymbol - declared - || !IsUnderReservedRoot(declared, context.CancellationToken)) + || context.SemanticModel.GetDeclaredSymbol(declaration, context.CancellationToken) is not INamespaceSymbol + declared + || !IsUnderReservedRoot(declared, context.CancellationToken)) { return; } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Plugin/ClassicNativeExportAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Plugin/ClassicNativeExportAnalyzer.cs index bcc69a49..ca0723b6 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Plugin/ClassicNativeExportAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Plugin/ClassicNativeExportAnalyzer.cs @@ -95,14 +95,14 @@ private static void Analyze(Action report, IMethodSymbol method, INa foreach (KeyValuePair argument in attribute.NamedArguments) { if (!string.Equals(argument.Key, EntryPointArgument, StringComparison.Ordinal) || - argument.Value.Value is not string entryPoint || - !entryPoint.StartsWith(ClassicExportPrefix, StringComparison.Ordinal)) + argument.Value.Value is not string entryPoint || + !entryPoint.StartsWith(ClassicExportPrefix, StringComparison.Ordinal)) { continue; } Location location = attribute.ApplicationSyntaxReference?.GetSyntax(cancellationToken).GetLocation() - ?? (method.Locations.IsEmpty ? Location.None : method.Locations[0]); + ?? (method.Locations.IsEmpty ? Location.None : method.Locations[0]); report(Diagnostic.Create(DiagnosticDescriptors.ClassicNativePluginExport, location, method.Name, entryPoint)); } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Plugin/PluginCompilationState.cs b/analyzers/CheatEngine.SDK.Analyzers/Plugin/PluginCompilationState.cs index 146e92da..13260a17 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Plugin/PluginCompilationState.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Plugin/PluginCompilationState.cs @@ -57,7 +57,7 @@ public void Report(CompilationAnalysisContext context) { int pluginClassCount = _pluginClasses.Count; if (pluginClassCount == 0) - // Not a plugin assembly (the SDK's own libraries, a helper library): both rules are about plugins. + // Not a plugin assembly (the SDK's own libraries, a helper library): both rules are about plugins. { return; } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Usage/ExceptionGuard.cs b/analyzers/CheatEngine.SDK.Analyzers/Usage/ExceptionGuard.cs index 97f80cd3..b9db1a10 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Usage/ExceptionGuard.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Usage/ExceptionGuard.cs @@ -113,16 +113,16 @@ private static bool IsGuardTry(ITryOperation tryOperation, INamedTypeSymbol exce } return hasCatchAll - && (tryOperation.Finally is null - || !ContainsThrow(tryOperation.Finally, doesNotReturnAttribute, environmentType)); + && (tryOperation.Finally is null + || !ContainsThrow(tryOperation.Finally, doesNotReturnAttribute, environmentType)); } // 'catch { }' has the exception type System.Object; 'catch (Exception)' names the root of the hierarchy. private static bool IsCatchAll(ICatchClauseOperation catchClause, INamedTypeSymbol exceptionType) { return catchClause.Filter is null - && (catchClause.ExceptionType.SpecialType == SpecialType.System_Object - || SymbolEqualityComparer.Default.Equals(catchClause.ExceptionType, exceptionType)); + && (catchClause.ExceptionType.SpecialType == SpecialType.System_Object + || SymbolEqualityComparer.Default.Equals(catchClause.ExceptionType, exceptionType)); } private static bool ContainsThrow(IOperation block, INamedTypeSymbol? doesNotReturnAttribute, @@ -131,8 +131,8 @@ private static bool ContainsThrow(IOperation block, INamedTypeSymbol? doesNotRet foreach (IOperation descendant in block.Descendants()) { if (descendant.Kind == OperationKind.Throw - || (descendant is IInvocationOperation invocation - && NeverReturnsByThrowing(invocation.TargetMethod, doesNotReturnAttribute, environmentType))) + || (descendant is IInvocationOperation invocation + && NeverReturnsByThrowing(invocation.TargetMethod, doesNotReturnAttribute, environmentType))) { return true; } @@ -148,7 +148,7 @@ private static bool NeverReturnsByThrowing(IMethodSymbol method, INamedTypeSymbo INamedTypeSymbol? environmentType) { if (doesNotReturnAttribute is null - || SymbolEqualityComparer.Default.Equals(method.ContainingType, environmentType)) + || SymbolEqualityComparer.Default.Equals(method.ContainingType, environmentType)) { return false; } @@ -199,7 +199,7 @@ private static bool IsTriviallyNonThrowing(IOperation value) } => true, IConversionOperation conversion => IsNonThrowingConversion(conversion) && - IsTriviallyNonThrowing(conversion.Operand), + IsTriviallyNonThrowing(conversion.Operand), // '-x', '+x', '~x', '!x' outside a checked context. 'dynamic' and 'decimal' operands run code, and so does // the fifth built-in unary operator: '^x' constructs a System.Index, which rejects negative values. @@ -229,7 +229,7 @@ private static bool IsNonThrowingConversion(IConversionOperation operation) { Conversion conversion = operation.GetConversion(); if (!conversion.Exists || conversion.IsUserDefined || conversion.MethodSymbol is not null || - conversion.IsDynamic) + conversion.IsDynamic) { return false; } @@ -246,15 +246,15 @@ private static bool IsNonThrowingConversion(IConversionOperation operation) if (conversion.IsImplicit) { return conversion.IsNumeric - || conversion.IsReference - || conversion.IsPointer - || (conversion.IsNullable && IsNullableWrapping(source, target)); + || conversion.IsReference + || conversion.IsPointer + || (conversion.IsNullable && IsNullableWrapping(source, target)); } return !operation.IsChecked - && (conversion.IsNumeric || conversion.IsEnumeration || conversion.IsPointer) - && IsPrimitiveEnumOrPointer(source) - && IsPrimitiveEnumOrPointer(target); + && (conversion.IsNumeric || conversion.IsEnumeration || conversion.IsPointer) + && IsPrimitiveEnumOrPointer(source) + && IsPrimitiveEnumOrPointer(target); } // 'int -> int?', 'int -> long?', 'int? -> long?', 'Guid -> Guid?'. An implicit nullable conversion can also @@ -265,9 +265,9 @@ private static bool IsNullableWrapping(ITypeSymbol? source, ITypeSymbol? target) ITypeSymbol? from = UnwrapNullable(source); ITypeSymbol? to = UnwrapNullable(target); return from is not null - && to is not null - && (SymbolEqualityComparer.Default.Equals(from, to) || - (IsPrimitiveOrEnum(from) && IsPrimitiveOrEnum(to))); + && to is not null + && (SymbolEqualityComparer.Default.Equals(from, to) || + (IsPrimitiveOrEnum(from) && IsPrimitiveOrEnum(to))); } private static ITypeSymbol? UnwrapNullable(ITypeSymbol? type) @@ -287,12 +287,12 @@ private static bool IsPrimitiveEnumOrPointer(ITypeSymbol? type) private static bool IsPrimitiveOrEnum(ITypeSymbol? type) { return type is { TypeKind: TypeKind.Enum } - || type?.SpecialType is SpecialType.System_Boolean or SpecialType.System_Char - or SpecialType.System_SByte or SpecialType.System_Byte - or SpecialType.System_Int16 or SpecialType.System_UInt16 - or SpecialType.System_Int32 or SpecialType.System_UInt32 - or SpecialType.System_Int64 or SpecialType.System_UInt64 - or SpecialType.System_IntPtr or SpecialType.System_UIntPtr - or SpecialType.System_Single or SpecialType.System_Double; + || type?.SpecialType is SpecialType.System_Boolean or SpecialType.System_Char + or SpecialType.System_SByte or SpecialType.System_Byte + or SpecialType.System_Int16 or SpecialType.System_UInt16 + or SpecialType.System_Int32 or SpecialType.System_UInt32 + or SpecialType.System_Int64 or SpecialType.System_UInt64 + or SpecialType.System_IntPtr or SpecialType.System_UIntPtr + or SpecialType.System_Single or SpecialType.System_Double; } } diff --git a/analyzers/CheatEngine.SDK.Analyzers/Usage/HostWidthPointerSizeAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Usage/HostWidthPointerSizeAnalyzer.cs index 11267a33..f1f3b692 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Usage/HostWidthPointerSizeAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Usage/HostWidthPointerSizeAnalyzer.cs @@ -73,7 +73,7 @@ private static void OnCompilationStart(CompilationStartAnalysisContext context) foreach (MetadataReference reference in compilation.References) { if (compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly - && string.Equals(assembly.Identity.Name, EngineAssemblyName, StringComparison.Ordinal)) + && string.Equals(assembly.Identity.Name, EngineAssemblyName, StringComparison.Ordinal)) { return assembly.GetTypeByMetadataName(PointerSizeMetadataName); } @@ -86,8 +86,8 @@ private static void AnalyzeObjectCreation(OperationAnalysisContext context, Host { IObjectCreationOperation creation = (IObjectCreationOperation) context.Operation; if (creation.Constructor is null - || !SymbolEqualityComparer.Default.Equals(creation.Constructor.ContainingType, symbols.PointerSize) - || creation.Arguments.Length != 1) + || !SymbolEqualityComparer.Default.Equals(creation.Constructor.ContainingType, symbols.PointerSize) + || creation.Arguments.Length != 1) { return; } @@ -106,9 +106,9 @@ private static void AnalyzeConditional(OperationAnalysisContext context, HostWid { IConditionalOperation conditional = (IConditionalOperation) context.Operation; if (conditional.WhenFalse is null - || !SymbolEqualityComparer.Default.Equals(conditional.Type, symbols.PointerSize) - || !IsWidthConstant(conditional.WhenTrue, symbols) - || !IsWidthConstant(conditional.WhenFalse, symbols)) + || !SymbolEqualityComparer.Default.Equals(conditional.Type, symbols.PointerSize) + || !IsWidthConstant(conditional.WhenTrue, symbols) + || !IsWidthConstant(conditional.WhenFalse, symbols)) { return; } @@ -127,8 +127,8 @@ private static void AnalyzeConditional(OperationAnalysisContext context, HostWid private static bool IsWidthConstant(IOperation operation, HostWidthSymbols symbols) { return SkipConversions(operation) is IPropertyReferenceOperation { Instance: null } property - && SymbolEqualityComparer.Default.Equals(property.Property.ContainingType, symbols.PointerSize) - && property.Property.Name is "Bit32" or "Bit64"; + && SymbolEqualityComparer.Default.Equals(property.Property.ContainingType, symbols.PointerSize) + && property.Property.Name is "Bit32" or "Bit64"; } private static IOperation? FindHostWidthSource(IOperation condition, HostWidthSymbols symbols) @@ -156,7 +156,7 @@ private static bool IsHostWidthSource(IOperation operation, HostWidthSymbols sym case IPropertyReferenceOperation { Instance: null } property: // IntPtr.Size and UIntPtr.Size; nint.Size and nuint.Size bind to the same properties. return string.Equals(property.Property.Name, "Size", StringComparison.Ordinal) - && IsNativeWidthType(property.Property.ContainingType); + && IsNativeWidthType(property.Property.ContainingType); case ISizeOfOperation sizeOf: return IsNativeWidthType(sizeOf.TypeOperand) || sizeOf.TypeOperand is IPointerTypeSymbol; case IInvocationOperation invocation: @@ -171,14 +171,14 @@ private static bool IsGenericSizeOf(IInvocationOperation invocation, HostWidthSy { IMethodSymbol method = invocation.TargetMethod; if (!string.Equals(method.Name, "SizeOf", StringComparison.Ordinal) || method.TypeArguments.Length != 1 - || invocation.Arguments.Length != 0) + || invocation.Arguments.Length != 0) { return false; } INamedTypeSymbol declaring = method.ContainingType; bool knownHelper = SymbolEqualityComparer.Default.Equals(declaring, symbols.Unsafe) - || SymbolEqualityComparer.Default.Equals(declaring, symbols.Marshal); + || SymbolEqualityComparer.Default.Equals(declaring, symbols.Marshal); ITypeSymbol argument = method.TypeArguments[0]; return knownHelper && (IsNativeWidthType(argument) || argument is IPointerTypeSymbol); } @@ -186,8 +186,8 @@ private static bool IsGenericSizeOf(IInvocationOperation invocation, HostWidthSy private static bool IsIs64BitProcess(IOperation operation, HostWidthSymbols symbols) { return operation is IPropertyReferenceOperation { Instance: null } property - && string.Equals(property.Property.Name, "Is64BitProcess", StringComparison.Ordinal) - && SymbolEqualityComparer.Default.Equals(property.Property.ContainingType, symbols.Environment); + && string.Equals(property.Property.Name, "Is64BitProcess", StringComparison.Ordinal) + && SymbolEqualityComparer.Default.Equals(property.Property.ContainingType, symbols.Environment); } // System.IntPtr and System.UIntPtr, including their nint and nuint spellings. diff --git a/analyzers/CheatEngine.SDK.Analyzers/Usage/PluginLifecycleAndOwnershipAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Usage/PluginLifecycleAndOwnershipAnalyzer.cs index 2d1dc3d5..6d60546a 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Usage/PluginLifecycleAndOwnershipAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Usage/PluginLifecycleAndOwnershipAnalyzer.cs @@ -77,8 +77,8 @@ private static void AnalyzeInvocation(OperationAnalysisContext context, PluginLi { IInvocationOperation invocation = (IInvocationOperation) context.Operation; if (symbols.RequiresPluginEnabled is not null && IsTooEarly(context.ContainingSymbol, symbols.PluginAttribute) - && RequiresEnabled(invocation.TargetMethod, - symbols.RequiresPluginEnabled)) + && RequiresEnabled(invocation.TargetMethod, + symbols.RequiresPluginEnabled)) { context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.RequiresPluginEnabledTooEarly, invocation.Syntax.GetLocation(), DisplayName(invocation.TargetMethod))); @@ -102,7 +102,7 @@ private static void AnalyzePropertyReference(OperationAnalysisContext context, PluginLifecycleContractSymbols symbols) { if (symbols.RequiresPluginEnabled is null || - !IsTooEarly(context.ContainingSymbol, symbols.PluginAttribute)) + !IsTooEarly(context.ContainingSymbol, symbols.PluginAttribute)) { return; } @@ -120,14 +120,14 @@ private static void AnalyzePropertyReference(OperationAnalysisContext context, private static void AnalyzeObjectCreation(OperationAnalysisContext context, PluginLifecycleContractSymbols symbols) { if (symbols.RequiresPluginEnabled is null || - !IsTooEarly(context.ContainingSymbol, symbols.PluginAttribute)) + !IsTooEarly(context.ContainingSymbol, symbols.PluginAttribute)) { return; } IObjectCreationOperation creation = (IObjectCreationOperation) context.Operation; if (creation.Constructor is null || - !RequiresEnabled(creation.Constructor, symbols.RequiresPluginEnabled)) + !RequiresEnabled(creation.Constructor, symbols.RequiresPluginEnabled)) { return; } @@ -140,7 +140,7 @@ private static void AnalyzeMethod(SymbolAnalysisContext context, PluginLifecycle { IMethodSymbol method = (IMethodSymbol) context.Symbol; if (!method.IsAsync || !method.ReturnsVoid || - !IsPluginClass(method.ContainingType, symbols.PluginAttribute)) + !IsPluginClass(method.ContainingType, symbols.PluginAttribute)) { return; } @@ -183,8 +183,8 @@ private static bool IsLifecycleOverride(IMethodSymbol method, INamedTypeSymbol p } for (IMethodSymbol? overridden = method.OverriddenMethod; - overridden is not null; - overridden = overridden.OverriddenMethod) + overridden is not null; + overridden = overridden.OverriddenMethod) { if (SymbolEqualityComparer.Default.Equals(overridden.ContainingType, pluginBase)) { diff --git a/analyzers/CheatEngine.SDK.Analyzers/Usage/UnmanagedCallersOnlyGuardAnalyzer.cs b/analyzers/CheatEngine.SDK.Analyzers/Usage/UnmanagedCallersOnlyGuardAnalyzer.cs index 1f037769..f7e1589f 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/Usage/UnmanagedCallersOnlyGuardAnalyzer.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/Usage/UnmanagedCallersOnlyGuardAnalyzer.cs @@ -82,7 +82,7 @@ private static void AnalyzeMethodBody(OperationAnalysisContext context, INamedTy { IMethodBodyOperation body = (IMethodBodyOperation) context.Operation; if (context.ContainingSymbol is not IMethodSymbol method || - !IsUnmanagedCallersOnly(method, unmanagedCallersOnly)) + !IsUnmanagedCallersOnly(method, unmanagedCallersOnly)) { return; } diff --git a/analyzers/CheatEngine.SDK.Analyzers/WellKnown/SdkSymbolResolver.cs b/analyzers/CheatEngine.SDK.Analyzers/WellKnown/SdkSymbolResolver.cs index 83b760c2..6c21f93d 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/WellKnown/SdkSymbolResolver.cs +++ b/analyzers/CheatEngine.SDK.Analyzers/WellKnown/SdkSymbolResolver.cs @@ -38,7 +38,7 @@ internal static class SdkSymbolResolver foreach (MetadataReference reference in compilation.References) { if (compilation.GetAssemblyOrModuleSymbol(reference) is not IAssemblySymbol assembly - || !string.Equals(assembly.Identity.Name, assemblyName, StringComparison.Ordinal)) + || !string.Equals(assembly.Identity.Name, assemblyName, StringComparison.Ordinal)) { continue; } diff --git a/analyzers/CheatEngine.SDK.Analyzers/packages.lock.json b/analyzers/CheatEngine.SDK.Analyzers/packages.lock.json index 64d57ef4..50d815cb 100644 --- a/analyzers/CheatEngine.SDK.Analyzers/packages.lock.json +++ b/analyzers/CheatEngine.SDK.Analyzers/packages.lock.json @@ -4,9 +4,9 @@ ".NETStandard,Version=v2.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.Analyzers": { "type": "Direct", diff --git a/libs/CheatEngine.SDK.Abi/Native/BoundedDebugEventObservationBuffer.cs b/libs/CheatEngine.SDK.Abi/Native/BoundedDebugEventObservationBuffer.cs index 73db789e..8f738885 100644 --- a/libs/CheatEngine.SDK.Abi/Native/BoundedDebugEventObservationBuffer.cs +++ b/libs/CheatEngine.SDK.Abi/Native/BoundedDebugEventObservationBuffer.cs @@ -30,7 +30,7 @@ public BoundedDebugEventObservationBuffer(int capacity, DebugEventObservationOve { ArgumentOutOfRangeException.ThrowIfNegativeOrZero(capacity); if (overflowPolicy is not DebugEventObservationOverflowPolicy.DropNewest - and not DebugEventObservationOverflowPolicy.DropOldest) + and not DebugEventObservationOverflowPolicy.DropOldest) { throw new ArgumentOutOfRangeException(nameof(overflowPolicy)); } diff --git a/libs/CheatEngine.SDK.Abi/Native/ClassicDebugEventDispatcher.cs b/libs/CheatEngine.SDK.Abi/Native/ClassicDebugEventDispatcher.cs index 58b0e44d..2cb6520d 100644 --- a/libs/CheatEngine.SDK.Abi/Native/ClassicDebugEventDispatcher.cs +++ b/libs/CheatEngine.SDK.Abi/Native/ClassicDebugEventDispatcher.cs @@ -207,9 +207,9 @@ private static int Dispatch(void* nativeEvent) } if (!TryEnterActiveCallback( - out ClassicDebugEventDispatcher? dispatcher, - out DebugEventDecisionHandler handler, - out BoundedDebugEventObservationBuffer? observations)) + out ClassicDebugEventDispatcher? dispatcher, + out DebugEventDecisionHandler handler, + out BoundedDebugEventObservationBuffer? observations)) { return 0; } diff --git a/libs/CheatEngine.SDK.Abi/packages.lock.json b/libs/CheatEngine.SDK.Abi/packages.lock.json index 75a512c2..cc7bf705 100644 --- a/libs/CheatEngine.SDK.Abi/packages.lock.json +++ b/libs/CheatEngine.SDK.Abi/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.BannedApiAnalyzers": { "type": "Direct", diff --git a/libs/CheatEngine.SDK.Annotations/packages.lock.json b/libs/CheatEngine.SDK.Annotations/packages.lock.json index 75a512c2..cc7bf705 100644 --- a/libs/CheatEngine.SDK.Annotations/packages.lock.json +++ b/libs/CheatEngine.SDK.Annotations/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.BannedApiAnalyzers": { "type": "Direct", diff --git a/libs/CheatEngine.SDK.Engine/AddressList/AddressListCalls.cs b/libs/CheatEngine.SDK.Engine/AddressList/AddressListCalls.cs index ca6eaa62..30036470 100644 --- a/libs/CheatEngine.SDK.Engine/AddressList/AddressListCalls.cs +++ b/libs/CheatEngine.SDK.Engine/AddressList/AddressListCalls.cs @@ -32,7 +32,7 @@ public static bool TryGetGlobal(LuaRef cache, ReadOnlySpan try { if (!LuaGlobalFunctions.TryPush(state, cache, global) || !state.TryCall(0, 1).IsOk || - !TMarshaller.TryRead(state, -1, out result)) + !TMarshaller.TryRead(state, -1, out result)) { return LuaCallSupport.Fail(state, top, out result); } diff --git a/libs/CheatEngine.SDK.Engine/AddressList/AddressListMutations.cs b/libs/CheatEngine.SDK.Engine/AddressList/AddressListMutations.cs index b0a697bd..721ed89a 100644 --- a/libs/CheatEngine.SDK.Engine/AddressList/AddressListMutations.cs +++ b/libs/CheatEngine.SDK.Engine/AddressList/AddressListMutations.cs @@ -438,7 +438,7 @@ private static MemoryRecordMutationOutcome ValidateParentChain(LuaState state, M { HashSet seen = new(); MemoryRecord current = proposedParent; - for (int hops = 0;; hops++) + for (int hops = 0; ; hops++) { LuaStatus status = current.Handle.TryGetProperty(state, "ID"u8); if (!status.IsOk) diff --git a/libs/CheatEngine.SDK.Engine/Allocation/AllocatedRegion.cs b/libs/CheatEngine.SDK.Engine/Allocation/AllocatedRegion.cs index 10e168c9..2184a939 100644 --- a/libs/CheatEngine.SDK.Engine/Allocation/AllocatedRegion.cs +++ b/libs/CheatEngine.SDK.Engine/Allocation/AllocatedRegion.cs @@ -291,7 +291,7 @@ private TargetMemoryOperationOutcome ReleaseTakenWithOutcome() return outcome; } catch (InvalidOperationException) when (!LuaRuntime.IsAttached || - !EngineResourceOrigin.IsCurrent(Origin.Runtime)) + !EngineResourceOrigin.IsCurrent(Origin.Runtime)) { // The binding could not acquire a Lua operation: deAlloc never ran. _lastReleaseOutcome = TargetReleaseOutcome.NotInvoked(EngineFailureKind.BindingFailure); @@ -313,7 +313,7 @@ private TargetMemoryOperationOutcome ReleaseTakenWithOutcome() private void ThrowForReleaseOutcome(TargetMemoryOperationOutcome outcome) { if (outcome.Kind is TargetMemoryOperationOutcomeKind.TargetIdentityUnavailable or - TargetMemoryOperationOutcomeKind.TargetIdentityMismatch) + TargetMemoryOperationOutcomeKind.TargetIdentityMismatch) { throw new EngineTargetIdentityException("TargetMemoryDeallocate", LastReleaseOutcome.TargetCheck.GetValueOrDefault()); diff --git a/libs/CheatEngine.SDK.Engine/Allocation/TargetMemoryAllocator.cs b/libs/CheatEngine.SDK.Engine/Allocation/TargetMemoryAllocator.cs index cfd4413b..6413a29e 100644 --- a/libs/CheatEngine.SDK.Engine/Allocation/TargetMemoryAllocator.cs +++ b/libs/CheatEngine.SDK.Engine/Allocation/TargetMemoryAllocator.cs @@ -403,7 +403,7 @@ private static void ThrowForAllocationOutcome(TargetMemoryOperationOutcome outco } if (outcome.Kind is TargetMemoryOperationOutcomeKind.TargetIdentityUnavailable or - TargetMemoryOperationOutcomeKind.TargetIdentityMismatch) + TargetMemoryOperationOutcomeKind.TargetIdentityMismatch) { throw new EngineTargetIdentityException(AllocateOperation, GetUnavailableTargetCheck()); } diff --git a/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerPatcher.cs b/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerPatcher.cs index 9ae4c9ab..386981e4 100644 --- a/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerPatcher.cs +++ b/libs/CheatEngine.SDK.Engine/Assembly/AutoAssemblerPatcher.cs @@ -360,7 +360,7 @@ internal static AutoAssemblerApplyOutcome ApplyCore(string script, AutoAssembler { snapshot = AutoAssemblerDisableInfoSnapshot.Read(state, detail, options); patch = patchFactory(script, disableInfo, origin, snapshot, postCheck) ?? - throw new InvalidOperationException("The Auto Assembler patch factory returned no patch."); + throw new InvalidOperationException("The Auto Assembler patch factory returned no patch."); } catch (Exception exception) { diff --git a/libs/CheatEngine.SDK.Engine/Assembly/InstructionDisassembler.cs b/libs/CheatEngine.SDK.Engine/Assembly/InstructionDisassembler.cs index e3588c99..d889fb9e 100644 --- a/libs/CheatEngine.SDK.Engine/Assembly/InstructionDisassembler.cs +++ b/libs/CheatEngine.SDK.Engine/Assembly/InstructionDisassembler.cs @@ -120,9 +120,9 @@ public static InstructionOperationStatus TryDisassemble(InstructionTargetProfile } if (!state.TryReadUtf8(-4, out ReadOnlySpan addressUtf8) || - !state.TryReadUtf8(-3, out ReadOnlySpan bytesUtf8) || - !state.TryReadUtf8(-2, out ReadOnlySpan opcodeUtf8) || - !state.TryReadUtf8(-1, out ReadOnlySpan extraUtf8)) + !state.TryReadUtf8(-3, out ReadOnlySpan bytesUtf8) || + !state.TryReadUtf8(-2, out ReadOnlySpan opcodeUtf8) || + !state.TryReadUtf8(-1, out ReadOnlySpan extraUtf8)) { return InstructionOperationStatus.InvalidResult; } diff --git a/libs/CheatEngine.SDK.Engine/Assembly/InstructionProfiles.cs b/libs/CheatEngine.SDK.Engine/Assembly/InstructionProfiles.cs index 6ae45ddf..8f263bf4 100644 --- a/libs/CheatEngine.SDK.Engine/Assembly/InstructionProfiles.cs +++ b/libs/CheatEngine.SDK.Engine/Assembly/InstructionProfiles.cs @@ -64,8 +64,8 @@ public static InstructionOperationStatus TryObserveCurrent(out InstructionTarget } if (!RuntimeInfo.TryDeriveTargetArchitecture(probe.IsX86Family.GetValueOrDefault(), - probe.IsArmFamily.GetValueOrDefault(), probe.Is64Bit.GetValueOrDefault(), - out CheatEngineArchitecture architecture)) + probe.IsArmFamily.GetValueOrDefault(), probe.Is64Bit.GetValueOrDefault(), + out CheatEngineArchitecture architecture)) { return InstructionOperationStatus.InvalidProfile; } diff --git a/libs/CheatEngine.SDK.Engine/Enums/CEEnumNames.cs b/libs/CheatEngine.SDK.Engine/Enums/CEEnumNames.cs index b793f0af..b130deb9 100644 --- a/libs/CheatEngine.SDK.Engine/Enums/CEEnumNames.cs +++ b/libs/CheatEngine.SDK.Engine/Enums/CEEnumNames.cs @@ -312,8 +312,8 @@ public static ReadOnlySpan ToCEName(this MemoryProtection value) public static bool TryParseCEName(ReadOnlySpan ceName, out MemoryProtection value) { for (MemoryProtection candidate = MemoryProtection.ReadOnly; - candidate <= MemoryProtection.ExecuteWriteCopy; - candidate = (MemoryProtection) ((uint) candidate << 1)) + candidate <= MemoryProtection.ExecuteWriteCopy; + candidate = (MemoryProtection) ((uint) candidate << 1)) { if (ceName.SequenceEqual(candidate.ToCEName())) { diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineGlobalUnavailableException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineGlobalUnavailableException.cs index f504b52b..0493514c 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineGlobalUnavailableException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineGlobalUnavailableException.cs @@ -49,6 +49,6 @@ public string Operation private static string CreateDefaultMessage(string operation) { return "The required binding global for Cheat Engine operation '" + - RequireText(operation, nameof(operation)) + "' is unavailable."; + RequireText(operation, nameof(operation)) + "' is unavailable."; } } diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineLuaException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineLuaException.cs index 77bb10a3..0ff4c182 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineLuaException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineLuaException.cs @@ -75,6 +75,6 @@ private static string CreateDefaultMessage(string operation, LuaStatus status) } return "The protected Lua operation '" + RequireText(operation, nameof(operation)) + "' failed with status " + - status + "."; + status + "."; } } diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs index a8fb204b..41a9fb49 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineMarshallingException.cs @@ -87,8 +87,8 @@ private static string CreateDefaultMessage(string operation, EngineMarshallingDi string directionText = ValidateDirection(direction) == EngineMarshallingDirection.Argument ? "argument" : "result"; return "The " + directionText + " of Cheat Engine operation '" + - RequireText(operation, nameof(operation)) + "' could not be marshalled: expected " + - RequireText(expected, nameof(expected)) + ", observed " + RequireText(actual, nameof(actual)) + "."; + RequireText(operation, nameof(operation)) + "' could not be marshalled: expected " + + RequireText(expected, nameof(expected)) + ", observed " + RequireText(actual, nameof(actual)) + "."; } private static EngineMarshallingDirection ValidateDirection(EngineMarshallingDirection direction) diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineResourceHandoffException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineResourceHandoffException.cs index a95af947..f29f792e 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineResourceHandoffException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineResourceHandoffException.cs @@ -48,7 +48,7 @@ public TargetReleaseOutcome CleanupOutcome private static string CreateMessage(string operation, TargetReleaseOutcome cleanupOutcome) { return "The Engine operation '" + RequireText(operation, nameof(operation)) + - "' completed before its ownership could be published; compensation ended as " + - cleanupOutcome.Status + "."; + "' completed before its ownership could be published; compensation ended as " + + cleanupOutcome.Status + "."; } } diff --git a/libs/CheatEngine.SDK.Engine/Errors/EngineTargetIdentityException.cs b/libs/CheatEngine.SDK.Engine/Errors/EngineTargetIdentityException.cs index 40e0063f..0791a540 100644 --- a/libs/CheatEngine.SDK.Engine/Errors/EngineTargetIdentityException.cs +++ b/libs/CheatEngine.SDK.Engine/Errors/EngineTargetIdentityException.cs @@ -36,6 +36,6 @@ public TargetIdentityCheck Check private static string CreateMessage(string operation, TargetIdentityCheck check) { return "The Engine operation '" + RequireText(operation, nameof(operation)) + - "' was refused because its original target is not verified as current (" + check.Kind + ")."; + "' was refused because its original target is not verified as current (" + check.Kind + ")."; } } diff --git a/libs/CheatEngine.SDK.Engine/Inspection/EngineInspection.cs b/libs/CheatEngine.SDK.Engine/Inspection/EngineInspection.cs index e081e23c..73b5aedf 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/EngineInspection.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/EngineInspection.cs @@ -512,7 +512,7 @@ private static InspectionStatus ReadModuleCollection(LuaState state, int tableIn for (int index = 0; index < sequenceCount; index++) { if (state.RawGetSequenceItem(tableIndex, index) != LuaType.Table || - !TryReadModuleInfo(state, -1, out snapshot[index])) + !TryReadModuleInfo(state, -1, out snapshot[index])) { return InspectionStatus.InvalidResult; } @@ -554,7 +554,7 @@ private static InspectionStatus ReadSectionCollection(LuaState state, int tableI for (int index = 0; index < sequenceCount; index++) { if (state.RawGetSequenceItem(tableIndex, index) != LuaType.Table || - !TryReadModuleSectionInfo(state, -1, out snapshot[index])) + !TryReadModuleSectionInfo(state, -1, out snapshot[index])) { return InspectionStatus.InvalidResult; } @@ -596,7 +596,7 @@ private static InspectionStatus ReadMemoryRegionCollection(LuaState state, int t for (int index = 0; index < sequenceCount; index++) { if (state.RawGetSequenceItem(tableIndex, index) != LuaType.Table || - !TryReadMemoryRegionInfo(state, -1, out snapshot[index])) + !TryReadMemoryRegionInfo(state, -1, out snapshot[index])) { return InspectionStatus.InvalidResult; } @@ -627,10 +627,10 @@ private static bool TryReadModuleInfo(LuaState state, int tableIndex, out Module { module = default; if (!TryReadRequiredStringField(state, tableIndex, "Name"u8, out string? name) || - !TryReadAddressField(state, tableIndex, "Address"u8, out Address address) || - !TryReadOptionalMemorySizeField(state, tableIndex, "Size"u8, out MemorySize? size) || - !TryReadBooleanField(state, tableIndex, "Is64Bit"u8, out bool is64Bit) || - !TryReadRequiredStringField(state, tableIndex, "PathToFile"u8, out string? pathToFile)) + !TryReadAddressField(state, tableIndex, "Address"u8, out Address address) || + !TryReadOptionalMemorySizeField(state, tableIndex, "Size"u8, out MemorySize? size) || + !TryReadBooleanField(state, tableIndex, "Is64Bit"u8, out bool is64Bit) || + !TryReadRequiredStringField(state, tableIndex, "PathToFile"u8, out string? pathToFile)) { return false; } @@ -643,9 +643,9 @@ private static bool TryReadModuleSectionInfo(LuaState state, int tableIndex, out { section = default; if (!TryReadRequiredStringField(state, tableIndex, "Name"u8, out string? name) || - !TryReadMemorySizeField(state, tableIndex, "Size"u8, out MemorySize size) || - !TryReadAddressField(state, tableIndex, "Address"u8, out Address address) || - !TryReadUInt64Field(state, tableIndex, "FileAddress"u8, out ulong fileAddress)) + !TryReadMemorySizeField(state, tableIndex, "Size"u8, out MemorySize size) || + !TryReadAddressField(state, tableIndex, "Address"u8, out Address address) || + !TryReadUInt64Field(state, tableIndex, "FileAddress"u8, out ulong fileAddress)) { return false; } @@ -658,9 +658,9 @@ private static bool TryReadSymbolInfo(LuaState state, int tableIndex, out Symbol { symbol = default; if (!TryReadRequiredStringField(state, tableIndex, "modulename"u8, out string? moduleName) || - !TryReadRequiredStringField(state, tableIndex, "searchkey"u8, out string? searchKey) || - !TryReadAddressField(state, tableIndex, "address"u8, out Address address) || - !TryReadMemorySizeField(state, tableIndex, "symbolsize"u8, out MemorySize size)) + !TryReadRequiredStringField(state, tableIndex, "searchkey"u8, out string? searchKey) || + !TryReadAddressField(state, tableIndex, "address"u8, out Address address) || + !TryReadMemorySizeField(state, tableIndex, "symbolsize"u8, out MemorySize size)) { return false; } @@ -673,14 +673,14 @@ private static bool TryReadMemoryRegionInfo(LuaState state, int tableIndex, out { region = default; if (!TryReadAddressField(state, tableIndex, "BaseAddress"u8, out Address baseAddress) || - !TryReadAddressField(state, tableIndex, "AllocationBase"u8, out Address allocationBase) || - !TryReadProtectionField(state, tableIndex, "AllocationProtect"u8, - out MemoryProtection allocationProtection) || - !TryReadMemorySizeField(state, tableIndex, "RegionSize"u8, out MemorySize size) || - !TryReadUInt32Field(state, tableIndex, "State"u8, out uint stateValue) || - !TryReadProtectionField(state, tableIndex, "Protect"u8, out MemoryProtection protection) || - !TryReadUInt32Field(state, tableIndex, "Type"u8, out uint typeValue) || - !TryReadOptionalStringField(state, tableIndex, "Extra"u8, out string? extra)) + !TryReadAddressField(state, tableIndex, "AllocationBase"u8, out Address allocationBase) || + !TryReadProtectionField(state, tableIndex, "AllocationProtect"u8, + out MemoryProtection allocationProtection) || + !TryReadMemorySizeField(state, tableIndex, "RegionSize"u8, out MemorySize size) || + !TryReadUInt32Field(state, tableIndex, "State"u8, out uint stateValue) || + !TryReadProtectionField(state, tableIndex, "Protect"u8, out MemoryProtection protection) || + !TryReadUInt32Field(state, tableIndex, "Type"u8, out uint typeValue) || + !TryReadOptionalStringField(state, tableIndex, "Extra"u8, out string? extra)) { return false; } diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolLists.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolLists.cs index c29a3694..3005c25c 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolLists.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolLists.cs @@ -158,8 +158,8 @@ internal static LuaOperationStatus TryRegisterCore(Owned list, out S try { lease = leaseFactory(transferred, true) ?? - throw new InvalidOperationException( - "The symbol-list registration lease factory returned no lease."); + throw new InvalidOperationException( + "The symbol-list registration lease factory returned no lease."); } catch (Exception exception) { diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistry.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistry.cs index 28fa5fbc..7375e67c 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistry.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolRegistry.cs @@ -206,7 +206,7 @@ internal static SymbolRegistrationReleaseOutcome ReleaseOwned(SymbolRegistration } if (!SOwnedRegistrations.TryGetValue(lease.Name, out SymbolRegistrationLease? current) || - !ReferenceEquals(current, lease)) + !ReferenceEquals(current, lease)) { lease.MarkTerminalAndObserve(SymbolRegistrationReleaseKind.Superseded); return new SymbolRegistrationReleaseOutcome(SymbolRegistrationReleaseKind.Superseded, NoBindingCall); @@ -238,7 +238,7 @@ private static SymbolRegistrationReleaseOutcome ReleaseCurrentLease(SymbolRegist status = UnregisterCore(lease.Name); } catch (InvalidOperationException) when (!LuaRuntime.IsAttached || - lease.Identity != LuaRuntime.CurrentStateIdentity) + lease.Identity != LuaRuntime.CurrentStateIdentity) { return MarkStaleRuntime(lease, NoBindingCall); } @@ -367,7 +367,7 @@ private static SymbolRegistrationReleaseOutcome CompensateFailedPublication(Symb status = UnregisterCore(name); } catch (InvalidOperationException) when (!LuaRuntime.IsAttached || - identity != LuaRuntime.CurrentStateIdentity) + identity != LuaRuntime.CurrentStateIdentity) { return new SymbolRegistrationReleaseOutcome(SymbolRegistrationReleaseKind.StaleRuntime, NoBindingCall); } @@ -407,7 +407,7 @@ private static void SupersedeCurrentLease(SymbolName name) private static void RemoveCurrentLease(SymbolRegistrationLease lease) { if (SOwnedRegistrations.TryGetValue(lease.Name, out SymbolRegistrationLease? current) && - ReferenceEquals(current, lease)) + ReferenceEquals(current, lease)) { SOwnedRegistrations.Remove(lease.Name); } diff --git a/libs/CheatEngine.SDK.Engine/Inspection/SymbolTableReader.cs b/libs/CheatEngine.SDK.Engine/Inspection/SymbolTableReader.cs index 53cdda0f..e5f03cd5 100644 --- a/libs/CheatEngine.SDK.Engine/Inspection/SymbolTableReader.cs +++ b/libs/CheatEngine.SDK.Engine/Inspection/SymbolTableReader.cs @@ -27,7 +27,7 @@ internal static bool TryRead(LuaState state, int index, out SymbolInfo symbol) using LuaFrame frame = new(state); if (!TryReadString(state, table, "modulename"u8, out string? moduleName) || - !TryReadString(state, table, "searchkey"u8, out string? searchKey)) + !TryReadString(state, table, "searchkey"u8, out string? searchKey)) { return false; } diff --git a/libs/CheatEngine.SDK.Engine/Memory/HostMemory.cs b/libs/CheatEngine.SDK.Engine/Memory/HostMemory.cs index e1bbb821..7a499299 100644 --- a/libs/CheatEngine.SDK.Engine/Memory/HostMemory.cs +++ b/libs/CheatEngine.SDK.Engine/Memory/HostMemory.cs @@ -83,8 +83,8 @@ public static bool TryReadInt8(HostAddress address, out sbyte value, out MemoryA public static bool TryReadUInt16(HostAddress address, out ushort value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadSmallInteger, "readSmallIntegerLocal"u8, address.ToInt64(), false, - true, - out long raw, out failure) || raw < 0 || raw > ushort.MaxValue) + true, + out long raw, out failure) || raw < 0 || raw > ushort.MaxValue) { value = default; if (failure == MemoryAccessFailure.None) @@ -103,8 +103,8 @@ public static bool TryReadUInt16(HostAddress address, out ushort value, out Memo public static bool TryReadInt16(HostAddress address, out short value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadSmallInteger, "readSmallIntegerLocal"u8, address.ToInt64(), true, - true, - out long raw, out failure) || raw < short.MinValue || raw > short.MaxValue) + true, + out long raw, out failure) || raw < short.MinValue || raw > short.MaxValue) { value = default; if (failure == MemoryAccessFailure.None) @@ -123,8 +123,8 @@ public static bool TryReadInt16(HostAddress address, out short value, out Memory public static bool TryReadUInt32(HostAddress address, out uint value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadInteger, "readIntegerLocal"u8, address.ToInt64(), false, - true, out long raw, - out failure) || raw < 0 || (ulong) raw > uint.MaxValue) + true, out long raw, + out failure) || raw < 0 || (ulong) raw > uint.MaxValue) { value = default; if (failure == MemoryAccessFailure.None) @@ -143,8 +143,8 @@ public static bool TryReadUInt32(HostAddress address, out uint value, out Memory public static bool TryReadInt32(HostAddress address, out int value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadInteger, "readIntegerLocal"u8, address.ToInt64(), true, - true, out long raw, - out failure) || raw < int.MinValue || raw > int.MaxValue) + true, out long raw, + out failure) || raw < int.MinValue || raw > int.MaxValue) { value = default; if (failure == MemoryAccessFailure.None) @@ -163,8 +163,8 @@ public static bool TryReadInt32(HostAddress address, out int value, out MemoryAc public static bool TryReadUInt64(HostAddress address, out ulong value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadQword, "readQwordLocal"u8, address.ToInt64(), false, - false, out long raw, - out failure)) + false, out long raw, + out failure)) { value = default; return false; @@ -186,8 +186,8 @@ public static bool TryReadInt64(HostAddress address, out long value, out MemoryA public static bool TryReadPointer(HostAddress address, out HostAddress value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadPointer, "readPointerLocal"u8, address.ToInt64(), false, - false, out long raw, - out failure)) + false, out long raw, + out failure)) { value = default; return false; diff --git a/libs/CheatEngine.SDK.Engine/Memory/MemoryLua.cs b/libs/CheatEngine.SDK.Engine/Memory/MemoryLua.cs index 6ac46977..342fe523 100644 --- a/libs/CheatEngine.SDK.Engine/Memory/MemoryLua.cs +++ b/libs/CheatEngine.SDK.Engine/Memory/MemoryLua.cs @@ -288,7 +288,7 @@ private static bool TryCopyCompleteBytes(LuaState state, int table, Span d { LuaType type = state.RawGetIndex(table, index + 1L); bool valid = type == LuaType.Number && state.TryReadInteger(-1, out long value) - && (ulong) value <= byte.MaxValue; + && (ulong) value <= byte.MaxValue; state.Pop(1); if (!valid) { @@ -319,7 +319,7 @@ private static bool TryCopyPartialBytes(LuaState state, int table, Span de LuaType type = state.RawGetIndex(table, index + 1L); long value = default; bool valid = type == LuaType.Number && state.TryReadInteger(-1, out value) - && (ulong) value <= byte.MaxValue; + && (ulong) value <= byte.MaxValue; state.Pop(1); if (!valid) { diff --git a/libs/CheatEngine.SDK.Engine/Memory/TargetMemory.cs b/libs/CheatEngine.SDK.Engine/Memory/TargetMemory.cs index 28021e82..35cccc18 100644 --- a/libs/CheatEngine.SDK.Engine/Memory/TargetMemory.cs +++ b/libs/CheatEngine.SDK.Engine/Memory/TargetMemory.cs @@ -69,8 +69,8 @@ public static class TargetMemory public static bool TryReadUInt8(Address address, out byte value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadByte, "readByte"u8, address.ToInt64(), false, - false, out long raw, - out failure)) + false, out long raw, + out failure)) { value = default; return false; @@ -96,9 +96,9 @@ public static bool TryReadInt8(Address address, out sbyte value, out MemoryAcces public static bool TryReadUInt16(Address address, out ushort value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadSmallInteger, "readSmallInteger"u8, address.ToInt64(), false, - true, - out long raw, - out failure)) + true, + out long raw, + out failure)) { value = default; return false; @@ -111,9 +111,9 @@ public static bool TryReadUInt16(Address address, out ushort value, out MemoryAc public static bool TryReadInt16(Address address, out short value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadSmallInteger, "readSmallInteger"u8, address.ToInt64(), true, - true, - out long raw, - out failure)) + true, + out long raw, + out failure)) { value = default; return false; @@ -126,8 +126,8 @@ public static bool TryReadInt16(Address address, out short value, out MemoryAcce public static bool TryReadUInt32(Address address, out uint value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadInteger, "readInteger"u8, address.ToInt64(), false, - true, out long raw, - out failure)) + true, out long raw, + out failure)) { value = default; return false; @@ -140,8 +140,8 @@ public static bool TryReadUInt32(Address address, out uint value, out MemoryAcce public static bool TryReadInt32(Address address, out int value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadInteger, "readInteger"u8, address.ToInt64(), true, - true, out long raw, - out failure)) + true, out long raw, + out failure)) { value = default; return false; @@ -154,8 +154,8 @@ public static bool TryReadInt32(Address address, out int value, out MemoryAccess public static bool TryReadUInt64(Address address, out ulong value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadQword, "readQword"u8, address.ToInt64(), false, - false, out long raw, - out failure)) + false, out long raw, + out failure)) { value = default; return false; @@ -176,8 +176,8 @@ public static bool TryReadInt64(Address address, out long value, out MemoryAcces public static bool TryReadPointer(Address address, out Address value, out MemoryAccessFailure failure) { if (!MemoryLua.TryReadInteger(SReadPointer, "readPointer"u8, address.ToInt64(), false, - false, out long raw, - out failure)) + false, out long raw, + out failure)) { value = default; return false; diff --git a/libs/CheatEngine.SDK.Engine/Objects/EngineResourceOrigin.cs b/libs/CheatEngine.SDK.Engine/Objects/EngineResourceOrigin.cs index 1f91d5bf..6a69030a 100644 --- a/libs/CheatEngine.SDK.Engine/Objects/EngineResourceOrigin.cs +++ b/libs/CheatEngine.SDK.Engine/Objects/EngineResourceOrigin.cs @@ -64,7 +64,7 @@ public TargetProcessIncarnation? Target /// origin is never current. /// public bool IsCurrentRuntime => Runtime.AttachEpoch != 0 && LuaRuntime.IsAttached && - Runtime == LuaRuntime.CurrentStateIdentity; + Runtime == LuaRuntime.CurrentStateIdentity; /// Captures the current runtime identity, without a target component. internal static EngineResourceOrigin CaptureRuntime() diff --git a/libs/CheatEngine.SDK.Engine/Objects/StringLists.cs b/libs/CheatEngine.SDK.Engine/Objects/StringLists.cs index 1ea7939a..13a2823a 100644 --- a/libs/CheatEngine.SDK.Engine/Objects/StringLists.cs +++ b/libs/CheatEngine.SDK.Engine/Objects/StringLists.cs @@ -31,8 +31,8 @@ public static bool TryCreate([NotNullWhen(true)] out Owned? list) LuaState state = operation.State; using LuaFrame frame = new(state); if (!LuaGlobalFunctions.TryPush(state, SCreateStringList, "createStringlist"u8) || - !state.TryCall(0, 1).IsOk || - !CEObject.TryRead(state, -1, out CEObject handle)) + !state.TryCall(0, 1).IsOk || + !CEObject.TryRead(state, -1, out CEObject handle)) { list = null; return false; diff --git a/libs/CheatEngine.SDK.Engine/Processes/RuntimeHostOperations.cs b/libs/CheatEngine.SDK.Engine/Processes/RuntimeHostOperations.cs index c5fa140f..24bc780e 100644 --- a/libs/CheatEngine.SDK.Engine/Processes/RuntimeHostOperations.cs +++ b/libs/CheatEngine.SDK.Engine/Processes/RuntimeHostOperations.cs @@ -361,7 +361,7 @@ private static LuaOperationStatus TryReadFileVersion(LuaState state, out CheatEn } if (!state.IsInteger(packedIndex) || !state.TryReadInteger(packedIndex, out long packed) || - !RuntimeInfo.TryDecodeFileVersion(packed, out CheatEngineVersion decoded)) + !RuntimeInfo.TryDecodeFileVersion(packed, out CheatEngineVersion decoded)) { return LuaOperationStatus.InvalidResult; } @@ -465,7 +465,7 @@ private static LuaOperationStatus TryGetCheatEngineVersion(LuaState state, out d } if (state.TypeOf(-1) != LuaType.Number || !state.TryReadNumber(-1, out version) || - !double.IsFinite(version) || version < 0) + !double.IsFinite(version) || version < 0) { version = default; return state.IsNil(-1) ? LuaOperationStatus.NilResult : LuaOperationStatus.InvalidResult; diff --git a/libs/CheatEngine.SDK.Engine/Processes/RuntimeObservations.cs b/libs/CheatEngine.SDK.Engine/Processes/RuntimeObservations.cs index 345ecf99..28f684e3 100644 --- a/libs/CheatEngine.SDK.Engine/Processes/RuntimeObservations.cs +++ b/libs/CheatEngine.SDK.Engine/Processes/RuntimeObservations.cs @@ -38,7 +38,10 @@ public static class RuntimeObservations RuntimeOwnership.None, RuntimeReturnSemantics.Value); private static readonly RuntimeCapabilityContract SHostOptionalValue = - SHostValue with { ReturnSemantics = RuntimeReturnSemantics.OptionalValue }; + SHostValue with + { + ReturnSemantics = RuntimeReturnSemantics.OptionalValue + }; private static readonly RuntimeCapabilityContract STargetValue = new(CheatEngineVersion.Ce77010621, RuntimeArchitectureScope.Target, RuntimeArchitectureRequirement.Unknown, RuntimeThreadRequirement.Unknown, diff --git a/libs/CheatEngine.SDK.Engine/Processes/RuntimeProcessOperations.cs b/libs/CheatEngine.SDK.Engine/Processes/RuntimeProcessOperations.cs index e839de47..f0e5cf2d 100644 --- a/libs/CheatEngine.SDK.Engine/Processes/RuntimeProcessOperations.cs +++ b/libs/CheatEngine.SDK.Engine/Processes/RuntimeProcessOperations.cs @@ -83,7 +83,7 @@ public static ProcessOperationStatus SelectAndObserve(TargetProcessId processId, status = TryGetOpenedProcessId(state, out TargetProcessId? observedProcessId); if (status.Kind == ProcessOperationStatusKind.TargetNotAttached || - (status.IsSuccess && observedProcessId != processId)) + (status.IsSuccess && observedProcessId != processId)) { observation = default; return ProcessOperationStatus.SelectionNotConfirmed; diff --git a/libs/CheatEngine.SDK.Engine/Processes/TargetArchitectureProbe.cs b/libs/CheatEngine.SDK.Engine/Processes/TargetArchitectureProbe.cs index 8d8a2b61..1eaa7d1a 100644 --- a/libs/CheatEngine.SDK.Engine/Processes/TargetArchitectureProbe.cs +++ b/libs/CheatEngine.SDK.Engine/Processes/TargetArchitectureProbe.cs @@ -263,7 +263,7 @@ private static TargetProbeStatus ReadFact(LuaState state, TargetProbeFacts read, // CE pushes these with lua_pushinteger. A float, even an integral one, and a value outside int are // refused rather than rounded or truncated. if (!state.IsInteger(-1) || !state.TryReadInteger(-1, out long raw) || - raw is < int.MinValue or > int.MaxValue) + raw is < int.MinValue or > int.MaxValue) { return TargetProbeStatus.InvalidResult; } @@ -325,7 +325,7 @@ internal void RecordProcessIdRead(TargetProbeStatus status) Absent |= TargetProbeFacts.SelectedProcess; } else if (status is TargetProbeStatus.Success or TargetProbeStatus.NoTargetSelected - or TargetProbeStatus.FileAsProcess) + or TargetProbeStatus.FileAsProcess) { Resolved |= TargetProbeFacts.SelectedProcess; } diff --git a/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineVersion.cs b/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineVersion.cs index c0d717bc..a1c63ec5 100644 --- a/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineVersion.cs +++ b/libs/CheatEngine.SDK.Engine/Runtime/CheatEngineVersion.cs @@ -110,9 +110,9 @@ public override int GetHashCode() public override string ToString() { return Major.ToString(CultureInfo.InvariantCulture) + "." + - Minor.ToString(CultureInfo.InvariantCulture) + "." + - Release.ToString(CultureInfo.InvariantCulture) + "." + - Build.ToString(CultureInfo.InvariantCulture); + Minor.ToString(CultureInfo.InvariantCulture) + "." + + Release.ToString(CultureInfo.InvariantCulture) + "." + + Build.ToString(CultureInfo.InvariantCulture); } /// Tests two versions for equality. diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobBoundedScan.cs b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobBoundedScan.cs index 5df945dc..74829cf4 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobBoundedScan.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobBoundedScan.cs @@ -97,7 +97,7 @@ private static void RunSession(LuaState state, MemoryScanSession session, string } if (staging is not null && - facts.Kind is AobBoundedScanOutcomeKind.Matches or AobBoundedScanOutcomeKind.NoMatches) + facts.Kind is AobBoundedScanOutcomeKind.Matches or AobBoundedScanOutcomeKind.NoMatches) { staging.AsSpan(0, facts.Written).CopyTo(destination); } @@ -323,7 +323,11 @@ private static AobBoundedScanOutcomeKind FromContext(MemoryScanMaterializationSt private static AobBoundedScanResult Refused(AobBoundedScanOutcomeKind kind) { - AobBoundedScanFacts facts = new() { Kind = kind, Termination = MemoryScanTerminationStatus.NotRequired }; + AobBoundedScanFacts facts = new() + { + Kind = kind, + Termination = MemoryScanTerminationStatus.NotRequired + }; return new AobBoundedScanResult(in facts); } diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanBounds.cs b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanBounds.cs index 85ca2a04..aeef3a41 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanBounds.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanBounds.cs @@ -102,7 +102,7 @@ public static bool TryCreate(Address start, Address stop, out AobScanBounds boun public static bool TryFromModule(in ModuleInfo module, out AobScanBounds bounds) { if (module.ImageSize is not { } size || size.Value == 0 || - size.Value > ulong.MaxValue - module.BaseAddress.Value) + size.Value > ulong.MaxValue - module.BaseAddress.Value) { bounds = default; return false; diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOptions.cs b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOptions.cs index 90dbe341..db1f5304 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOptions.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Aob/AobScanOptions.cs @@ -94,8 +94,8 @@ public string? AlignmentParameter public bool Equals(AobScanOptions other) { return string.Equals(ProtectionFlags, other.ProtectionFlags, StringComparison.Ordinal) && - AlignmentMethod == other.AlignmentMethod && - string.Equals(AlignmentParameter, other.AlignmentParameter, StringComparison.Ordinal); + AlignmentMethod == other.AlignmentMethod && + string.Equals(AlignmentParameter, other.AlignmentParameter, StringComparison.Ordinal); } /// diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSession.cs b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSession.cs index ff5e8239..33e55081 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSession.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSession.cs @@ -668,7 +668,7 @@ public void ResetCancellable(CancellationToken cancellationToken) } if (State == MemoryScanState.Scanning || - (_terminationAttempted && _termination != MemoryScanTerminationStatus.Confirmed)) + (_terminationAttempted && _termination != MemoryScanTerminationStatus.Confirmed)) { ThrowWrongState("Reset"); } @@ -1258,7 +1258,7 @@ internal static int ToWaitMilliseconds(TimeSpan timeout, string parameterName) long ticks = timeout.Ticks; long milliseconds = (ticks / TimeSpan.TicksPerMillisecond) + - (ticks % TimeSpan.TicksPerMillisecond == 0 ? 0 : 1); + (ticks % TimeSpan.TicksPerMillisecond == 0 ? 0 : 1); if (milliseconds > int.MaxValue) { throw new ArgumentOutOfRangeException(parameterName, timeout, @@ -1372,7 +1372,7 @@ private MemoryScanTerminationStatus SettleAfterTermination(LuaState state, int w using LuaFrame frame = new(state); state.PushInteger(waitMilliseconds); if (!_scanner!.Value.Handle.TryCallMethod(state, "waitTillDone"u8, 1, 1).IsOk || - state.TypeOf(-1) != LuaType.Boolean) + state.TypeOf(-1) != LuaType.Boolean) { return MemoryScanTerminationStatus.WaitFailed; } @@ -1386,7 +1386,7 @@ internal bool TryReadHostErrorTextCore(LuaState state, [NotNullWhen(true)] out s { using LuaFrame frame = new(state); if (!_scanner!.Value.Handle.TryGetProperty(state, "ErrorString"u8).IsOk || - !state.TryReadUtf8(-1, out ReadOnlySpan utf8)) + !state.TryReadUtf8(-1, out ReadOnlySpan utf8)) { text = null; truncated = false; @@ -1653,7 +1653,7 @@ private MemoryScanReleaseOutcome CompleteRelease(TargetReleaseOutcome foundListO private TargetReleaseOutcome CreateRefusedReleaseOutcome(MemoryScanMaterializationStatus context) { if (context is MemoryScanMaterializationStatus.TargetIdentityUnavailable or - MemoryScanMaterializationStatus.TargetIdentityMismatch && LastTargetCheck.HasValue) + MemoryScanMaterializationStatus.TargetIdentityMismatch && LastTargetCheck.HasValue) { return TargetReleaseOutcome.Refused(LastTargetCheck.GetValueOrDefault()); } diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSessions.cs b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSessions.cs index 3502fd93..642212d6 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSessions.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanSessions.cs @@ -157,8 +157,8 @@ private static MemoryScanCreationStatus TryCreateDetailedCore([NotNullWhen(true) bool foundListRollbackFailed = !TryRollback(state, foundList, foundListHandle); bool scannerRollbackFailed = !TryRollback(state, scanner, scannerHandle); if ((foundListRollbackFailed || scannerRollbackFailed) - && session is null - && status != MemoryScanCreationStatus.Success) + && session is null + && status != MemoryScanCreationStatus.Success) { status = MemoryScanCreationStatus.RollbackUnconfirmed; } diff --git a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanStateException.cs b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanStateException.cs index 74d26907..4c84d6be 100644 --- a/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanStateException.cs +++ b/libs/CheatEngine.SDK.Engine/Scanning/Values/MemoryScanStateException.cs @@ -18,7 +18,7 @@ internal MemoryScanStateException(string operation, MemoryScanState state) // A re-entrant call: work that Cheat Engine ran from inside the session's active CE call called back into it. internal MemoryScanStateException(string operation, MemoryScanState state, string activeOperation) : base("The memory-scan operation '" + operation + "' was refused because the session's '" + activeOperation + - "' operation is still inside a Cheat Engine call (the call came from work Cheat Engine ran during it).") + "' operation is still inside a Cheat Engine call (the call came from work Cheat Engine ran during it).") { Operation = operation; State = state; diff --git a/libs/CheatEngine.SDK.Engine/Targets/TargetSelection.cs b/libs/CheatEngine.SDK.Engine/Targets/TargetSelection.cs index 700e8f3e..dadf4d1a 100644 --- a/libs/CheatEngine.SDK.Engine/Targets/TargetSelection.cs +++ b/libs/CheatEngine.SDK.Engine/Targets/TargetSelection.cs @@ -216,7 +216,7 @@ private static bool TryObserveIncarnation(int processId, out TargetProcessIncarn return true; } catch (Exception exception) when (exception is ArgumentException or InvalidOperationException or Win32Exception - or NotSupportedException or UnauthorizedAccessException) + or NotSupportedException or UnauthorizedAccessException) { incarnation = default; return false; diff --git a/libs/CheatEngine.SDK.Engine/Values/Address.cs b/libs/CheatEngine.SDK.Engine/Values/Address.cs index 5c01ee30..c71ddf7e 100644 --- a/libs/CheatEngine.SDK.Engine/Values/Address.cs +++ b/libs/CheatEngine.SDK.Engine/Values/Address.cs @@ -574,7 +574,7 @@ private static int HexDigitValue(byte b) private static void ThrowFormat(ReadOnlySpan text) { throw new FormatException("'" + text.ToString() + - "' is not a hexadecimal address (digits with an optional 0x prefix)."); + "' is not a hexadecimal address (digits with an optional 0x prefix)."); } [DoesNotReturn] diff --git a/libs/CheatEngine.SDK.Engine/packages.lock.json b/libs/CheatEngine.SDK.Engine/packages.lock.json index 13ead563..323657c0 100644 --- a/libs/CheatEngine.SDK.Engine/packages.lock.json +++ b/libs/CheatEngine.SDK.Engine/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.BannedApiAnalyzers": { "type": "Direct", diff --git a/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs b/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs index 93f13ee7..ec7dada4 100644 --- a/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs +++ b/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.Lifecycle.cs @@ -139,7 +139,7 @@ private static bool TryEnterLifecycleCallback(string callback) if (SGate.IsHeldByCurrentThread) { HostLog.Error(callback + - ": re-entered from plugin code while OnEnable or OnDisable is running on this thread; the call is refused and the outer transition decides the state."); + ": re-entered from plugin code while OnEnable or OnDisable is running on this thread; the call is refused and the outer transition decides the state."); return false; } @@ -149,7 +149,7 @@ private static bool TryEnterLifecycleCallback(string callback) } HostLog.Error(callback + - ": another lifecycle transition is already running; concurrent callbacks fail immediately and do not wait for plugin code."); + ": another lifecycle transition is already running; concurrent callbacks fail immediately and do not wait for plugin code."); return false; } @@ -220,7 +220,7 @@ private static LifecycleStart TryStartEnable(out PluginDescriptor? descriptor) if (Phase is not PluginHostLifecyclePhase.Registered) { HostLog.Error("EnablePlugin: the plugin lifecycle is in " + Phase + - "; enable is valid only from Registered."); + "; enable is valid only from Registered."); return LifecycleStart.Refused; } @@ -537,17 +537,17 @@ private static LifecycleStart SelectDisableStart( if (context is null) { HostLog.Error("DisablePlugin: the plugin lifecycle is in " + Phase + - "; disable is valid only from Enabled or incomplete failed-enable cleanup."); + "; disable is valid only from Enabled or incomplete failed-enable cleanup."); return LifecycleStart.Refused; } if (Phase is PluginHostLifecyclePhase.Disabling) { if (Volatile.Read(ref s_incompleteEnableCleanup) == 0 - || Volatile.Read(ref s_incompleteEnableCleanupActive) != 0) + || Volatile.Read(ref s_incompleteEnableCleanupActive) != 0) { HostLog.Error("DisablePlugin: the plugin lifecycle is in " + Phase + - "; a disable transition is already completing."); + "; a disable transition is already completing."); return LifecycleStart.Refused; } @@ -557,7 +557,7 @@ private static LifecycleStart SelectDisableStart( if (Phase is not PluginHostLifecyclePhase.Enabled) { HostLog.Error("DisablePlugin: the plugin lifecycle is in " + Phase + - "; disable is valid only from Enabled or incomplete failed-enable cleanup."); + "; disable is valid only from Enabled or incomplete failed-enable cleanup."); return LifecycleStart.Refused; } diff --git a/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.cs b/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.cs index 9dc32b20..5721509f 100644 --- a/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.cs +++ b/libs/CheatEngine.SDK.Hosting/Bootstrap/PluginHost.cs @@ -124,8 +124,8 @@ internal static MainThreadWorkAdmission AdmitMainThreadWork(PluginContext contex lock (SAdmissionGate) { if (Phase is not PluginHostLifecyclePhase.Enabled || - !ReferenceEquals(context, Volatile.Read(ref s_context)) || - Volatile.Read(ref s_acceptingMainThreadWork) == 0) + !ReferenceEquals(context, Volatile.Read(ref s_context)) || + Volatile.Read(ref s_acceptingMainThreadWork) == 0) { throw new InvalidOperationException( "The plugin is stopping or disabled and no longer accepts new main-thread dispatch work."); diff --git a/libs/CheatEngine.SDK.Hosting/Diagnostics/LoadIdentification.cs b/libs/CheatEngine.SDK.Hosting/Diagnostics/LoadIdentification.cs index 49febe33..26be7211 100644 --- a/libs/CheatEngine.SDK.Hosting/Diagnostics/LoadIdentification.cs +++ b/libs/CheatEngine.SDK.Hosting/Diagnostics/LoadIdentification.cs @@ -108,9 +108,9 @@ private static void AppendSdkVersion(StringBuilder builder) string abiVersion = ReadInformationalVersion(typeof(AbiConstants).Assembly); bool consistent = string.Equals(hostingVersion, luaVersion, StringComparison.Ordinal) - && string.Equals(hostingVersion, luaInteropVersion, StringComparison.Ordinal) - && string.Equals(hostingVersion, abiVersion, StringComparison.Ordinal) - && !string.Equals(hostingVersion, Unknown, StringComparison.Ordinal); + && string.Equals(hostingVersion, luaInteropVersion, StringComparison.Ordinal) + && string.Equals(hostingVersion, abiVersion, StringComparison.Ordinal) + && !string.Equals(hostingVersion, Unknown, StringComparison.Ordinal); AppendField(builder, "sdk.version", hostingVersion); AppendField(builder, "sdk.commit", ParseCommit(hostingVersion)); @@ -217,7 +217,7 @@ private static void ReadBridgeFacts(out string fingerprint, out string sha256) try { if (!NativeLibrary.TryLoad("cheatengine-sdk-lua-bridge", typeof(PluginHost).Assembly, - DllImportSearchPath.AssemblyDirectory, out nint handle)) + DllImportSearchPath.AssemblyDirectory, out nint handle)) { return; } @@ -225,7 +225,7 @@ private static void ReadBridgeFacts(out string fingerprint, out string sha256) try { if (NativeLibrary.TryGetExport(handle, "cheatengine_sdk_lua_bridge_source_fingerprint", - out nint export)) + out nint export)) { string? text = ReadBoundedAnsiString((byte*) export, 160); if (text is not null && BridgeFingerprintPattern().IsMatch(text)) diff --git a/libs/CheatEngine.SDK.Hosting/Threading/MainThreadDispatcher.cs b/libs/CheatEngine.SDK.Hosting/Threading/MainThreadDispatcher.cs index ff27264e..e4d4c5ca 100644 --- a/libs/CheatEngine.SDK.Hosting/Threading/MainThreadDispatcher.cs +++ b/libs/CheatEngine.SDK.Hosting/Threading/MainThreadDispatcher.cs @@ -104,7 +104,7 @@ internal static void Dispatch(MainThreadWorkItem item) if (!status.IsOk) { throw new InvalidOperationException("The host's 'synchronize' global could not be read: " + - LuaError.FromStack(l, status).Message); + LuaError.FromStack(l, status).Message); } if (!l.IsFunction(-1)) @@ -118,7 +118,7 @@ internal static void Dispatch(MainThreadWorkItem item) if (!status.IsOk) { throw new InvalidOperationException("The dispatch callback could not be created: " + - LuaError.FromStack(l, status).Message); + LuaError.FromStack(l, status).Message); } using (callback) @@ -134,7 +134,7 @@ internal static void Dispatch(MainThreadWorkItem item) if (!status.IsOk) { throw new InvalidOperationException("The host's 'synchronize' call failed: " + - LuaError.FromStack(l, status).Message); + LuaError.FromStack(l, status).Message); } } diff --git a/libs/CheatEngine.SDK.Hosting/packages.lock.json b/libs/CheatEngine.SDK.Hosting/packages.lock.json index 6aaef2a2..51af413a 100644 --- a/libs/CheatEngine.SDK.Hosting/packages.lock.json +++ b/libs/CheatEngine.SDK.Hosting/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.BannedApiAnalyzers": { "type": "Direct", diff --git a/libs/CheatEngine.SDK.Lua.Interop/Protected/LuaBridgeContract.cs b/libs/CheatEngine.SDK.Lua.Interop/Protected/LuaBridgeContract.cs index ec24718c..918b1510 100644 --- a/libs/CheatEngine.SDK.Lua.Interop/Protected/LuaBridgeContract.cs +++ b/libs/CheatEngine.SDK.Lua.Interop/Protected/LuaBridgeContract.cs @@ -38,15 +38,15 @@ internal struct LuaBridgeContract internal readonly bool IsCompatible() { return Magic == ExpectedMagic && - ContractSize == (uint) Unsafe.SizeOf() && - AbiMajor == ExpectedMajor && - AbiMinor >= MinimumMinor && - PointerSize == (byte) lua_KContext.Size && - LuaIntegerSize == (byte) Unsafe.SizeOf() && - SizeTSize == (byte) Unsafe.SizeOf() && - ExportTableSize == (uint) Unsafe.SizeOf() && - Reserved == 0 && - (SupportedOperations & LuaProtectedOperationContract.RequiredBitmap) == - LuaProtectedOperationContract.RequiredBitmap; + ContractSize == (uint) Unsafe.SizeOf() && + AbiMajor == ExpectedMajor && + AbiMinor >= MinimumMinor && + PointerSize == (byte) lua_KContext.Size && + LuaIntegerSize == (byte) Unsafe.SizeOf() && + SizeTSize == (byte) Unsafe.SizeOf() && + ExportTableSize == (uint) Unsafe.SizeOf() && + Reserved == 0 && + (SupportedOperations & LuaProtectedOperationContract.RequiredBitmap) == + LuaProtectedOperationContract.RequiredBitmap; } } diff --git a/libs/CheatEngine.SDK.Lua.Interop/packages.lock.json b/libs/CheatEngine.SDK.Lua.Interop/packages.lock.json index 75a512c2..cc7bf705 100644 --- a/libs/CheatEngine.SDK.Lua.Interop/packages.lock.json +++ b/libs/CheatEngine.SDK.Lua.Interop/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.BannedApiAnalyzers": { "type": "Direct", diff --git a/libs/CheatEngine.SDK.Lua/Callbacks/LuaCallback.cs b/libs/CheatEngine.SDK.Lua/Callbacks/LuaCallback.cs index bbf67dbf..66626f81 100644 --- a/libs/CheatEngine.SDK.Lua/Callbacks/LuaCallback.cs +++ b/libs/CheatEngine.SDK.Lua/Callbacks/LuaCallback.cs @@ -160,8 +160,8 @@ protected virtual void Dispose(bool disposing) } if (result is LuaRuntime.LuaCallbackDisposeOperationResult.AdmissionClosed - or LuaRuntime.LuaCallbackDisposeOperationResult.ThreadNotAdmitted - or LuaRuntime.LuaCallbackDisposeOperationResult.ExternalStateReset) + or LuaRuntime.LuaCallbackDisposeOperationResult.ThreadNotAdmitted + or LuaRuntime.LuaCallbackDisposeOperationResult.ExternalStateReset) { // This result was observed atomically with the closed gate, the thread-admission refusal or the detected // external reset. A later failed Detach can reopen admission, but cannot make it safe to abandon the diff --git a/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscription.cs b/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscription.cs index ca7ebca3..ff6ee0fc 100644 --- a/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscription.cs +++ b/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscription.cs @@ -109,8 +109,8 @@ public void Dispose() } if (result is LuaRuntime.LuaCallbackDisposeOperationResult.AdmissionClosed - or LuaRuntime.LuaCallbackDisposeOperationResult.ThreadNotAdmitted - or LuaRuntime.LuaCallbackDisposeOperationResult.ExternalStateReset) + or LuaRuntime.LuaCallbackDisposeOperationResult.ThreadNotAdmitted + or LuaRuntime.LuaCallbackDisposeOperationResult.ExternalStateReset) { // The lifecycle transition still owns the linked registration and has the only state allowed to unregister // it. In particular, do not consume the action here: a failed transition can reopen the old binding, and a @@ -240,9 +240,9 @@ private bool TryEnterCallback(out Action callback) { callback = null!; if (!_acceptCallbacks - || !LuaRuntime.IsAttached - || LuaRuntime.CurrentStateIdentity != Identity - || _callback is null) + || !LuaRuntime.IsAttached + || LuaRuntime.CurrentStateIdentity != Identity + || _callback is null) { return false; } diff --git a/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscriptionRegistry.cs b/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscriptionRegistry.cs index 3a5bde31..eef08c4a 100644 --- a/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscriptionRegistry.cs +++ b/libs/CheatEngine.SDK.Lua/Callbacks/LuaHostSubscriptionRegistry.cs @@ -47,8 +47,8 @@ internal static bool TryAdd(LuaHostSubscription subscription) lock (Gate) { if (!s_acceptRegistrations - || !LuaRuntime.IsAttached - || LuaRuntime.CurrentStateIdentity != subscription.Identity) + || !LuaRuntime.IsAttached + || LuaRuntime.CurrentStateIdentity != subscription.Identity) { return false; } diff --git a/libs/CheatEngine.SDK.Lua/CompilerServices/LuaCallSupport.cs b/libs/CheatEngine.SDK.Lua/CompilerServices/LuaCallSupport.cs index d3cd12ad..9c759add 100644 --- a/libs/CheatEngine.SDK.Lua/CompilerServices/LuaCallSupport.cs +++ b/libs/CheatEngine.SDK.Lua/CompilerServices/LuaCallSupport.cs @@ -299,6 +299,6 @@ public static void ThrowUnexpectedResult(LuaState state, int top, int index, str string typeName = Encoding.UTF8.GetString(state.TypeName(index)); state.SetTop(top); throw new LuaException("The Lua global '" + globalName + "' returned a " + typeName + " value, not " + - expected + "."); + expected + "."); } } diff --git a/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs b/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs index f3385044..da1ea1a2 100644 --- a/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs +++ b/libs/CheatEngine.SDK.Lua/Marshalling/LuaIntegerReader.cs @@ -84,7 +84,7 @@ private static bool AcceptConverted(LuaState state, int index, bool acceptIntege // lua_tointegerx already refused a non-integral, infinite or NaN float and one outside the long range. LuaType.Number => value is > -FloatExactLimit and < FloatExactLimit, LuaType.String => acceptIntegerNumerals && state.TryReadUtf8(index, out ReadOnlySpan text) && - IsIntegerNumeral(text), + IsIntegerNumeral(text), _ => false }; @@ -124,7 +124,7 @@ private static bool TryScanDecimal(ReadOnlySpan text, bool negative, ref i { int digit = text[i] - (byte) '0'; if (accumulated >= MaxIntegerDividedBy10 && - (accumulated > MaxIntegerDividedBy10 || digit > lastDigitLimit)) + (accumulated > MaxIntegerDividedBy10 || digit > lastDigitLimit)) { return false; } @@ -150,6 +150,6 @@ private static int SkipSpaces(ReadOnlySpan text, int i) private static bool IsHexadecimalDigit(byte character) { return (character >= (byte) '0' && character <= (byte) '9') || ((character | 0x20) >= (byte) 'a' && - (character | 0x20) <= (byte) 'f'); + (character | 0x20) <= (byte) 'f'); } } diff --git a/libs/CheatEngine.SDK.Lua/Marshalling/LuaOptional.cs b/libs/CheatEngine.SDK.Lua/Marshalling/LuaOptional.cs index b9e80c0e..37fd0e07 100644 --- a/libs/CheatEngine.SDK.Lua/Marshalling/LuaOptional.cs +++ b/libs/CheatEngine.SDK.Lua/Marshalling/LuaOptional.cs @@ -140,7 +140,7 @@ public bool TryGetValue([MaybeNullWhen(false)] out T value) public bool Equals(LuaOptional other) { return _state == other._state - && (_state != ValueState || EqualityComparer.Default.Equals(_value, other._value)); + && (_state != ValueState || EqualityComparer.Default.Equals(_value, other._value)); } /// diff --git a/libs/CheatEngine.SDK.Lua/References/LuaRef.cs b/libs/CheatEngine.SDK.Lua/References/LuaRef.cs index c873039e..e8b04e94 100644 --- a/libs/CheatEngine.SDK.Lua/References/LuaRef.cs +++ b/libs/CheatEngine.SDK.Lua/References/LuaRef.cs @@ -162,8 +162,8 @@ public void Release(LuaState state) { LuaRefBinding? binding = Interlocked.Exchange(ref _binding, null); if (binding is not null && binding.Reference != NoReference && - binding.Identity == LuaRuntime.CurrentStateIdentity && - !state.IsNull) + binding.Identity == LuaRuntime.CurrentStateIdentity && + !state.IsNull) { LuaReferences.Release(state, binding.Reference); } diff --git a/libs/CheatEngine.SDK.Lua/Registration/LuaRegistrationSet.cs b/libs/CheatEngine.SDK.Lua/Registration/LuaRegistrationSet.cs index 03750711..8ee670fb 100644 --- a/libs/CheatEngine.SDK.Lua/Registration/LuaRegistrationSet.cs +++ b/libs/CheatEngine.SDK.Lua/Registration/LuaRegistrationSet.cs @@ -35,7 +35,7 @@ public static LuaRegistrationResult Register(LuaState state, ReadOnlySpan diff --git a/libs/CheatEngine.SDK.Lua/Runtime/LuaRuntime.cs b/libs/CheatEngine.SDK.Lua/Runtime/LuaRuntime.cs index f2f155e3..acaf947f 100644 --- a/libs/CheatEngine.SDK.Lua/Runtime/LuaRuntime.cs +++ b/libs/CheatEngine.SDK.Lua/Runtime/LuaRuntime.cs @@ -821,8 +821,8 @@ internal static void CloseHostSubscriptionAdmissionAndDrain() internal static bool IsGeneratedFunctionRegistrationCurrent(int attachEpoch, int stateGeneration) { return Read(ref s_services) is not null - && Read(ref s_identity) == PackIdentity(attachEpoch, stateGeneration) - && IsOperationAdmissionOpen(); + && Read(ref s_identity) == PackIdentity(attachEpoch, stateGeneration) + && IsOperationAdmissionOpen(); } /// @@ -963,9 +963,9 @@ private static LuaAdmissionStatus TryEnterAdmissionGate(bool bypassThreadAdmissi } if (!bypassThreadAdmission - && Read(ref s_threadAdmission) == (int) LuaThreadAdmission.MainThreadOnly - && Environment.CurrentManagedThreadId != services.MainThreadId - && t_operationDepth == 0) + && Read(ref s_threadAdmission) == (int) LuaThreadAdmission.MainThreadOnly + && Environment.CurrentManagedThreadId != services.MainThreadId + && t_operationDepth == 0) { return LuaAdmissionStatus.ThreadNotAdmitted; } diff --git a/libs/CheatEngine.SDK.Lua/State/LuaState.Tables.cs b/libs/CheatEngine.SDK.Lua/State/LuaState.Tables.cs index 8728ead4..1ccc62b1 100644 --- a/libs/CheatEngine.SDK.Lua/State/LuaState.Tables.cs +++ b/libs/CheatEngine.SDK.Lua/State/LuaState.Tables.cs @@ -86,7 +86,7 @@ public bool TryRawSet(int tableIndex) { int keyType = lua_type(Pointer, -2); if (keyType == LUA_TNIL || (keyType == LUA_TNUMBER && lua_isinteger(Pointer, -2) == 0 && - double.IsNaN(lua_tonumberx(Pointer, -2, null)))) + double.IsNaN(lua_tonumberx(Pointer, -2, null)))) { lua_settop(Pointer, -3); return false; diff --git a/libs/CheatEngine.SDK.Lua/packages.lock.json b/libs/CheatEngine.SDK.Lua/packages.lock.json index a1e55139..01aa6303 100644 --- a/libs/CheatEngine.SDK.Lua/packages.lock.json +++ b/libs/CheatEngine.SDK.Lua/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.BannedApiAnalyzers": { "type": "Direct", diff --git a/native/cheatengine-sdk-lua-bridge/cheatengine_sdk_lua_bridge.c b/native/cheatengine-sdk-lua-bridge/cheatengine_sdk_lua_bridge.c index e9b3923c..06b878a5 100644 --- a/native/cheatengine-sdk-lua-bridge/cheatengine_sdk_lua_bridge.c +++ b/native/cheatengine-sdk-lua-bridge/cheatengine_sdk_lua_bridge.c @@ -250,7 +250,7 @@ static int CHEATENGINE_SDK_CALL operation(lua_State* L) { case OP_PUSH_BYTES: { - static constexpr char empty = 0; + static const char empty = 0; if (c->input_count != 0 || (c->size != 0 && !c->data)) return fail(L, "CheatEngine.SDK protected byte push has invalid arguments"); a->pushlstring(L, c->size ? (const char*)c->data : &empty, c->size); diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Emit/EngineApiFileEmitter.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Emit/EngineApiFileEmitter.cs index 6e77c7ac..4251e4ee 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Emit/EngineApiFileEmitter.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Emit/EngineApiFileEmitter.cs @@ -187,7 +187,8 @@ private static void EmitAddressTypedWrapper(SourceWriter writer, SpecCallModel e LuaGlobalCallModel call = entry.Call; LuaGlobalCallModel core = call with { - Modifiers = "private static", MethodName = CoreMethodName(call.MethodName) + Modifiers = "private static", + MethodName = CoreMethodName(call.MethodName) }; writer.Write("// Raw core of '"); diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Model/SpecFiles.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Model/SpecFiles.cs index f87cc430..777ac885 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Model/SpecFiles.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Model/SpecFiles.cs @@ -56,7 +56,10 @@ private static void AssignUniqueHintNames(List specs) } } - specs[i] = specs[i] with { HintName = hintName }; + specs[i] = specs[i] with + { + HintName = hintName + }; } } @@ -95,7 +98,10 @@ private static void SuppressCrossFileConflicts(List specs) foreach (int index in indices) { - specs[index] = specs[index] with { IsSuppressed = true }; + specs[index] = specs[index] with + { + IsSuppressed = true + }; } } } @@ -196,7 +202,10 @@ private static void AddConflict(ref SpecFileModel spec, int line, int column, st { List issues = [.. spec.Issues]; issues.Add(new SpecIssue(line, message, column, SpecIssueKind.Conflict)); - spec = spec with { Issues = new EquatableArray([.. issues]) }; + spec = spec with + { + Issues = new EquatableArray([.. issues]) + }; } private static string QualifiedTypeName(SpecFileModel spec) diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs index f2a9be98..994155c2 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecFileParser.cs @@ -208,13 +208,13 @@ private static bool ParseHeader(List blocks, List issues, out } if (!ReadHeaderFields( - header, - issues, - out string? namespaceValue, - out string? typeValue, - out typeLine, - out typeColumn, - out contract)) + header, + issues, + out string? namespaceValue, + out string? typeValue, + out typeLine, + out typeColumn, + out contract)) { return false; } @@ -365,10 +365,10 @@ private static bool TryCreateCe77Contract(HeaderFields fields, Block header, Lis { contract = null; if (!TryRequireContractField(fields.Provenance, "provenance", header, issues, out SpecField provenance) - || !TryRequireContractField(fields.MinimumCe, "minimum-ce", header, issues, out SpecField minimumCe) - || !TryRequireContractField(fields.Architecture, "architecture", header, issues, out SpecField architecture) - || !TryRequireContractField(fields.Thread, "thread", header, issues, out SpecField thread) - || !TryRequireContractField(fields.Ownership, "ownership", header, issues, out SpecField ownership)) + || !TryRequireContractField(fields.MinimumCe, "minimum-ce", header, issues, out SpecField minimumCe) + || !TryRequireContractField(fields.Architecture, "architecture", header, issues, out SpecField architecture) + || !TryRequireContractField(fields.Thread, "thread", header, issues, out SpecField thread) + || !TryRequireContractField(fields.Ownership, "ownership", header, issues, out SpecField ownership)) { return false; } @@ -502,11 +502,11 @@ private static bool IsValidProvenance(string value) string status = value[..colon]; return string.Equals(status, "ExactBinary", StringComparison.Ordinal) - || string.Equals(status, "ExactInstalledFile", StringComparison.Ordinal) - || string.Equals(status, "PinnedUpstream", StringComparison.Ordinal) - || string.Equals(status, "ObservedLive", StringComparison.Ordinal) - || string.Equals(status, "Inferred", StringComparison.Ordinal) - || string.Equals(status, "Unknown", StringComparison.Ordinal); + || string.Equals(status, "ExactInstalledFile", StringComparison.Ordinal) + || string.Equals(status, "PinnedUpstream", StringComparison.Ordinal) + || string.Equals(status, "ObservedLive", StringComparison.Ordinal) + || string.Equals(status, "Inferred", StringComparison.Ordinal) + || string.Equals(status, "Unknown", StringComparison.Ordinal); } private static bool IsFourPartVersion(string value) @@ -541,23 +541,23 @@ private static bool IsFourPartVersion(string value) private static bool IsThreadAffinity(string value) { return string.Equals(value, "any", StringComparison.Ordinal) - || string.Equals(value, "main", StringComparison.Ordinal) - || string.Equals(value, "unknown", StringComparison.Ordinal); + || string.Equals(value, "main", StringComparison.Ordinal) + || string.Equals(value, "unknown", StringComparison.Ordinal); } private static bool IsOwnership(string value) { return string.Equals(value, "none", StringComparison.Ordinal) - || string.Equals(value, "borrowed", StringComparison.Ordinal) - || string.Equals(value, "owned", StringComparison.Ordinal); + || string.Equals(value, "borrowed", StringComparison.Ordinal) + || string.Equals(value, "owned", StringComparison.Ordinal); } private static bool IsNilSemantics(string value) { return string.Equals(value, "none", StringComparison.Ordinal) - || string.Equals(value, "absence", StringComparison.Ordinal) - || string.Equals(value, "expected-failure", StringComparison.Ordinal) - || string.Equals(value, "lua-error", StringComparison.Ordinal); + || string.Equals(value, "absence", StringComparison.Ordinal) + || string.Equals(value, "expected-failure", StringComparison.Ordinal) + || string.Equals(value, "lua-error", StringComparison.Ordinal); } private static SpecCallModel? ParseEntry(Block block, List issues, SpecFileContract? fileContract) @@ -597,7 +597,7 @@ private static bool IsNilSemantics(string value) } if (!TryParseReturnKind(fields, form == LuaCallForm.Throwing, block.StartLine, issues, - out LuaValueKind? returnKind, out bool returnIsNullable)) + out LuaValueKind? returnKind, out bool returnIsNullable)) { return null; } @@ -763,7 +763,7 @@ private static bool ValidateRequiredText(EntryFields fields, int startLine, bool form = LuaCallForm.Throwing; if (!ValidateRequiredPresence(fields, startLine, issues) - || !ValidateNilContract(fields, startLine, requiresCe77Contract, issues)) + || !ValidateNilContract(fields, startLine, requiresCe77Contract, issues)) { return false; } @@ -935,8 +935,8 @@ private static bool TryParseReturnKind( private static LuaArgumentModel? ParseValueArgument(SpecToken token, List issues) { if (!TryParseNamedValue(token.Value, out string name, out string kindToken) - || !SpecIdentifiers.IsValidIdentifier(name) - || !SpecValueKinds.TryParse(kindToken, out LuaValueKind kind, out bool nullable)) + || !SpecIdentifiers.IsValidIdentifier(name) + || !SpecValueKinds.TryParse(kindToken, out LuaValueKind kind, out bool nullable)) { issues.Add(new SpecIssue(token.Line, "'" + token.Value + "' is not a valid 'name:kind' argument.", token.Column)); @@ -966,9 +966,9 @@ private static bool TryParseReturnKind( private static LuaArgumentModel? ParseFixedArgument(SpecToken token, List issues) { if (!TryParseNamedValue(token.Value, out string kindToken, out string literal) - || !string.Equals(kindToken, "boolean", StringComparison.Ordinal) - || !(string.Equals(literal, "true", StringComparison.Ordinal) - || string.Equals(literal, "false", StringComparison.Ordinal))) + || !string.Equals(kindToken, "boolean", StringComparison.Ordinal) + || !(string.Equals(literal, "true", StringComparison.Ordinal) + || string.Equals(literal, "false", StringComparison.Ordinal))) { issues.Add(new SpecIssue(token.Line, "'" + token.Value + "' is not a valid fixed argument: expected 'boolean:true' or 'boolean:false'.", @@ -985,8 +985,8 @@ private static bool TryParseReturnKind( foreach (SpecToken token in tokens) { if (!TryParseNamedValue(token.Value, out string name, out string kindToken) - || !SpecIdentifiers.IsValidIdentifier(name) - || !SpecValueKinds.TryParse(kindToken, out LuaValueKind kind, out bool nullable)) + || !SpecIdentifiers.IsValidIdentifier(name) + || !SpecValueKinds.TryParse(kindToken, out LuaValueKind kind, out bool nullable)) { issues.Add(new SpecIssue(token.Line, "'" + token.Value + "' is not a valid 'name:kind' result.", token.Column)); @@ -1245,8 +1245,8 @@ private static bool IsReservedBodyLocal(string name, LuaGlobalCallModel call) } if (string.Equals(name, "__engineApiSucceeded", StringComparison.Ordinal) - || string.Equals(name, "__engineApiStatus", StringComparison.Ordinal) - || string.Equals(name, "__engineApiRawResult", StringComparison.Ordinal)) + || string.Equals(name, "__engineApiStatus", StringComparison.Ordinal) + || string.Equals(name, "__engineApiRawResult", StringComparison.Ordinal)) { return true; } @@ -1259,7 +1259,7 @@ private static bool IsReservedBodyLocal(string name, LuaGlobalCallModel call) for (int i = 0; i < call.Results.Length; i++) { if (call.Results[i].Kind == LuaValueKind.Address - && string.Equals(name, RawResultName(i), StringComparison.Ordinal)) + && string.Equals(name, RawResultName(i), StringComparison.Ordinal)) { return true; } @@ -1327,8 +1327,8 @@ private static List DropCacheMemberCollisions(List foreach (SpecCallModel entry in entries) { bool conflicts = cacheFields.Contains(entry.Call.MethodName) - || (UsesAddressFacade(entry.Call) && - cacheFields.Contains(CoreMethodName(entry.Call.MethodName))); + || (UsesAddressFacade(entry.Call) && + cacheFields.Contains(CoreMethodName(entry.Call.MethodName))); if (!conflicts) { valid.Add(entry); @@ -1354,9 +1354,9 @@ private static List DropTypeMemberCollisions(List foreach (SpecCallModel entry in entries) { bool conflicts = string.Equals(entry.Call.MethodName, typeName, StringComparison.Ordinal) - || (UsesAddressFacade(entry.Call) - && string.Equals(CoreMethodName(entry.Call.MethodName), typeName, - StringComparison.Ordinal)); + || (UsesAddressFacade(entry.Call) + && string.Equals(CoreMethodName(entry.Call.MethodName), typeName, + StringComparison.Ordinal)); if (!conflicts) { valid.Add(entry); diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs index ee692c81..d845190a 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/Parsing/SpecIdentifiers.cs @@ -86,7 +86,7 @@ public static string Escape(string identifier) private static bool IsStart(char c) { - return c is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or '_'; + return c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '_'; } private static bool IsPart(char c) diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/packages.lock.json b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/packages.lock.json index 64d57ef4..50d815cb 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/packages.lock.json +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EngineApi/packages.lock.json @@ -4,9 +4,9 @@ ".NETStandard,Version=v2.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.Analyzers": { "type": "Direct", diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Emit/BootstrapEmitter.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Emit/BootstrapEmitter.cs index ffbb1dcd..6641af32 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Emit/BootstrapEmitter.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Emit/BootstrapEmitter.cs @@ -95,8 +95,8 @@ public static SourceText Emit(BootstrapModel model) internal static string ChooseFactoryName(string fullyQualifiedPluginTypeName) { bool collides = fullyQualifiedPluginTypeName.StartsWith(QualifiedFactoryName, StringComparison.Ordinal) - && (fullyQualifiedPluginTypeName.Length == QualifiedFactoryName.Length - || fullyQualifiedPluginTypeName[QualifiedFactoryName.Length] == '.'); + && (fullyQualifiedPluginTypeName.Length == QualifiedFactoryName.Length + || fullyQualifiedPluginTypeName[QualifiedFactoryName.Length] == '.'); return collides ? AlternateFactoryName : FactoryName; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointContractSymbols.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointContractSymbols.cs index 7832ce47..8e008a51 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointContractSymbols.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointContractSymbols.cs @@ -93,7 +93,7 @@ public static EntryPointContractSymbols Resolve(Compilation compilation) foreach (MetadataReference reference in compilation.References) { if (compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly - && string.Equals(assembly.Identity.Name, assemblyName, StringComparison.Ordinal)) + && string.Equals(assembly.Identity.Name, assemblyName, StringComparison.Ordinal)) { return assembly.GetTypeByMetadataName(metadataName); } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointDeclaredDiagnosticIds.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointDeclaredDiagnosticIds.cs index 5ba484e2..1e77ee26 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointDeclaredDiagnosticIds.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointDeclaredDiagnosticIds.cs @@ -82,8 +82,8 @@ private static void CollectFrom( foreach (AttributeData attribute in attributes) { if (ReadDeclaredId(attribute, experimentalAttribute, obsoleteAttribute) is { } id - && IsUsableInPragma(id) - && (ids is null || !ids.Contains(id))) + && IsUsableInPragma(id) + && (ids is null || !ids.Contains(id))) { (ids ??= []).Add(id); } @@ -96,24 +96,24 @@ private static void CollectFrom( INamedTypeSymbol? obsoleteAttribute) { if (experimentalAttribute is not null - && SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, experimentalAttribute)) - // [Experimental(string diagnosticId)] + && SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, experimentalAttribute)) + // [Experimental(string diagnosticId)] { return attribute.ConstructorArguments.Length == 1 - && attribute.ConstructorArguments[0] is - { Kind: TypedConstantKind.Primitive, Value: string experimentalId } + && attribute.ConstructorArguments[0] is + { Kind: TypedConstantKind.Primitive, Value: string experimentalId } ? experimentalId : null; } if (obsoleteAttribute is not null - && SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, obsoleteAttribute)) - // [Obsolete(..., DiagnosticId = "ID")] + && SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, obsoleteAttribute)) + // [Obsolete(..., DiagnosticId = "ID")] { foreach (KeyValuePair argument in attribute.NamedArguments) { if (string.Equals(argument.Key, "DiagnosticId", StringComparison.Ordinal) - && argument.Value is { Kind: TypedConstantKind.Primitive, Value: string obsoleteId }) + && argument.Value is { Kind: TypedConstantKind.Primitive, Value: string obsoleteId }) { return obsoleteId; } @@ -129,7 +129,7 @@ private static void CollectFrom( private static bool IsUsableInPragma(string id) { return SyntaxFacts.IsValidIdentifier(id) - && SyntaxFacts.GetKeywordKind(id) == SyntaxKind.None - && SyntaxFacts.GetPreprocessorKeywordKind(id) == SyntaxKind.None; + && SyntaxFacts.GetKeywordKind(id) == SyntaxKind.None + && SyntaxFacts.GetPreprocessorKeywordKind(id) == SyntaxKind.None; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointGeneratedIdentity.cs b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointGeneratedIdentity.cs index 4620c2ca..b32aaa9d 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointGeneratedIdentity.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/Parsing/EntryPointGeneratedIdentity.cs @@ -29,8 +29,8 @@ public static bool HasEntryPointTypeCollision(Compilation compilation) foreach (INamedTypeSymbol type in @namespace.GetTypeMembers(ManagedEntryPointNames.TypeName)) { if (type.Arity == 0 - && !type.IsFileLocal - && SymbolEqualityComparer.Default.Equals(type.ContainingAssembly, compilation.Assembly)) + && !type.IsFileLocal + && SymbolEqualityComparer.Default.Equals(type.ContainingAssembly, compilation.Assembly)) { return true; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/packages.lock.json b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/packages.lock.json index 64d57ef4..50d815cb 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/packages.lock.json +++ b/source-generators/CheatEngine.SDK.SourceGenerators.EntryPoint/packages.lock.json @@ -4,9 +4,9 @@ ".NETStandard,Version=v2.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.Analyzers": { "type": "Direct", diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Emit/LuaObjectMembersFileEmitter.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Emit/LuaObjectMembersFileEmitter.cs index 7af12ef8..11eef56a 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Emit/LuaObjectMembersFileEmitter.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Emit/LuaObjectMembersFileEmitter.cs @@ -215,7 +215,7 @@ private static void WriteStackCheck(SourceWriter writer, LuaObjectMethodModel mo writer.Write('('); writer.Write(CSharpLiteral.ToStringLiteral( "The Lua stack could not grow by " + requiredSlots.ToString(CultureInfo.InvariantCulture) - + " slots to call '" + model.LuaName + "'.")); + + " slots to call '" + model.LuaName + "'.")); writer.WriteLine(");"); } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionModel.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionModel.cs index 41dc2aa4..4a6510f0 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionModel.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionModel.cs @@ -35,5 +35,5 @@ internal sealed record LuaFunctionModel( /// group). /// public bool IsValid => Issues == LuaFunctionShapeIssues.None && ContainingTypeIssues == ContainingTypeIssues.None && - Thunk is not null && !HasGeneratedIdentityCollision; + Thunk is not null && !HasGeneratedIdentityCollision; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionTables.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionTables.cs index 203502fc..d6b50a7f 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionTables.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaFunctionTables.cs @@ -67,7 +67,10 @@ private static List AssignHintNames(List when a body can be emitted for this method. public bool IsValid => Issues == LuaGlobalShapeIssues.None && ContainingTypeIssues == ContainingTypeIssues.None && - Call is not null && !HasGeneratedIdentityCollision; + Call is not null && !HasGeneratedIdentityCollision; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaGlobalTables.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaGlobalTables.cs index 8b4cf4b5..d865efd9 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaGlobalTables.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Model/LuaGlobalTables.cs @@ -85,7 +85,10 @@ private static List AssignHintNames(List tables) for (int i = 0; i < tables.Count; i++) { string baseName = tables[i].ContainingType.HintBaseName; - tables[i] = tables[i] with { HintName = HintNames.AllocateUnique(baseName, HintSuffix, used) }; + tables[i] = tables[i] with + { + HintName = HintNames.AllocateUnique(baseName, HintSuffix, used) + }; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/ContainingTypeParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/ContainingTypeParser.cs index 94a58a4f..fa885b88 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/ContainingTypeParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/ContainingTypeParser.cs @@ -75,7 +75,7 @@ private static bool IsReadOnly(INamedTypeSymbol type) foreach (SyntaxReference reference in type.DeclaringSyntaxReferences) { if (reference.GetSyntax() is TypeDeclarationSyntax declaration - && declaration.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) + && declaration.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) { return true; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaBindingsDeclaredDiagnosticIds.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaBindingsDeclaredDiagnosticIds.cs index ea7f0b3f..8d08bae3 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaBindingsDeclaredDiagnosticIds.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaBindingsDeclaredDiagnosticIds.cs @@ -81,24 +81,24 @@ public static string Collect(IMethodSymbol method) } if (string.Equals(attributeClass.Name, "ExperimentalAttribute", StringComparison.Ordinal)) - // [Experimental(string diagnosticId)] + // [Experimental(string diagnosticId)] { return IsNamespace(attributeClass.ContainingNamespace, "System", "Diagnostics", "CodeAnalysis") - && attribute.ConstructorArguments.Length == 1 - && attribute.ConstructorArguments[0] is - { Kind: TypedConstantKind.Primitive, Value: string experimentalId } + && attribute.ConstructorArguments.Length == 1 + && attribute.ConstructorArguments[0] is + { Kind: TypedConstantKind.Primitive, Value: string experimentalId } ? experimentalId : null; } if (string.Equals(attributeClass.Name, "ObsoleteAttribute", StringComparison.Ordinal) - && IsNamespace(attributeClass.ContainingNamespace, "System")) - // [Obsolete(..., DiagnosticId = "ID")] + && IsNamespace(attributeClass.ContainingNamespace, "System")) + // [Obsolete(..., DiagnosticId = "ID")] { foreach (KeyValuePair argument in attribute.NamedArguments) { if (string.Equals(argument.Key, "DiagnosticId", StringComparison.Ordinal) - && argument.Value is { Kind: TypedConstantKind.Primitive, Value: string obsoleteId }) + && argument.Value is { Kind: TypedConstantKind.Primitive, Value: string obsoleteId }) { return obsoleteId; } @@ -130,7 +130,7 @@ private static bool IsNamespace(INamespaceSymbol? @namespace, params string[] na private static bool IsUsableInPragma(string id) { return SyntaxFacts.IsValidIdentifier(id) - && SyntaxFacts.GetKeywordKind(id) == SyntaxKind.None - && SyntaxFacts.GetPreprocessorKeywordKind(id) == SyntaxKind.None; + && SyntaxFacts.GetKeywordKind(id) == SyntaxKind.None + && SyntaxFacts.GetPreprocessorKeywordKind(id) == SyntaxKind.None; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaClassParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaClassParser.cs index bf4789c0..43a5d565 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaClassParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaClassParser.cs @@ -27,7 +27,7 @@ public static LuaClassModel Parse(GeneratorAttributeSyntaxContext context, Cance string? luaName = LuaBindingSymbols.ReadSdkAttributeName(context.Attributes, compilation, LuaBindingsGenerator.LuaClassAttributeMetadataName); bool isValid = isSdkAttribute && LuaNames.IsValidName(luaName) - && IsBorrowedHandleShape(type, compilation, cancellationToken); + && IsBorrowedHandleShape(type, compilation, cancellationToken); return new LuaClassModel(ContainingTypeParser.Parse(type), luaName ?? string.Empty, isValid); } @@ -71,7 +71,7 @@ internal static bool IsGeneratedHandle(INamedTypeSymbol type, Compilation compil { ImmutableArray attributes = ImmutableArray.Create(attribute); if (LuaBindingSymbols.ContainsSdkAttribute(attributes, compilation, - LuaBindingsGenerator.LuaClassAttributeMetadataName)) + LuaBindingsGenerator.LuaClassAttributeMetadataName)) { return LuaNames.IsValidName(LuaBindingSymbols.ReadSdkAttributeName( attributes, @@ -89,7 +89,7 @@ private static bool IsReadOnlyStruct(INamedTypeSymbol type, CancellationToken ca { cancellationToken.ThrowIfCancellationRequested(); if (reference.GetSyntax(cancellationToken) is StructDeclarationSyntax declaration - && declaration.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) + && declaration.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) { return true; } @@ -103,10 +103,10 @@ private static bool IsReadOnlyStruct(INamedTypeSymbol type, CancellationToken ca private static bool HasGeneratedIdentityCollision(INamedTypeSymbol type, INamedTypeSymbol? ceObject) { return LuaClassGeneratedNames.IsGeneratedType(type.Name) - || HasGeneratedMember(type, ceObject) - || HasMember(type, "op_Equality") - || HasMember(type, "op_Inequality") - || HasCEObjectConstructor(type, ceObject); + || HasGeneratedMember(type, ceObject) + || HasMember(type, "op_Equality") + || HasMember(type, "op_Inequality") + || HasCEObjectConstructor(type, ceObject); } private static bool HasCEObjectConstructor(INamedTypeSymbol type, INamedTypeSymbol? ceObject) @@ -125,7 +125,7 @@ private static bool HasCEObjectConstructor(INamedTypeSymbol type, INamedTypeSymb IParameterSymbol parameter = constructor.Parameters[0]; if (parameter.RefKind == RefKind.None - && SymbolEqualityComparer.Default.Equals(parameter.Type, ceObject)) + && SymbolEqualityComparer.Default.Equals(parameter.Type, ceObject)) { return true; } @@ -139,7 +139,7 @@ private static bool HasGeneratedMember(INamedTypeSymbol type, INamedTypeSymbol? foreach (ISymbol member in type.GetMembers()) { if (LuaClassGeneratedNames.IsGeneratedMember(member.Name) - || LuaClassGeneratedNames.IsGeneratedAccessorCollision(member, ceObject)) + || LuaClassGeneratedNames.IsGeneratedAccessorCollision(member, ceObject)) { return true; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaFunctionParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaFunctionParser.cs index eb683f80..650f51ab 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaFunctionParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaFunctionParser.cs @@ -66,13 +66,13 @@ private static bool HasGeneratedIdentityCollision(IMethodSymbol method, string? { INamedTypeSymbol type = method.ContainingType; if (type.GetMembers(LuaRegistrationEmitter.RegisterMethodName).Length != 0 - || type.GetMembers(LuaRegistrationEmitter.RegisterLeaseMethodName).Length != 0 - || type.GetMembers(LuaRegistrationEmitter.UnregisterMethodName).Length != 0) + || type.GetMembers(LuaRegistrationEmitter.RegisterLeaseMethodName).Length != 0 + || type.GetMembers(LuaRegistrationEmitter.UnregisterMethodName).Length != 0) { return true; } return LuaNames.IsValidName(luaName) - && type.GetMembers(LuaThunkModel.ThunkNameFor(luaName!)).Length != 0; + && type.GetMembers(LuaThunkModel.ThunkNameFor(luaName!)).Length != 0; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaGlobalParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaGlobalParser.cs index 48475c6f..9e1f92e2 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaGlobalParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaGlobalParser.cs @@ -159,6 +159,6 @@ private static bool HasGeneratedIdentityCollision(IMethodSymbol method, string? } return LuaNames.IsValidName(luaName) - && method.ContainingType.GetMembers(LuaGlobalCallModel.CacheFieldFor(luaName!)).Length != 0; + && method.ContainingType.GetMembers(LuaGlobalCallModel.CacheFieldFor(luaName!)).Length != 0; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs index 2ebd0d2d..e72de6bd 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectMethodParser.cs @@ -38,13 +38,17 @@ public static LuaObjectMethodModel Parse(GeneratorAttributeSyntaxContext context bool described = TryDescribe(method, context.TargetNode as MethodDeclarationSyntax, out LuaObjectMethodModel model); bool valid = isSdkAttribute && LuaNames.IsValidName(luaName) - && LuaClassParser.IsGeneratedHandle(method.ContainingType, compilation, - cancellationToken) - && described; + && LuaClassParser.IsGeneratedHandle(method.ContainingType, compilation, + cancellationToken) + && described; if (valid) { - return model with { LuaName = luaName!, IsValid = true }; + return model with + { + LuaName = luaName!, + IsValid = true + }; } return new LuaObjectMethodModel( @@ -68,11 +72,11 @@ private static bool TryDescribe(IMethodSymbol method, MethodDeclarationSyntax? d ImmutableArray.CreateBuilder(method.Parameters.Length); ImmutableArray.Builder results = ImmutableArray.CreateBuilder(); bool valid = method.MethodKind == MethodKind.Ordinary - && !method.IsStatic - && method.IsPartialDefinition - && method.PartialImplementationPart is null - && !method.IsGenericMethod - && !method.IsAsync; + && !method.IsStatic + && method.IsPartialDefinition + && method.PartialImplementationPart is null + && !method.IsGenericMethod + && !method.IsAsync; valid &= DescribeParameters(method.Parameters, arguments, results); LuaCallForm form = results.Count == 0 ? LuaCallForm.Throwing : LuaCallForm.Try; @@ -103,7 +107,7 @@ private static bool DescribeParameters(ImmutableArray paramete foreach (IParameterSymbol parameter in parameters) { if (IsReserved(parameter.Name) || parameter.IsParams || parameter.IsOptional - || parameter.HasExplicitDefaultValue) + || parameter.HasExplicitDefaultValue) { valid = false; } @@ -112,7 +116,7 @@ private static bool DescribeParameters(ImmutableArray paramete { seenResult = true; if (!LuaValueKindMapper.TryMap(parameter.Type, out LuaValueKind kind, out bool nullable) - || !LuaValueKinds.CanBeResult(kind)) + || !LuaValueKinds.CanBeResult(kind)) { valid = false; } @@ -125,9 +129,9 @@ private static bool DescribeParameters(ImmutableArray paramete } if (parameter.RefKind != RefKind.None || seenResult - || !LuaValueKindMapper.TryMap(parameter.Type, - out LuaValueKind argumentKind, - out bool argumentNullable)) + || !LuaValueKindMapper.TryMap(parameter.Type, + out LuaValueKind argumentKind, + out bool argumentNullable)) { valid = false; } @@ -149,7 +153,7 @@ private static bool TryDescribeReturn(IMethodSymbol method, LuaCallForm form, ou if (form == LuaCallForm.Try) { return method.ReturnType.SpecialType == SpecialType.System_Boolean && !method.ReturnsByRef - && !method.ReturnsByRefReadonly; + && !method.ReturnsByRefReadonly; } if (method.ReturnsVoid) @@ -158,9 +162,9 @@ private static bool TryDescribeReturn(IMethodSymbol method, LuaCallForm form, ou } if (method.ReturnsByRef || method.ReturnsByRefReadonly - || !LuaValueKindMapper.TryMap(method.ReturnType, out LuaValueKind kind, - out returnNullable) - || !LuaValueKinds.CanBeResult(kind)) + || !LuaValueKindMapper.TryMap(method.ReturnType, out LuaValueKind kind, + out returnNullable) + || !LuaValueKinds.CanBeResult(kind)) { return false; } @@ -172,10 +176,10 @@ private static bool TryDescribeReturn(IMethodSymbol method, LuaCallForm form, ou private static bool IsReserved(string name) { return string.Equals(name, StateLocal, StringComparison.Ordinal) - || string.Equals(name, OperationLocal, StringComparison.Ordinal) - || string.Equals(name, TopLocal, StringComparison.Ordinal) - || string.Equals(name, StatusLocal, StringComparison.Ordinal) - || string.Equals(name, ResultLocal, StringComparison.Ordinal); + || string.Equals(name, OperationLocal, StringComparison.Ordinal) + || string.Equals(name, TopLocal, StringComparison.Ordinal) + || string.Equals(name, StatusLocal, StringComparison.Ordinal) + || string.Equals(name, ResultLocal, StringComparison.Ordinal); } private static string Modifiers(MethodDeclarationSyntax? declaration) diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs index 0ea9598a..4af51e2a 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/Parsing/LuaObjectPropertyParser.cs @@ -29,13 +29,17 @@ public static LuaObjectPropertyModel Parse(GeneratorAttributeSyntaxContext conte LuaBindingsGenerator.LuaPropertyAttributeMetadataName); bool described = TryDescribe(property, declaration, out LuaObjectPropertyModel model); bool valid = isSdkAttribute && LuaNames.IsValidName(luaName) - && LuaClassParser.IsGeneratedHandle(property.ContainingType, compilation, - cancellationToken) - && described; + && LuaClassParser.IsGeneratedHandle(property.ContainingType, compilation, + cancellationToken) + && described; if (valid) { - return model with { LuaName = luaName!, IsValid = true }; + return model with + { + LuaName = luaName!, + IsValid = true + }; } return new LuaObjectPropertyModel( @@ -59,7 +63,7 @@ private static bool TryDescribe(IPropertySymbol property, PropertyDeclarationSyn LuaValueKind kind; bool isNullable; bool typeIsSupported = LuaValueKindMapper.TryMap(property.Type, out kind, out isNullable) - && LuaValueKinds.CanBeResult(kind); + && LuaValueKinds.CanBeResult(kind); string modifiers; bool definitionIsSupported = IsSupportedDefinition(property, declaration, typeIsSupported, out modifiers); @@ -88,15 +92,15 @@ private static bool IsSupportedDefinition(IPropertySymbol property, PropertyDecl { modifiers = string.Empty; return declaration is not null - && !property.IsStatic - && !property.IsIndexer - && property.RefKind == RefKind.None - && declaration.Modifiers.Any(SyntaxKind.PartialKeyword) - && declaration.AccessorList is not null - && declaration.ExplicitInterfaceSpecifier is null - && property.PartialImplementationPart is null - && typeIsSupported - && TryModifiers(declaration, out modifiers); + && !property.IsStatic + && !property.IsIndexer + && property.RefKind == RefKind.None + && declaration.Modifiers.Any(SyntaxKind.PartialKeyword) + && declaration.AccessorList is not null + && declaration.ExplicitInterfaceSpecifier is null + && property.PartialImplementationPart is null + && typeIsSupported + && TryModifiers(declaration, out modifiers); } private static bool TryDescribeAccessors(PropertyDeclarationSyntax? declaration, out bool hasGetter, @@ -114,7 +118,7 @@ private static bool TryDescribeAccessors(PropertyDeclarationSyntax? declaration, foreach (AccessorDeclarationSyntax accessor in accessorList.Accessors) { if (!TryDescribeAccessor(accessor, ref hasGetter, ref getterModifiers, ref hasSetter, - ref setterModifiers)) + ref setterModifiers)) { return false; } @@ -127,7 +131,7 @@ private static bool TryDescribeAccessor(AccessorDeclarationSyntax accessor, ref ref string getterModifiers, ref bool hasSetter, ref string setterModifiers) { if (accessor.Body is not null || accessor.ExpressionBody is not null - || !TryAccessorModifiers(accessor, out string modifiers)) + || !TryAccessorModifiers(accessor, out string modifiers)) { return false; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/packages.lock.json b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/packages.lock.json index 64d57ef4..50d815cb 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/packages.lock.json +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBindings/packages.lock.json @@ -4,9 +4,9 @@ ".NETStandard,Version=v2.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.Analyzers": { "type": "Direct", diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs index 342e21fb..1a4f4cf0 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/Catalog/ProtectedOperationCatalogParser.cs @@ -149,7 +149,7 @@ private static void ParseOperation( ref ulong bitmap) { if (!TryReadOperationFields(value, reader, diagnostics, out JsonString idValue, out JsonNumber opcodeValue, - out JsonString? managedConstant)) + out JsonString? managedConstant)) { return; } @@ -162,7 +162,7 @@ private static void ParseOperation( } if (managedConstant is not null && - !string.Equals(managedConstant.Text, idValue.Text + "Operation", StringComparison.Ordinal)) + !string.Equals(managedConstant.Text, idValue.Text + "Operation", StringComparison.Ordinal)) { diagnostics.Add(reader.CreateDiagnostic(managedConstant.Span, "Property 'managed.constant' must be '" + idValue.Text + "Operation' for operation '" + idValue.Text + @@ -170,8 +170,8 @@ private static void ParseOperation( } if (!int.TryParse(opcodeValue.Text, NumberStyles.None, CultureInfo.InvariantCulture, out int opcode) - || opcode < 0 - || opcode > 63) + || opcode < 0 + || opcode > 63) { diagnostics.Add(reader.CreateDiagnostic(opcodeValue.Span, "Operation 'opcode' must be an integer between 0 and 63.")); @@ -446,7 +446,7 @@ private static bool IsPascalIdentifier(string value) for (int i = 1; i < value.Length; i++) { char character = value[i]; - if (character is not (>= 'A' and <= 'Z' or >= 'a' and <= 'z' or >= '0' and <= '9')) + if (character is not ((>= 'A' and <= 'Z') or (>= 'a' and <= 'z') or (>= '0' and <= '9'))) { return false; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/packages.lock.json b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/packages.lock.json index b52c3444..7109ba3b 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/packages.lock.json +++ b/source-generators/CheatEngine.SDK.SourceGenerators.LuaBridgeContract/packages.lock.json @@ -4,9 +4,9 @@ ".NETStandard,Version=v2.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.Analyzers": { "type": "Direct", diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/GeneratedCodeText.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/GeneratedCodeText.cs index a2925b84..eb75fc03 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/GeneratedCodeText.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/GeneratedCodeText.cs @@ -76,9 +76,9 @@ public static string CreateGeneratedCodeAttribute(Type generatorType) AssemblyName assembly = generatorType.Assembly.GetName(); string version = (assembly.Version ?? new Version(0, 0, 0, 0)).ToString(); return "[global::System.CodeDom.Compiler.GeneratedCode(" - + CSharpLiteral.ToStringLiteral(assembly.Name ?? string.Empty) - + ", " - + CSharpLiteral.ToStringLiteral(version) - + ")]"; + + CSharpLiteral.ToStringLiteral(assembly.Name ?? string.Empty) + + ", " + + CSharpLiteral.ToStringLiteral(version) + + ")]"; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs index fc7a6c50..a89502bd 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/HintNames.cs @@ -103,7 +103,7 @@ public static string AllocateUnique(string typeName, string suffix, HashSet= 'a' and <= 'z' or >= 'A' and <= 'Z' or >= '0' and <= '9' or '.' or '_') + if (c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or (>= '0' and <= '9') or '.' or '_') { builder.Append(c); } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/ContainingTypeShape.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/ContainingTypeShape.cs index ef0fb3bf..22fdeb27 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/ContainingTypeShape.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/ContainingTypeShape.cs @@ -61,7 +61,7 @@ private static bool IsPartial(INamedTypeSymbol type, CancellationToken cancellat foreach (SyntaxReference reference in type.DeclaringSyntaxReferences) { if (reference.GetSyntax(cancellationToken) is TypeDeclarationSyntax declaration - && declaration.Modifiers.Any(SyntaxKind.PartialKeyword)) + && declaration.Modifiers.Any(SyntaxKind.PartialKeyword)) { return true; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/Identifiers.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/Identifiers.cs index bd68372a..71173812 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/Identifiers.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/Identifiers.cs @@ -12,7 +12,7 @@ internal static class Identifiers public static string Escape(string name) { return SyntaxFacts.GetKeywordKind(name) != SyntaxKind.None || - SyntaxFacts.GetContextualKeywordKind(name) != SyntaxKind.None + SyntaxFacts.GetContextualKeywordKind(name) != SyntaxKind.None ? "@" + name : name; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaClassGeneratedNames.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaClassGeneratedNames.cs index 9c3397e8..e78f1a1f 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaClassGeneratedNames.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaClassGeneratedNames.cs @@ -28,12 +28,12 @@ public static bool IsGeneratedAccessorCollision(ISymbol member, INamedTypeSymbol } return method.MethodKind == MethodKind.Ordinary - && ((string.Equals(method.Name, "get_Handle", StringComparison.Ordinal) - && method.Parameters.Length == 0) - || (string.Equals(method.Name, "set_Handle", StringComparison.Ordinal) - && ceObject is not null - && method.Parameters.Length == 1 - && method.Parameters[0].RefKind == RefKind.None - && SymbolEqualityComparer.Default.Equals(method.Parameters[0].Type, ceObject))); + && ((string.Equals(method.Name, "get_Handle", StringComparison.Ordinal) + && method.Parameters.Length == 0) + || (string.Equals(method.Name, "set_Handle", StringComparison.Ordinal) + && ceObject is not null + && method.Parameters.Length == 1 + && method.Parameters[0].RefKind == RefKind.None + && SymbolEqualityComparer.Default.Equals(method.Parameters[0].Type, ceObject))); } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaContractTypes.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaContractTypes.cs index 1370cd95..2a23ffac 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaContractTypes.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaContractTypes.cs @@ -59,8 +59,8 @@ internal static class LuaContractTypes public static bool Is(ITypeSymbol type, INamedTypeSymbol? expected) { return expected is not null - && type is INamedTypeSymbol named - && SymbolEqualityComparer.Default.Equals(named.OriginalDefinition, expected); + && type is INamedTypeSymbol named + && SymbolEqualityComparer.Default.Equals(named.OriginalDefinition, expected); } /// @@ -70,8 +70,8 @@ public static bool Is(ITypeSymbol type, INamedTypeSymbol? expected) public static bool IsLookAlike(ITypeSymbol type, INamedTypeSymbol? expected, string metadataName) { return type is INamedTypeSymbol named - && !Is(type, expected) - && HasMetadataName(named.OriginalDefinition, metadataName); + && !Is(type, expected) + && HasMetadataName(named.OriginalDefinition, metadataName); } /// Whether a top-level has the full metadata name . @@ -114,6 +114,6 @@ public static bool HasMetadataName(INamedTypeSymbol type, string metadataName) private static bool NameEquals(string name, string metadataName, int start, int end) { return name.Length == end - start - && string.CompareOrdinal(name, 0, metadataName, start, name.Length) == 0; + && string.CompareOrdinal(name, 0, metadataName, start, name.Length) == 0; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaFunctionShape.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaFunctionShape.cs index 556cf5b3..ff76412a 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaFunctionShape.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaFunctionShape.cs @@ -205,8 +205,8 @@ private static LuaFunctionShapeIssues AddRequiredArgument(Compilation? compilati INamedTypeSymbol? luaMarshallerContract, ImmutableArray.Builder builder) { if (!LuaMarshallerResolver.TryResolve(compilation, method.ContainingType, parameter.Type, - parameter.GetAttributes(), luaMarshallerAttribute, luaMarshallerContract, - out LuaCustomMarshallerModel? customMarshaller, out _)) + parameter.GetAttributes(), luaMarshallerAttribute, luaMarshallerContract, + out LuaCustomMarshallerModel? customMarshaller, out _)) { return LuaFunctionShapeIssues.UnsupportedParameterType; } @@ -255,9 +255,9 @@ private static LuaFunctionShapeIssues InspectReturn(Compilation? compilation, IM } if (!LuaMarshallerResolver.TryResolve(compilation, method.ContainingType, method.ReturnType, - method.GetReturnTypeAttributes(), luaMarshallerAttribute, luaMarshallerContract, - out returnMarshaller, out _) - || (returnMarshaller is not null && method.ReturnType.IsRefLikeType)) + method.GetReturnTypeAttributes(), luaMarshallerAttribute, luaMarshallerContract, + out returnMarshaller, out _) + || (returnMarshaller is not null && method.ReturnType.IsRefLikeType)) { return LuaFunctionShapeIssues.UnsupportedReturnType; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaGlobalShape.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaGlobalShape.cs index 2864efbb..e6bb03d1 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaGlobalShape.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaGlobalShape.cs @@ -193,7 +193,7 @@ private static LuaGlobalShapeIssues InspectReturn(Compilation? compilation, IMet } if (LuaContractTypes.IsLookAlike(method.ReturnType, contracts.LuaOperationStatus, - LuaContractTypes.LuaOperationStatusMetadataName)) + LuaContractTypes.LuaOperationStatusMetadataName)) { return LuaGlobalShapeIssues.LookAlikeContractType; } @@ -239,9 +239,9 @@ private static LuaGlobalShapeIssues InspectThrowingReturn(Compilation? compilati } if (!LuaMarshallerResolver.TryResolve(compilation, method.ContainingType, method.ReturnType, - method.GetReturnTypeAttributes(), contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, - out returnMarshaller, out _) - || (returnMarshaller is not null && method.ReturnType.IsRefLikeType)) + method.GetReturnTypeAttributes(), contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, + out returnMarshaller, out _) + || (returnMarshaller is not null && method.ReturnType.IsRefLikeType)) { return LuaGlobalShapeIssues.UnsupportedReturnType; } @@ -252,7 +252,7 @@ private static LuaGlobalShapeIssues InspectThrowingReturn(Compilation? compilati } if (!LuaValueKindMapper.TryMap(method.ReturnType, out LuaValueKind kind, out returnIsNullable) || - !LuaValueKinds.CanBeResult(kind)) + !LuaValueKinds.CanBeResult(kind)) { return LuaGlobalShapeIssues.UnsupportedReturnType; } @@ -429,9 +429,9 @@ private LuaGlobalShapeIssues AddOutResult(IParameterSymbol parameter) } if (!LuaMarshallerResolver.TryResolve(compilation, bindingType, parameter.Type, parameter.GetAttributes(), - contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, - out LuaCustomMarshallerModel? customMarshaller, out _) - || (customMarshaller is not null && parameter.Type.IsRefLikeType)) + contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, + out LuaCustomMarshallerModel? customMarshaller, out _) + || (customMarshaller is not null && parameter.Type.IsRefLikeType)) { return issues | LuaGlobalShapeIssues.UnsupportedResultType; } @@ -443,7 +443,7 @@ private LuaGlobalShapeIssues AddOutResult(IParameterSymbol parameter) } if (!LuaValueKindMapper.TryMap(parameter.Type, out LuaValueKind kind, out bool isNullable) || - !LuaValueKinds.CanBeResult(kind)) + !LuaValueKinds.CanBeResult(kind)) { return issues | LuaGlobalShapeIssues.UnsupportedResultType; } @@ -457,8 +457,8 @@ private LuaGlobalShapeIssues AddCopyOutResult(ImmutableArray p { LuaGlobalShapeIssues issues = EnterResult(false); if (index + 1 >= parameters.Length - || parameters[index + 1] is - not { RefKind: RefKind.Out, Type.SpecialType: SpecialType.System_Int32 } written) + || parameters[index + 1] is + not { RefKind: RefKind.Out, Type.SpecialType: SpecialType.System_Int32 } written) { return issues | LuaGlobalShapeIssues.UnsupportedResultType; } @@ -482,8 +482,8 @@ private LuaGlobalShapeIssues AddVariadicResult(ImmutableArray HasVariadicResult = true; if (index + 1 >= parameters.Length - || parameters[index + 1] is - not { RefKind: RefKind.Out, Type.SpecialType: SpecialType.System_Int32 } count) + || parameters[index + 1] is + not { RefKind: RefKind.Out, Type.SpecialType: SpecialType.System_Int32 } count) { return issues | LuaGlobalShapeIssues.UnsupportedResultType; } @@ -491,7 +491,7 @@ private LuaGlobalShapeIssues AddVariadicResult(ImmutableArray IParameterSymbol values = parameters[index]; index++; if (!LuaValueKindMapper.TryMap(element, out LuaValueKind kind, out _) - || !LuaValueKinds.CanBeVariadicElement(kind)) + || !LuaValueKinds.CanBeVariadicElement(kind)) { return issues | LuaGlobalShapeIssues.UnsupportedVariadicElement; } @@ -541,8 +541,8 @@ private LuaGlobalShapeIssues AddArgument(IParameterSymbol parameter, int index) } if (!LuaMarshallerResolver.TryResolve(compilation, bindingType, parameter.Type, parameter.GetAttributes(), - contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, - out LuaCustomMarshallerModel? customMarshaller, out _)) + contracts.LuaMarshallerAttribute, contracts.LuaMarshallerContract, + out LuaCustomMarshallerModel? customMarshaller, out _)) { return issues | LuaGlobalShapeIssues.UnsupportedParameterType; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaMarshallerResolver.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaMarshallerResolver.cs index fe7cd52d..b866c2d5 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaMarshallerResolver.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaMarshallerResolver.cs @@ -57,7 +57,7 @@ public static bool TryResolve(Compilation? compilation, INamedTypeSymbol binding } if (!Implements(type, marshallerContract, valueType) - || !HasCallableStaticContract(compilation, bindingType, type, marshallerContract, valueType)) + || !HasCallableStaticContract(compilation, bindingType, type, marshallerContract, valueType)) { return false; } @@ -74,7 +74,7 @@ private static bool Implements(INamedTypeSymbol candidate, INamedTypeSymbol cont foreach (INamedTypeSymbol implementation in candidate.AllInterfaces) { if (!SymbolEqualityComparer.Default.Equals(implementation.OriginalDefinition, contract) - || implementation.TypeArguments.Length != 1) + || implementation.TypeArguments.Length != 1) { continue; } @@ -101,7 +101,7 @@ private static bool HasCallableStaticContract(Compilation? compilation, INamedTy INamedTypeSymbol closedContract = contract.Construct(valueType); return HasCallableStaticMethod(compilation, bindingType, candidate, closedContract, "Push") - && HasCallableStaticMethod(compilation, bindingType, candidate, closedContract, "TryRead"); + && HasCallableStaticMethod(compilation, bindingType, candidate, closedContract, "TryRead"); } private static bool HasCallableStaticMethod(Compilation? compilation, INamedTypeSymbol bindingType, @@ -125,12 +125,12 @@ private static bool HasCallableStaticMethod(Compilation? compilation, INamedType foreach (ISymbol member in candidate.GetMembers(name)) { if (member is not IMethodSymbol method - || method.MethodKind != MethodKind.Ordinary - || !method.IsStatic - || method.IsAbstract - || method.Arity != 0 - || (compilation is not null && !compilation.IsSymbolAccessibleWithin(method, bindingType)) - || !HasMatchingSignature(method, required)) + || method.MethodKind != MethodKind.Ordinary + || !method.IsStatic + || method.IsAbstract + || method.Arity != 0 + || (compilation is not null && !compilation.IsSymbolAccessibleWithin(method, bindingType)) + || !HasMatchingSignature(method, required)) { continue; } @@ -144,8 +144,8 @@ private static bool HasCallableStaticMethod(Compilation? compilation, INamedType private static bool HasMatchingSignature(IMethodSymbol candidate, IMethodSymbol required) { if (candidate.ReturnsVoid != required.ReturnsVoid - || !SymbolEqualityComparer.Default.Equals(candidate.ReturnType, required.ReturnType) - || candidate.Parameters.Length != required.Parameters.Length) + || !SymbolEqualityComparer.Default.Equals(candidate.ReturnType, required.ReturnType) + || candidate.Parameters.Length != required.Parameters.Length) { return false; } @@ -155,7 +155,7 @@ private static bool HasMatchingSignature(IMethodSymbol candidate, IMethodSymbol IParameterSymbol actual = candidate.Parameters[i]; IParameterSymbol expected = required.Parameters[i]; if (actual.RefKind != expected.RefKind - || !SymbolEqualityComparer.Default.Equals(actual.Type, expected.Type)) + || !SymbolEqualityComparer.Default.Equals(actual.Type, expected.Type)) { return false; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaValueKindMapper.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaValueKindMapper.cs index d88a1bf1..61f8a1c7 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaValueKindMapper.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaBindings/Parsing/LuaValueKindMapper.cs @@ -111,9 +111,9 @@ public static LuaOptionalUse ClassifyOptional(ITypeSymbol type, INamedTypeSymbol public static bool IsSpanOfOther(ITypeSymbol type, [NotNullWhen(true)] out ITypeSymbol? element) { if (type is INamedTypeSymbol { Arity: 1, ContainingType: null } named - && string.Equals(named.Name, "Span", StringComparison.Ordinal) - && named.ContainingNamespace is { Name: "System", ContainingNamespace.IsGlobalNamespace: true } - && named.TypeArguments[0].SpecialType != SpecialType.System_Byte) + && string.Equals(named.Name, "Span", StringComparison.Ordinal) + && named.ContainingNamespace is { Name: "System", ContainingNamespace.IsGlobalNamespace: true } + && named.TypeArguments[0].SpecialType != SpecialType.System_Byte) { element = named.TypeArguments[0]; return true; @@ -144,8 +144,8 @@ public static bool IsSpanOfByte(ITypeSymbol type) private static bool IsSystemSpanOfByte(ITypeSymbol type, string name) { return type is INamedTypeSymbol { Arity: 1, ContainingType: null } named - && string.Equals(named.Name, name, StringComparison.Ordinal) - && named.TypeArguments[0].SpecialType == SpecialType.System_Byte - && named.ContainingNamespace is { Name: "System", ContainingNamespace.IsGlobalNamespace: true }; + && string.Equals(named.Name, name, StringComparison.Ordinal) + && named.TypeArguments[0].SpecialType == SpecialType.System_Byte + && named.ContainingNamespace is { Name: "System", ContainingNamespace.IsGlobalNamespace: true }; } } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallEmitter.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallEmitter.cs index 08bc4200..873f06f4 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallEmitter.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallEmitter.cs @@ -365,7 +365,7 @@ private static void WriteArgumentCount(SourceWriter writer, LuaGlobalCallModel m public static string OmittedBeforePresentMessage(string globalName, string parameterName) { return "The optional argument '" + parameterName + "' of the Lua global '" + globalName + - "' is omitted while a later optional argument is present; Lua cannot receive an argument after an absent one. Pass LuaOptional.Nil() to send nil in its place."; + "' is omitted while a later optional argument is present; Lua cannot receive an argument after an absent one. Pass LuaOptional.Nil() to send nil in its place."; } private static string UnescapedName(string name) @@ -896,7 +896,7 @@ private static void WriteThrowingCall(SourceWriter writer, LuaGlobalCallModel mo private static void WriteThrowingResult(SourceWriter writer, LuaGlobalCallModel model) { if (!model.HasReturn) - // A void call keeps no result: the successful call already left the stack at its recorded top. + // A void call keeps no result: the successful call already left the stack at its recorded top. { return; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallModel.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallModel.cs index 039b5a12..4efdd097 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallModel.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaGlobalCallModel.cs @@ -149,15 +149,15 @@ public int RequiredResultCount /// The concrete static marshaller for the throwing-form return value. public string ReturnMarshallerTypeName => ReturnMarshaller?.MarshallerTypeName ?? - LuaValueKinds.MarshallerTypeName(ReturnKind!.Value); + LuaValueKinds.MarshallerTypeName(ReturnKind!.Value); /// The C# type spelling for the generated return and result local. public string ReturnTypeName => ReturnMarshaller?.ValueTypeName ?? - LuaValueKinds.TypeName(ReturnKind!.Value, ReturnIsNullable); + LuaValueKinds.TypeName(ReturnKind!.Value, ReturnIsNullable); /// The Lua-facing expected type for a throwing-form result failure. public string ExpectedReturnTypeName => ReturnMarshaller?.ExpectedTypeName ?? - LuaValueKinds.ExpectedResult(ReturnKind!.Value); + LuaValueKinds.ExpectedResult(ReturnKind!.Value); /// Whether the body reads the state from rather than from the runtime. public bool TakesState => StateParameterName.Length > 0; diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs index 23ce6c45..e8da28ef 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaNames.cs @@ -61,7 +61,7 @@ public static bool IsReservedWord(string name) private static bool IsIdentifierStart(char c) { - return c is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or '_'; + return c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '_'; } private static bool IsIdentifierPart(char c) diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaResultModel.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaResultModel.cs index 9368bc61..a2bf7deb 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaResultModel.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaResultModel.cs @@ -64,7 +64,7 @@ public LuaResultModel(LuaResultShape shape, LuaValueKind kind, string name, bool /// reference type (an optional result is a struct, a copy-out or variadic count is an ). /// public bool IsReferenceType => Shape == LuaResultShape.Value && - (CustomMarshaller?.IsReferenceType ?? LuaValueKinds.IsReferenceType(Kind)); + (CustomMarshaller?.IsReferenceType ?? LuaValueKinds.IsReferenceType(Kind)); /// Whether the protected call must keep every result and read the factual count. public bool IsDynamic => Shape is LuaResultShape.Optional or LuaResultShape.Variadic; diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkEmitter.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkEmitter.cs index 22edfd22..ae08b987 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkEmitter.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkEmitter.cs @@ -101,7 +101,7 @@ public static void Emit(SourceWriter writer, LuaThunkModel model) public static string WrongArgumentCountMessage(string luaName, int expected) { return "wrong number of arguments to '" + luaName + "' (" + expected.ToString(CultureInfo.InvariantCulture) + - " expected)"; + " expected)"; } /// diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkModel.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkModel.cs index 059f36e6..1d9a6209 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkModel.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/LuaEmit/LuaThunkModel.cs @@ -73,7 +73,7 @@ public int RequiredArgumentCount /// The concrete static marshaller for the return value. public string ReturnMarshallerTypeName => ReturnMarshaller?.MarshallerTypeName ?? - LuaValueKinds.MarshallerTypeName(ReturnKind!.Value); + LuaValueKinds.MarshallerTypeName(ReturnKind!.Value); /// The C# type spelling for the generated result local. public string ReturnTypeName => ReturnMarshaller?.ValueTypeName ?? LuaValueKinds.TypeName(ReturnKind!.Value, true); diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/Shapes/PluginShape.cs b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/Shapes/PluginShape.cs index 98d6924b..1dde5b55 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/Shapes/PluginShape.cs +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/Shapes/PluginShape.cs @@ -124,8 +124,8 @@ public static PluginShapeIssues Inspect( parameterlessConstructor = null; if (type.IsStatic) - // A static class is also abstract and sealed in metadata, has no base class and no instance - // constructor: one message instead of four. + // A static class is also abstract and sealed in metadata, has no base class and no instance + // constructor: one message instead of four. { return issues | PluginShapeIssues.Static; } @@ -229,8 +229,8 @@ private static bool DerivesFromPluginBase(INamedTypeSymbol type, INamedTypeSymbo for (INamedTypeSymbol? current = type.BaseType; current is not null; current = current.BaseType) { if (pluginBase is null - ? IsPluginBaseFallback(current) - : SymbolEqualityComparer.Default.Equals(current, pluginBase)) + ? IsPluginBaseFallback(current) + : SymbolEqualityComparer.Default.Equals(current, pluginBase)) { return true; } @@ -329,7 +329,7 @@ private static bool HasRequiredMembers(INamedTypeSymbol type) for (INamedTypeSymbol? current = type; current is not null; current = current.BaseType) { if (current.GetMembers().Any(static member => - member is IPropertySymbol { IsRequired: true } or IFieldSymbol { IsRequired: true })) + member is IPropertySymbol { IsRequired: true } or IFieldSymbol { IsRequired: true })) { return true; } diff --git a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/packages.lock.json b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/packages.lock.json index b52c3444..7109ba3b 100644 --- a/source-generators/CheatEngine.SDK.SourceGenerators.Shared/packages.lock.json +++ b/source-generators/CheatEngine.SDK.SourceGenerators.Shared/packages.lock.json @@ -4,9 +4,9 @@ ".NETStandard,Version=v2.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.Analyzers": { "type": "Direct", diff --git a/src/CheatEngine.SDK/CompatibilitySuppressions.xml b/src/CheatEngine.SDK/CompatibilitySuppressions.xml index 081ac12d..a77ae4cf 100644 --- a/src/CheatEngine.SDK/CompatibilitySuppressions.xml +++ b/src/CheatEngine.SDK/CompatibilitySuppressions.xml @@ -17,17 +17,14 @@ CP0002 - M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.#ctor(System.Boolean,System.Boolean) - + M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.#ctor(System.Boolean,System.Boolean) lib/net10.0/CheatEngine.SDK.Engine.dll lib/net10.0/CheatEngine.SDK.Engine.dll true CP0002 - - M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.Deconstruct(System.Boolean@,System.Boolean@) - + M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.Deconstruct(System.Boolean@,System.Boolean@) lib/net10.0/CheatEngine.SDK.Engine.dll lib/net10.0/CheatEngine.SDK.Engine.dll true @@ -41,8 +38,7 @@ CP0002 - M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.set_UseHostSymbolTable(System.Boolean) - + M:CheatEngine.SDK.Engine.Inspection.AddressResolutionOptions.set_UseHostSymbolTable(System.Boolean) lib/net10.0/CheatEngine.SDK.Engine.dll lib/net10.0/CheatEngine.SDK.Engine.dll true diff --git a/src/CheatEngine.SDK/README.md b/src/CheatEngine.SDK/README.md index 04b786a8..4b5ecca6 100644 --- a/src/CheatEngine.SDK/README.md +++ b/src/CheatEngine.SDK/README.md @@ -128,13 +128,13 @@ graph with Native AOT. A successful probe establishes only the analysed graph an Cheat Engine plugin and says nothing about whether CE can host or unload a Native AOT artifact. **A NativeAOT publish success is never a Cheat Engine load success.** -| Profile | Status | -|-----------------------------------------------------------------------|---------------------------------| -| Historical CLR route (`MSCorEE.dll` hosting, string entry point) | Documentary only, not supported | -| Managed hostfxr route (`CESDK.CESDK.CEPluginInitialize(IntPtr, int)`) | The only supported profile | -| NativeAOT plugin DLL | Not supported | -| Classic native plugin exporting `CEPlugin_*` | Not provided by the SDK | -| x86 or ARM64 host | Not supported | +| Profile | Status | +|---|---| +| Historical CLR route (`MSCorEE.dll` hosting, string entry point) | Documentary only, not supported | +| Managed hostfxr route (`CESDK.CESDK.CEPluginInitialize(IntPtr, int)`) | The only supported profile | +| NativeAOT plugin DLL | Not supported | +| Classic native plugin exporting `CEPlugin_*` | Not provided by the SDK | +| x86 or ARM64 host | Not supported | Cheat Engine's native loader removes a plugin with `FreeLibrary`, diff --git a/src/CheatEngine.SDK/packages.lock.json b/src/CheatEngine.SDK/packages.lock.json index 79b82719..394ebff1 100644 --- a/src/CheatEngine.SDK/packages.lock.json +++ b/src/CheatEngine.SDK/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.BannedApiAnalyzers": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Abi.Tests/FieldLayout/FieldLayoutContractTests.cs b/tests/CheatEngine.SDK.Abi.Tests/FieldLayout/FieldLayoutContractTests.cs index f41c44be..d34418e6 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/FieldLayout/FieldLayoutContractTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/FieldLayout/FieldLayoutContractTests.cs @@ -60,7 +60,7 @@ public void Every_layout_row_names_an_existing_field() stale.Add($"{row.TypeFullName}.{row.FieldName} (duplicate)"); } else if (!structures.TryGetValue(row.TypeFullName, out Type? structure) || - structure.GetField(row.FieldName, FieldLayoutGate.InstanceFields) is null) + structure.GetField(row.FieldName, FieldLayoutGate.InstanceFields) is null) { stale.Add($"{row.TypeFullName}.{row.FieldName}"); } @@ -251,14 +251,14 @@ private static FieldInfo Field(FieldLayoutRow row) { Type structure = AbiStructures.AbiAssembly.GetType(row.TypeFullName, true, false)!; return structure.GetField(row.FieldName, FieldLayoutGate.InstanceFields) - ?? throw new InvalidOperationException($"{row.TypeFullName} has no field {row.FieldName}."); + ?? throw new InvalidOperationException($"{row.TypeFullName} has no field {row.FieldName}."); } private static void AssertSameOffset(string fieldName, int addressOfOffset) where T : unmanaged { FieldInfo field = typeof(T).GetField(fieldName, FieldLayoutGate.InstanceFields) - ?? throw new InvalidOperationException($"{typeof(T).Name} has no field {fieldName}."); + ?? throw new InvalidOperationException($"{typeof(T).Name} has no field {fieldName}."); Assert.Equal(addressOfOffset, FieldLayoutGate.OffsetOf(field)); } diff --git a/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureContractTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureContractTests.cs index a9c0ecde..ee6b1dd6 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureContractTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureContractTests.cs @@ -58,8 +58,8 @@ public void Header_derived_classic_records_have_the_fixture_x64_alignments() public void Header_and_pinned_Pascal_popup_contract_conflict_keeps_the_slot_opaque_until_a_live_canary() { FieldInfo popup = typeof(DisassemblerContextPluginInit).GetField( - nameof(DisassemblerContextPluginInit.CallbackOnPopup)) - ?? throw new InvalidOperationException("The popup callback field was not found."); + nameof(DisassemblerContextPluginInit.CallbackOnPopup)) + ?? throw new InvalidOperationException("The popup callback field was not found."); Type fieldType = popup.GetModifiedFieldType().UnderlyingSystemType; diff --git a/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureManagedComparisonTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureManagedComparisonTests.cs index 0aa3ee0c..8a011961 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureManagedComparisonTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Fixture/NativeAbiFixtureManagedComparisonTests.cs @@ -47,7 +47,7 @@ public void Native_fixture_layout_facts_match_the_managed_x64_measurements_when_ foreach (string record in comparedRecords) { if (nativeKey.StartsWith("offsetof." + record + ".", StringComparison.Ordinal) || - nativeKey.StartsWith("fieldsize." + record + ".", StringComparison.Ordinal)) + nativeKey.StartsWith("fieldsize." + record + ".", StringComparison.Ordinal)) { Assert.True(managedFacts.ContainsKey(nativeKey), $"The native fixture transcribes '{nativeKey}', which has no managed field."); diff --git a/tests/CheatEngine.SDK.Abi.Tests/Managed/PluginInitRecordTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Managed/PluginInitRecordTests.cs index 65561892..e7230545 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Managed/PluginInitRecordTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Managed/PluginInitRecordTests.cs @@ -120,7 +120,7 @@ private static Bool32 FakeGetVersion(PluginVersion* version, int size) private static Bool32 FakeEnablePlugin(ManagedExportedFunctions* exports, uint pluginId) { return exports is not null && exports->SizeOfExportedFunctions == sizeof(ManagedExportedFunctions) && - pluginId == 0xFFFF_FFF0u; + pluginId == 0xFFFF_FFF0u; } [UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])] diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsPrefixReaderTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsPrefixReaderTests.cs index 7f4f02a5..a2144537 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsPrefixReaderTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/ClassicExportedFunctionsPrefixReaderTests.cs @@ -157,14 +157,14 @@ public void TryCopy_is_all_or_nothing_between_slot_boundaries(int declaredSize) public void Prefix_distinguishes_direct_function_slots_value_cells_and_opaque_null_slots_without_invocation() { FieldInfo showMessage = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.ShowMessage)) - ?? throw new InvalidOperationException("The ShowMessage field was not found."); + ?? throw new InvalidOperationException("The ShowMessage field was not found."); FieldInfo processId = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.OpenedProcessId)) - ?? throw new InvalidOperationException("The OpenedProcessId field was not found."); + ?? throw new InvalidOperationException("The OpenedProcessId field was not found."); FieldInfo processHandle = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.OpenedProcessHandle)) ?? throw new InvalidOperationException("The OpenedProcessHandle field was not found."); FieldInfo fixMemory = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.FixMemory)) - ?? throw new InvalidOperationException("The FixMemory field was not found."); + ?? throw new InvalidOperationException("The FixMemory field was not found."); FieldInfo getAddress = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.GetAddressFromPointer)) ?? throw new InvalidOperationException("The GetAddressFromPointer field was not found."); diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs index f1c64b40..4bda49d2 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/ExportedFunctionsPrefixTests.cs @@ -91,13 +91,13 @@ public void Prefix_stops_before_the_pointer_to_pointer_hook_suffix() public void Historically_null_and_conflicting_slots_stay_opaque() { FieldInfo fixMemory = typeof(ExportedFunctionsPrefix).GetField(nameof(ExportedFunctionsPrefix.FixMemory), - BindingFlags.Instance | BindingFlags.Public) - ?? throw new InvalidOperationException("The FixMemory field was not found."); + BindingFlags.Instance | BindingFlags.Public) + ?? throw new InvalidOperationException("The FixMemory field was not found."); FieldInfo getAddressFromPointer = typeof(ExportedFunctionsPrefix).GetField( - nameof(ExportedFunctionsPrefix.GetAddressFromPointer), - BindingFlags.Instance | BindingFlags.Public) - ?? throw new InvalidOperationException( - "The GetAddressFromPointer field was not found."); + nameof(ExportedFunctionsPrefix.GetAddressFromPointer), + BindingFlags.Instance | BindingFlags.Public) + ?? throw new InvalidOperationException( + "The GetAddressFromPointer field was not found."); Type fixMemoryType = fixMemory.GetModifiedFieldType().UnderlyingSystemType; Type getAddressFromPointerType = getAddressFromPointer.GetModifiedFieldType().UnderlyingSystemType; diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/PluginType0RecordTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/PluginType0RecordTests.cs index c01091e4..e1d82fd2 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/PluginType0RecordTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/PluginType0RecordTests.cs @@ -58,6 +58,6 @@ public void PluginType0Record_fields_have_the_host_widths() private static Type TypeOf(string fieldName) { return (typeof(PluginType0Record).GetField(fieldName) - ?? throw new InvalidOperationException($"PluginType0Record has no field {fieldName}.")).FieldType; + ?? throw new InvalidOperationException($"PluginType0Record has no field {fieldName}.")).FieldType; } } diff --git a/tests/CheatEngine.SDK.Abi.Tests/Native/SelectedRecordOracleTests.cs b/tests/CheatEngine.SDK.Abi.Tests/Native/SelectedRecordOracleTests.cs index 10cfd23b..e78032da 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Native/SelectedRecordOracleTests.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Native/SelectedRecordOracleTests.cs @@ -176,7 +176,7 @@ private static FieldKind KindOf(string typeFullName, string fieldName) private static bool IsOffsetOrWidth(string violation) { return violation.Contains(": offset ", StringComparison.Ordinal) || - violation.Contains(": width ", StringComparison.Ordinal); + violation.Contains(": width ", StringComparison.Ordinal); } private static int Offset(string fieldName) @@ -192,7 +192,7 @@ private static int Width(string fieldName) private static FieldInfo FieldOf(string fieldName) { return typeof(T).GetField(fieldName, FieldLayoutGate.InstanceFields) - ?? throw new InvalidOperationException($"{typeof(T).Name} has no field {fieldName}."); + ?? throw new InvalidOperationException($"{typeof(T).Name} has no field {fieldName}."); } private static string Text(int value) diff --git a/tests/CheatEngine.SDK.Abi.Tests/Support/ClassicSlotRegistry.cs b/tests/CheatEngine.SDK.Abi.Tests/Support/ClassicSlotRegistry.cs index ec4e183c..4d727552 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Support/ClassicSlotRegistry.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Support/ClassicSlotRegistry.cs @@ -32,8 +32,8 @@ public static int MinDeclaredSize(int slot) private static JsonElement Load() { using Stream stream = typeof(ClassicSlotRegistry).Assembly.GetManifestResourceStream(ResourceName) - ?? throw new InvalidOperationException( - $"The embedded resource {ResourceName} is missing."); + ?? throw new InvalidOperationException( + $"The embedded resource {ResourceName} is missing."); using JsonDocument document = JsonDocument.Parse(stream); return document.RootElement.Clone(); } diff --git a/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutGate.cs b/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutGate.cs index 2cbc14e6..9337c54d 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutGate.cs +++ b/tests/CheatEngine.SDK.Abi.Tests/Support/FieldLayoutGate.cs @@ -95,7 +95,7 @@ public static unsafe int OffsetOf(FieldInfo field) { ArgumentNullException.ThrowIfNull(field); Type declaringType = field.DeclaringType ?? - throw new ArgumentException("A field has a declaring type.", nameof(field)); + throw new ArgumentException("A field has a declaring type.", nameof(field)); if (!declaringType.IsValueType || field.IsStatic) { throw new ArgumentException("Only instance fields of structures have a layout offset.", nameof(field)); diff --git a/tests/CheatEngine.SDK.Abi.Tests/packages.lock.json b/tests/CheatEngine.SDK.Abi.Tests/packages.lock.json index 0729acf9..bc0d6e39 100644 --- a/tests/CheatEngine.SDK.Abi.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.Abi.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.Testing.Extensions.CodeCoverage": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Architecture/LuaDirectApiBoundaryGuardTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Architecture/LuaDirectApiBoundaryGuardTests.cs index f79e04ef..99ca6888 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Architecture/LuaDirectApiBoundaryGuardTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Architecture/LuaDirectApiBoundaryGuardTests.cs @@ -429,12 +429,12 @@ private static void AddViolations(List violations, LuaDirectApiP foreach (SyntaxNode node in root.DescendantNodes()) { if (node is not InvocationExpressionSyntax invocation || - !TryGetLuaApiMemberName(invocation, aliases, hasStaticLuaApiImport, hasLuaApiNamespaceImport, - shadowedNames, out string memberName) || - !policy.TryGet(memberName, out LuaDirectApiPolicyEntry entry) || - !entry.RequiresBridge || - entry.AllowedDirectly || - IsConditionallyAllowed(entry, invocation, path)) + !TryGetLuaApiMemberName(invocation, aliases, hasStaticLuaApiImport, hasLuaApiNamespaceImport, + shadowedNames, out string memberName) || + !policy.TryGet(memberName, out LuaDirectApiPolicyEntry entry) || + !entry.RequiresBridge || + entry.AllowedDirectly || + IsConditionallyAllowed(entry, invocation, path)) { continue; } @@ -450,7 +450,7 @@ private static HashSet CollectLuaApiAliases(CompilationUnitSyntax root) foreach (SyntaxNode node in root.DescendantNodesAndSelf()) { if (node is not UsingDirectiveSyntax directive || directive.Alias is null || directive.Name is null || - !IsExactLuaApiTypeName(directive.Name.ToString())) + !IsExactLuaApiTypeName(directive.Name.ToString())) { continue; } @@ -466,8 +466,8 @@ private static bool HasStaticLuaApiImport(CompilationUnitSyntax root) foreach (SyntaxNode node in root.DescendantNodesAndSelf()) { if (node is UsingDirectiveSyntax { Name: not null } directive && - directive.StaticKeyword.RawKind != 0 && - IsExactLuaApiTypeName(directive.Name.ToString())) + directive.StaticKeyword.RawKind != 0 && + IsExactLuaApiTypeName(directive.Name.ToString())) { return true; } @@ -481,8 +481,8 @@ private static bool HasLuaApiNamespaceImport(CompilationUnitSyntax root) foreach (SyntaxNode node in root.DescendantNodesAndSelf()) { if (node is UsingDirectiveSyntax { Alias: null, Name: not null } directive && - directive.StaticKeyword.RawKind == 0 && - IsLuaApiNamespaceName(directive.Name.ToString())) + directive.StaticKeyword.RawKind == 0 && + IsLuaApiNamespaceName(directive.Name.ToString())) { return true; } @@ -527,14 +527,14 @@ private static bool TryGetLuaApiMemberName(InvocationExpressionSyntax invocation switch (invocation.Expression) { case IdentifierNameSyntax identifier when hasStaticLuaApiImport && - !shadowedNames.Contains(identifier.Identifier.ValueText): + !shadowedNames.Contains(identifier.Identifier.ValueText): memberName = identifier.Identifier.ValueText; return true; case MemberAccessExpressionSyntax { Name: IdentifierNameSyntax name } memberAccess: string typeName = memberAccess.Expression.ToString(); if (IsExactLuaApiTypeName(typeName) || aliases.Contains(typeName) || - (hasLuaApiNamespaceImport && string.Equals(typeName, "LuaApi", StringComparison.Ordinal))) + (hasLuaApiNamespaceImport && string.Equals(typeName, "LuaApi", StringComparison.Ordinal))) { memberName = name.Identifier.ValueText; return true; @@ -551,15 +551,15 @@ private static bool IsConditionallyAllowed(LuaDirectApiPolicyEntry entry, Invoca string path) { if (!entry.ConditionalDirectUse || !entry.ConditionalAllowed || - !string.Equals(entry.MemberName, "lua_pushcclosure", StringComparison.Ordinal) || - !string.Equals(path, LightCFunctionFastPathSourcePath, StringComparison.Ordinal)) + !string.Equals(entry.MemberName, "lua_pushcclosure", StringComparison.Ordinal) || + !string.Equals(path, LightCFunctionFastPathSourcePath, StringComparison.Ordinal)) { return false; } SeparatedSyntaxList arguments = invocation.ArgumentList.Arguments; if (arguments.Count != 3 || !IsIdentifier(arguments[0].Expression, "Pointer") || - !IsIntegerZero(arguments[2].Expression)) + !IsIntegerZero(arguments[2].Expression)) { return false; } @@ -567,8 +567,8 @@ private static bool IsConditionallyAllowed(LuaDirectApiPolicyEntry entry, Invoca ExpressionStatementSyntax? pushStatement = invocation.FirstAncestorOrSelf(); MethodDeclarationSyntax? method = invocation.FirstAncestorOrSelf(); if (pushStatement is null || method is null || - !string.Equals(method.Identifier.ValueText, "PushUncheckedFunction", StringComparison.Ordinal) || - method.Body is null) + !string.Equals(method.Identifier.ValueText, "PushUncheckedFunction", StringComparison.Ordinal) || + method.Body is null) { return false; } @@ -590,20 +590,20 @@ private static bool IsConditionallyAllowed(LuaDirectApiPolicyEntry entry, Invoca private static bool IsImmediateOneSlotCheckStackGuard(StatementSyntax statement) { if (statement is not IfStatementSyntax condition || - !ContainsOnlyThrow(condition.Statement) || - condition.Condition is not BinaryExpressionSyntax equals || - !equals.IsKind(SyntaxKind.EqualsExpression) || - !IsIntegerZero(equals.Right)) + !ContainsOnlyThrow(condition.Statement) || + condition.Condition is not BinaryExpressionSyntax equals || + !equals.IsKind(SyntaxKind.EqualsExpression) || + !IsIntegerZero(equals.Right)) { return false; } if (equals.Left is not InvocationExpressionSyntax - { - Expression: IdentifierNameSyntax { Identifier.ValueText: "lua_checkstack" }, - ArgumentList.Arguments: var arguments - } || arguments.Count != 2 || !IsIdentifier(arguments[0].Expression, "Pointer") || - !IsIntegerOne(arguments[1].Expression)) + { + Expression: IdentifierNameSyntax { Identifier.ValueText: "lua_checkstack" }, + ArgumentList.Arguments: var arguments + } || arguments.Count != 2 || !IsIdentifier(arguments[0].Expression, "Pointer") || + !IsIntegerOne(arguments[1].Expression)) { return false; } @@ -614,7 +614,7 @@ condition.Condition is not BinaryExpressionSyntax equals || private static bool ContainsOnlyThrow(StatementSyntax statement) { return statement is ThrowStatementSyntax || - (statement is BlockSyntax { Statements.Count: 1 } block && block.Statements[0] is ThrowStatementSyntax); + (statement is BlockSyntax { Statements.Count: 1 } block && block.Statements[0] is ThrowStatementSyntax); } private static bool IsIntegerZero(ExpressionSyntax expression) @@ -662,7 +662,7 @@ private static bool IsIntegerOne(ExpressionSyntax expression) private static bool IsIdentifier(ExpressionSyntax expression, string identifier) { return expression is IdentifierNameSyntax name && - string.Equals(name.Identifier.ValueText, identifier, StringComparison.Ordinal); + string.Equals(name.Identifier.ValueText, identifier, StringComparison.Ordinal); } private static string[] ReadProvenance(JsonElement entry) @@ -691,7 +691,7 @@ private static string GetRepositoryPath(string sourcePath) private static bool IsGeneratedPath(string repositoryPath) { return repositoryPath.Contains("/bin/", StringComparison.Ordinal) || - repositoryPath.Contains("/obj/", StringComparison.Ordinal); + repositoryPath.Contains("/obj/", StringComparison.Ordinal); } private static bool IsExactLuaApiTypeName(string typeName) diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Diagnostics/DiagnosticCatalogTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Diagnostics/DiagnosticCatalogTests.cs index 4783e4bd..a8eec0b5 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Diagnostics/DiagnosticCatalogTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Diagnostics/DiagnosticCatalogTests.cs @@ -154,9 +154,9 @@ private static bool HasRow(string tracking, DiagnosticDescriptor descriptor) { string[] cells = line.Split('|'); if (cells.Length >= 3 - && string.Equals(cells[0].Trim(), descriptor.Id, StringComparison.Ordinal) - && string.Equals(cells[1].Trim(), descriptor.Category, StringComparison.Ordinal) - && string.Equals(cells[2].Trim(), descriptor.DefaultSeverity.ToString(), StringComparison.Ordinal)) + && string.Equals(cells[0].Trim(), descriptor.Id, StringComparison.Ordinal) + && string.Equals(cells[1].Trim(), descriptor.Category, StringComparison.Ordinal) + && string.Equals(cells[2].Trim(), descriptor.DefaultSeverity.ToString(), StringComparison.Ordinal)) { return true; } diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaBindingAnalyzerTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaBindingAnalyzerTests.cs index f61b2f69..2a3e8384 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaBindingAnalyzerTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Generation/LuaBindingAnalyzerTests.cs @@ -62,32 +62,32 @@ public sealed class LuaBindingAnalyzerTests { { "valid function", ShapeUsings + - "public static partial class Functions { [LuaFunction(\"add\")] public static long Add(long a, long b) => a + b; }", + "public static partial class Functions { [LuaFunction(\"add\")] public static long Add(long a, long b) => a + b; }", true }, { "instance method", ShapeUsings + - "public partial class Functions { [LuaFunction(\"add\")] public long Add(long a, long b) => a + b; }", + "public partial class Functions { [LuaFunction(\"add\")] public long Add(long a, long b) => a + b; }", false }, { "not partial container", ShapeUsings + - "public static class Functions { [LuaFunction(\"add\")] public static long Add(long a, long b) => a + b; }", + "public static class Functions { [LuaFunction(\"add\")] public static long Add(long a, long b) => a + b; }", false }, { "invalid lua name", ShapeUsings + - "public static partial class Functions { [LuaFunction(\"end\")] public static long Add(long a, long b) => a + b; }", + "public static partial class Functions { [LuaFunction(\"end\")] public static long Add(long a, long b) => a + b; }", false }, { "valid global try form", ShapeUsings + - "public static partial class Bindings { [LuaGlobal(\"readInteger\")] public static partial bool TryReadInt32(nuint address, out int value); }", + "public static partial class Bindings { [LuaGlobal(\"readInteger\")] public static partial bool TryReadInt32(nuint address, out int value); }", true }, { "global try form returning int instead of bool", ShapeUsings + - "public static partial class Bindings { [LuaGlobal(\"readInteger\")] public static partial int TryReadInt32(nuint address, out int value); }", + "public static partial class Bindings { [LuaGlobal(\"readInteger\")] public static partial int TryReadInt32(nuint address, out int value); }", false }, { @@ -112,47 +112,47 @@ public static partial class Memory { { "optional arguments of a global", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"load\")] public static partial void Load(string path, LuaOptional merge, LuaOptional flags); }", + "public static partial class Bindings { [LuaGlobal(\"load\")] public static partial void Load(string path, LuaOptional merge, LuaOptional flags); }", true }, { "optional results of a global", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"read\")] public static partial LuaOperationStatus Read(int mode, out long first, out LuaOptional second); }", + "public static partial class Bindings { [LuaGlobal(\"read\")] public static partial LuaOperationStatus Read(int mode, out long first, out LuaOptional second); }", true }, { "variadic outcome of a global", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"seq\")] public static partial LuaOperationStatus Seq(int n, Span values, out int count); }", + "public static partial class Bindings { [LuaGlobal(\"seq\")] public static partial LuaOperationStatus Seq(int n, Span values, out int count); }", true }, { "optional parameter of a function", OptionalUsings + - "public static partial class Functions { [LuaFunction(\"f\")] public static int F(int a, LuaOptional b) => a; }", + "public static partial class Functions { [LuaFunction(\"f\")] public static int F(int a, LuaOptional b) => a; }", true }, { "optional argument before a required one", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a, int b); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a, int b); }", false }, { "required result after an optional one", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(out LuaOptional a, out int b); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(out LuaOptional a, out int b); }", false }, { "variadic pair on the try form", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(Span v, out int c); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(Span v, out int c); }", false }, { "optional nullable string", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a); }", false }, { "optional throwing return", OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial LuaOptional G(int a); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial LuaOptional G(int a); }", false } }; @@ -475,10 +475,10 @@ public static class Functions static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaBindingContainingType, StringComparison.Ordinal)); Assert.Contains(diagnostics, static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaFunction, StringComparison.Ordinal) && - d.GetMessage(CultureInfo.InvariantCulture).Contains("reserved word", StringComparison.Ordinal)); + d.GetMessage(CultureInfo.InvariantCulture).Contains("reserved word", StringComparison.Ordinal)); Assert.Contains(diagnostics, static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaFunction, StringComparison.Ordinal) && - d.GetMessage(CultureInfo.InvariantCulture).Contains("default value", StringComparison.Ordinal)); + d.GetMessage(CultureInfo.InvariantCulture).Contains("default value", StringComparison.Ordinal)); } [Fact] @@ -516,11 +516,11 @@ public static partial class Globals ImmutableArray diagnostics = await GetDiagnosticsAsync(compilation); Assert.Contains(diagnostics, static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaFunction, StringComparison.Ordinal) && - d.GetMessage(CultureInfo.InvariantCulture) - .Contains("parameter type", StringComparison.Ordinal)); + d.GetMessage(CultureInfo.InvariantCulture) + .Contains("parameter type", StringComparison.Ordinal)); Assert.Contains(diagnostics, static d => string.Equals(d.Id, DiagnosticIds.InvalidLuaGlobal, StringComparison.Ordinal) && - d.GetMessage(CultureInfo.InvariantCulture).Contains("argument type", StringComparison.Ordinal)); + d.GetMessage(CultureInfo.InvariantCulture).Contains("argument type", StringComparison.Ordinal)); } [Theory] @@ -585,7 +585,7 @@ .. diagnostics.Where(static d => public async Task Required_result_after_an_optional_result_reports_CESDK2011() { ImmutableArray diagnostics = await AnalyzeAsync(OptionalUsings + - "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(out LuaOptional a, out int b); }", + "public static partial class Bindings { [LuaGlobal(\"g\")] public static partial bool TryG(out LuaOptional a, out int b); }", true); Diagnostic diagnostic = Assert.Single(diagnostics); diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/CodeFixVerifier.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/CodeFixVerifier.cs index c0127865..ab0bfb7e 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/CodeFixVerifier.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/CodeFixVerifier.cs @@ -37,7 +37,8 @@ public static Task VerifyAsync( { CheatEngineSdkCodeFixTest test = new() { - CodeActionEquivalenceKey = equivalenceKey, NumberOfFixAllIterations = fixAllIterations + CodeActionEquivalenceKey = equivalenceKey, + NumberOfFixAllIterations = fixAllIterations }; // The default drops fixable ids from the markup of the fixed state, assuming a fix always removes them all. diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferences.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferences.cs index d681851c..503606c6 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferences.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferences.cs @@ -76,8 +76,8 @@ public static ImmutableArray FromTargetingPack() { string candidate = Path.Combine(pack, "ref", TargetFramework); if (Directory.Exists(candidate) - && TryParsePackVersion(Path.GetFileName(pack), out Version? version) - && (bestVersion is null || version > bestVersion)) + && TryParsePackVersion(Path.GetFileName(pack), out Version? version) + && (bestVersion is null || version > bestVersion)) { best = candidate; bestVersion = version; diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferencesTests.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferencesTests.cs index f3392bd5..d0653902 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferencesTests.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/LocalFrameworkReferencesTests.cs @@ -42,7 +42,7 @@ public void References_are_existing_local_files_and_include_the_core_facade() foreach (MetadataReference reference in LocalFrameworkReferences.References) { string path = Assert.IsType(reference, false).FilePath - ?? throw new InvalidOperationException("A framework reference without a file path."); + ?? throw new InvalidOperationException("A framework reference without a file path."); Assert.True(File.Exists(path), path); hasSystemRuntime |= string.Equals(Path.GetFileName(path), "System.Runtime.dll", StringComparison.OrdinalIgnoreCase); diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/RepositoryLayout.cs b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/RepositoryLayout.cs index 7b8fe539..7262e163 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/RepositoryLayout.cs +++ b/tests/CheatEngine.SDK.Analyzers.Tests/Infrastructure/RepositoryLayout.cs @@ -20,8 +20,8 @@ public static string PathOf(string relativePath) private static string FindRoot() { for (DirectoryInfo? directory = new(AppContext.BaseDirectory); - directory is not null; - directory = directory.Parent) + directory is not null; + directory = directory.Parent) { if (File.Exists(Path.Combine(directory.FullName, SolutionFileName))) { diff --git a/tests/CheatEngine.SDK.Analyzers.Tests/packages.lock.json b/tests/CheatEngine.SDK.Analyzers.Tests/packages.lock.json index b3a73fef..45f87ce0 100644 --- a/tests/CheatEngine.SDK.Analyzers.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.Analyzers.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.CSharp": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Benchmarks/BenchFunctions.cs b/tests/CheatEngine.SDK.Benchmarks/BenchFunctions.cs index 6a9ad230..89f2770b 100644 --- a/tests/CheatEngine.SDK.Benchmarks/BenchFunctions.cs +++ b/tests/CheatEngine.SDK.Benchmarks/BenchFunctions.cs @@ -6,7 +6,7 @@ namespace CheatEngine.SDK.Benchmarks; /// A generated [LuaFunction] thunk, registered once by and then called /// from a Lua loop many times inside one protected call: register once, call from Lua N times. /// -internal static class BenchFunctions +internal static partial class BenchFunctions { /// Lua: cheatengine_sdk_bench_touch(x). Returns plus one. /// The running value. diff --git a/tests/CheatEngine.SDK.Benchmarks/CallbackBenchmarks.cs b/tests/CheatEngine.SDK.Benchmarks/CallbackBenchmarks.cs index b5d0e195..f7068a7c 100644 --- a/tests/CheatEngine.SDK.Benchmarks/CallbackBenchmarks.cs +++ b/tests/CheatEngine.SDK.Benchmarks/CallbackBenchmarks.cs @@ -64,7 +64,7 @@ public void Setup() if (!defined.IsOk) { throw new InvalidOperationException("Defining cheatengine_sdk_bench_loop failed: " + - LuaError.FromStack(_l, defined)); + LuaError.FromStack(_l, defined)); } } diff --git a/tests/CheatEngine.SDK.Benchmarks/EngineApiIncrementalBenchmarks.cs b/tests/CheatEngine.SDK.Benchmarks/EngineApiIncrementalBenchmarks.cs index dc3560c6..a2944adf 100644 --- a/tests/CheatEngine.SDK.Benchmarks/EngineApiIncrementalBenchmarks.cs +++ b/tests/CheatEngine.SDK.Benchmarks/EngineApiIncrementalBenchmarks.cs @@ -183,7 +183,7 @@ private BenchmarkAdditionalText Second() private BenchmarkAdditionalText EditedFirst() { return _editedFirstSpec ?? - throw new InvalidOperationException("Benchmark setup did not create the edited spec."); + throw new InvalidOperationException("Benchmark setup did not create the edited spec."); } private GeneratorDriver WarmDriver() diff --git a/tests/CheatEngine.SDK.Benchmarks/GlobalCallBenchmarks.cs b/tests/CheatEngine.SDK.Benchmarks/GlobalCallBenchmarks.cs index 394c262d..b239430e 100644 --- a/tests/CheatEngine.SDK.Benchmarks/GlobalCallBenchmarks.cs +++ b/tests/CheatEngine.SDK.Benchmarks/GlobalCallBenchmarks.cs @@ -37,7 +37,7 @@ public void Setup() if (!defined.IsOk) { throw new InvalidOperationException("Defining cheatengine_sdk_bench_add failed: " + - LuaError.FromStack(l, defined)); + LuaError.FromStack(l, defined)); } } diff --git a/tests/CheatEngine.SDK.Benchmarks/MemoryScalarBenchmarks.cs b/tests/CheatEngine.SDK.Benchmarks/MemoryScalarBenchmarks.cs index 815c97b1..d3c4fedc 100644 --- a/tests/CheatEngine.SDK.Benchmarks/MemoryScalarBenchmarks.cs +++ b/tests/CheatEngine.SDK.Benchmarks/MemoryScalarBenchmarks.cs @@ -81,7 +81,7 @@ public void Setup() if (!defined.IsOk) { throw new InvalidOperationException("Defining scalar-memory fixture globals failed: " + - LuaError.FromStack(state, defined)); + LuaError.FromStack(state, defined)); } if (!TargetMemory.TryWriteInt32(Address32, -42, out _)) @@ -95,15 +95,15 @@ public void Setup() } if (!HostMemory.TryWriteInt32(HostAddress32, -42, out _) || - !HostMemory.TryWriteInt64(HostAddress64, 0x1_0000_0000L, out _)) + !HostMemory.TryWriteInt64(HostAddress64, 0x1_0000_0000L, out _)) { throw new InvalidOperationException("Warming local scalar writes failed."); } if (!TargetMemory.TryReadInt32(Address32, out _, out _) || - !TargetMemory.TryReadInt64(Address64, out _, out _) || - !HostMemory.TryReadInt32(HostAddress32, out _, out _) || - !HostMemory.TryReadInt64(HostAddress64, out _, out _)) + !TargetMemory.TryReadInt64(Address64, out _, out _) || + !HostMemory.TryReadInt32(HostAddress32, out _, out _) || + !HostMemory.TryReadInt64(HostAddress64, out _, out _)) { throw new InvalidOperationException("Warming scalar reads failed."); } diff --git a/tests/CheatEngine.SDK.Benchmarks/Support/FakeHostRuntime.cs b/tests/CheatEngine.SDK.Benchmarks/Support/FakeHostRuntime.cs index 71d2a5f9..352cea17 100644 --- a/tests/CheatEngine.SDK.Benchmarks/Support/FakeHostRuntime.cs +++ b/tests/CheatEngine.SDK.Benchmarks/Support/FakeHostRuntime.cs @@ -72,7 +72,7 @@ private static void InstallMetatable(LuaState state) if (!status.IsOk) { throw new InvalidOperationException("Installing the fake host metatable failed: " + - LuaError.FromStack(state, status)); + LuaError.FromStack(state, status)); } state.RawSetPointer(LuaState.RegistryIndex, s_metatableKey); diff --git a/tests/CheatEngine.SDK.Benchmarks/packages.lock.json b/tests/CheatEngine.SDK.Benchmarks/packages.lock.json index 9614c691..91743cf6 100644 --- a/tests/CheatEngine.SDK.Benchmarks/packages.lock.json +++ b/tests/CheatEngine.SDK.Benchmarks/packages.lock.json @@ -22,9 +22,9 @@ }, "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.CSharp": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListExitTests.cs b/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListExitTests.cs index ee5381d5..3fba769c 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListExitTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/AddressList/AddressListExitTests.cs @@ -124,11 +124,11 @@ public void Mutation_during_a_table_load_is_refused() List mutations = []; List activations = []; using (FakeHost.InstallReentrantHook(host.State, "table_script", () => - { - mutations.Add(AddressListMutations.Delete(new MemoryRecordId(1))); - mutations.Add(AddressListMutations.SetParent(new MemoryRecordId(1), new MemoryRecordId(2))); - activations.Add(AddressListMutations.SetActive(new MemoryRecordId(1), true)); - })) + { + mutations.Add(AddressListMutations.Delete(new MemoryRecordId(1))); + mutations.Add(AddressListMutations.SetParent(new MemoryRecordId(1), new MemoryRecordId(2))); + activations.Add(AddressListMutations.SetActive(new MemoryRecordId(1), true)); + })) { host.Execute("loadTable = function(path, merge) table_script() end"); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Allocation/AllocatedRegionTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Allocation/AllocatedRegionTests.cs index 1adecf61..e7669a44 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Allocation/AllocatedRegionTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Allocation/AllocatedRegionTests.cs @@ -14,7 +14,10 @@ public sealed class AllocatedRegionTests [Fact] public void Dispose_releases_the_original_target_address_and_size_exactly_once() { - AllocationOperationsFake operations = new() { AllocatedAddress = new Address(0x7FF6_3000_0000) }; + AllocationOperationsFake operations = new() + { + AllocatedAddress = new Address(0x7FF6_3000_0000) + }; AllocatedRegion region = Allocate(operations, 12288); region.Dispose(); @@ -31,7 +34,10 @@ public void Dispose_releases_the_original_target_address_and_size_exactly_once() [Fact] public void Dispose_when_CE_reports_failure_is_no_throw_and_consumes_ownership() { - AllocationOperationsFake operations = new() { DeallocationResult = false }; + AllocationOperationsFake operations = new() + { + DeallocationResult = false + }; AllocatedRegion region = Allocate(operations, 4096); region.Dispose(); @@ -44,7 +50,10 @@ public void Dispose_when_CE_reports_failure_is_no_throw_and_consumes_ownership() [Fact] public void Release_when_CE_reports_failure_throws_the_expected_failure_and_never_retries() { - AllocationOperationsFake operations = new() { DeallocationResult = false }; + AllocationOperationsFake operations = new() + { + DeallocationResult = false + }; AllocatedRegion region = Allocate(operations, 4096); EngineOperationFailedException exception = Assert.Throws(region.Release); @@ -60,7 +69,10 @@ public void Release_when_CE_reports_failure_throws_the_expected_failure_and_neve public void Release_when_the_protected_lua_call_fails_preserves_the_failure_and_consumes_ownership() { EngineLuaException failure = new("TargetMemoryDeallocate", LuaStatus.RuntimeError); - AllocationOperationsFake operations = new() { DeallocationException = failure }; + AllocationOperationsFake operations = new() + { + DeallocationException = failure + }; AllocatedRegion region = Allocate(operations, 4096); EngineLuaException thrown = Assert.Throws(region.Release); @@ -75,7 +87,10 @@ public void Release_when_the_protected_lua_call_fails_preserves_the_failure_and_ public void Release_when_the_required_global_is_unavailable_preserves_the_distinct_failure() { EngineGlobalUnavailableException failure = new("TargetMemoryDeallocate"); - AllocationOperationsFake operations = new() { DeallocationException = failure }; + AllocationOperationsFake operations = new() + { + DeallocationException = failure + }; AllocatedRegion region = Allocate(operations, 4096); EngineGlobalUnavailableException thrown = Assert.Throws(region.Release); @@ -91,7 +106,10 @@ public void Release_when_the_binding_contract_fails_preserves_the_failure_and_co { EngineBindingException failure = new("TargetMemoryDeallocate", "the generated binding returned an incompatible result"); - AllocationOperationsFake operations = new() { DeallocationException = failure }; + AllocationOperationsFake operations = new() + { + DeallocationException = failure + }; AllocatedRegion region = Allocate(operations, 4096); EngineBindingException thrown = Assert.Throws(region.Release); @@ -106,7 +124,10 @@ public void Release_when_the_result_cannot_be_marshalled_preserves_the_failure_a { EngineMarshallingException failure = new("TargetMemoryDeallocate", EngineMarshallingDirection.Result, "a boolean", "a table"); - AllocationOperationsFake operations = new() { DeallocationException = failure }; + AllocationOperationsFake operations = new() + { + DeallocationException = failure + }; AllocatedRegion region = Allocate(operations, 4096); EngineMarshallingException thrown = Assert.Throws(region.Release); @@ -137,7 +158,10 @@ public void Dispose_when_the_binding_fails_is_no_throw_and_consumes_ownership() public void Dispose_when_an_EngineException_occurs_preserves_the_structured_failure_kind_and_consumes_ownership() { EngineException failure = new EngineLuaException("TargetMemoryDeallocate", LuaStatus.RuntimeError); - AllocationOperationsFake operations = new() { DeallocationException = failure }; + AllocationOperationsFake operations = new() + { + DeallocationException = failure + }; AllocatedRegion region = Allocate(operations, 4096); region.Dispose(); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Allocation/LuaTargetMemoryAllocationOperationsTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Allocation/LuaTargetMemoryAllocationOperationsTests.cs index af70f6e6..7b1238b5 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Allocation/LuaTargetMemoryAllocationOperationsTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Allocation/LuaTargetMemoryAllocationOperationsTests.cs @@ -424,7 +424,7 @@ function deAlloc(address, size) private static void InstallCurrentTarget(LuaState state) { EngineTest.Run(state, Encoding.UTF8.GetBytes("function getOpenedProcessID() return " + - Environment.ProcessId + " end")); + Environment.ProcessId + " end")); EngineTest.Run(state, FakeHost.LocalTargetBackendChunk); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Allocation/TargetMemoryAllocatorTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Allocation/TargetMemoryAllocatorTests.cs index ef5838ef..dc5002fc 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Allocation/TargetMemoryAllocatorTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Allocation/TargetMemoryAllocatorTests.cs @@ -40,7 +40,10 @@ public void Allocate_when_owner_publication_fails_compensates_once_and_exposes_t [Fact] public void Allocate_when_owner_publication_and_compensation_fail_reports_an_unconfirmed_effect_without_retrying() { - AllocationOperationsFake operations = new() { DeallocationResult = false }; + AllocationOperationsFake operations = new() + { + DeallocationResult = false + }; TargetMemoryAllocator allocator = new(operations); EngineResourceHandoffException exception = Assert.Throws(() => @@ -59,7 +62,10 @@ public void Allocate_when_owner_publication_and_compensation_raise_keeps_the_primary_cause_and_marks_the_effect_unknown() { EngineLuaException cleanupFailure = new("TargetMemoryDeallocate", LuaStatus.RuntimeError); - AllocationOperationsFake operations = new() { DeallocationException = cleanupFailure }; + AllocationOperationsFake operations = new() + { + DeallocationException = cleanupFailure + }; TargetMemoryAllocator allocator = new(operations); InvalidOperationException cause = new("injected region publication failure"); @@ -97,7 +103,10 @@ public void Allocate_when_owner_publication_observes_a_replacement_target_refuse [Fact] public void Allocate_on_success_returns_an_owned_region_and_forwards_the_full_request() { - AllocationOperationsFake operations = new() { AllocatedAddress = new Address(0x7FF6_1234_0000) }; + AllocationOperationsFake operations = new() + { + AllocatedAddress = new Address(0x7FF6_1234_0000) + }; TargetMemoryAllocator allocator = new(operations); TargetAllocationRequest request = new(new TargetAllocationSize(8192), new Address(0x7FF6_1200_0000), MemoryProtection.ExecuteReadWrite); @@ -113,7 +122,11 @@ public void Allocate_on_success_returns_an_owned_region_and_forwards_the_full_re [Fact] public void Allocate_when_CE_reports_expected_failure_throws_the_stable_expected_failure() { - AllocationOperationsFake operations = new() { AllocationResult = false, AllocatedAddress = Address.Zero }; + AllocationOperationsFake operations = new() + { + AllocationResult = false, + AllocatedAddress = Address.Zero + }; TargetMemoryAllocator allocator = new(operations); EngineOperationFailedException exception = Assert.Throws(() => @@ -127,7 +140,10 @@ public void Allocate_when_CE_reports_expected_failure_throws_the_stable_expected [Fact] public void Allocate_when_CE_reports_success_without_an_address_preserves_the_unknown_effect_diagnostic() { - AllocationOperationsFake operations = new() { AllocatedAddress = Address.Zero }; + AllocationOperationsFake operations = new() + { + AllocatedAddress = Address.Zero + }; TargetMemoryAllocator allocator = new(operations); EngineResourceHandoffException exception = Assert.Throws(() => @@ -144,7 +160,11 @@ public void Allocate_when_CE_reports_success_without_an_address_preserves_the_un public void Allocate_when_CE_reports_failure_with_an_address_throws_marshalling() { AllocationOperationsFake operations = - new() { AllocationResult = false, AllocatedAddress = new Address(0x1234) }; + new() + { + AllocationResult = false, + AllocatedAddress = new Address(0x1234) + }; TargetMemoryAllocator allocator = new(operations); EngineMarshallingException exception = Assert.Throws(() => @@ -159,7 +179,10 @@ public void Allocate_when_the_binding_fails_preserves_the_binding_exception() { EngineBindingException failure = new("TargetMemoryAllocate", "the generated binding returned an incompatible result"); - AllocationOperationsFake operations = new() { AllocationException = failure }; + AllocationOperationsFake operations = new() + { + AllocationException = failure + }; TargetMemoryAllocator allocator = new(operations); EngineBindingException thrown = Assert.Throws(() => @@ -172,7 +195,10 @@ public void Allocate_when_the_binding_fails_preserves_the_binding_exception() public void Allocate_when_the_required_global_is_unavailable_preserves_that_distinct_failure() { EngineGlobalUnavailableException failure = new("TargetMemoryAllocate"); - AllocationOperationsFake operations = new() { AllocationException = failure }; + AllocationOperationsFake operations = new() + { + AllocationException = failure + }; TargetMemoryAllocator allocator = new(operations); EngineGlobalUnavailableException thrown = Assert.Throws(() => @@ -186,7 +212,10 @@ public void Allocate_when_the_required_global_is_unavailable_preserves_that_dist public void Allocate_when_the_protected_lua_call_fails_preserves_the_EngineLuaException() { EngineLuaException failure = new("TargetMemoryAllocate", LuaStatus.RuntimeError); - AllocationOperationsFake operations = new() { AllocationException = failure }; + AllocationOperationsFake operations = new() + { + AllocationException = failure + }; TargetMemoryAllocator allocator = new(operations); EngineLuaException thrown = Assert.Throws(() => @@ -253,7 +282,10 @@ public void Allocate_with_a_target_bound_boundary_failure_throws_its_stable_publ [Fact] public void ReleaseWithOutcome_adapts_the_legacy_bool_seam_and_consumes_ownership() { - AllocationOperationsFake operations = new() { DeallocationResult = false }; + AllocationOperationsFake operations = new() + { + DeallocationResult = false + }; TargetMemoryAllocator allocator = new(operations); AllocatedRegion region = allocator.Allocate(new TargetAllocationRequest(new TargetAllocationSize(4096))); @@ -307,7 +339,10 @@ method.Name is not (nameof(ITargetMemoryAllocationOperations.TryAllocate) or [Fact] public void TryAllocate_success_returns_an_owner_with_its_incarnation_and_runtime_origin() { - AllocationOperationsFake operations = new() { AllocatedAddress = new Address(0x7FF6_1234_0000) }; + AllocationOperationsFake operations = new() + { + AllocatedAddress = new Address(0x7FF6_1234_0000) + }; TargetMemoryAllocator allocator = new(operations); TargetAllocationRequest request = new(new TargetAllocationSize(8192)); @@ -335,7 +370,11 @@ public void TryAllocate_success_returns_an_owner_with_its_incarnation_and_runtim [Fact] public void TryAllocate_expected_failure_reports_not_applied_without_an_owner() { - AllocationOperationsFake operations = new() { AllocationResult = false, AllocatedAddress = Address.Zero }; + AllocationOperationsFake operations = new() + { + AllocationResult = false, + AllocatedAddress = Address.Zero + }; TargetMemoryAllocator allocator = new(operations); TargetAllocationAcquireOutcome outcome = @@ -402,7 +441,8 @@ public void TryAllocate_publication_and_compensation_failure_keeps_the_allocated { AllocationOperationsFake operations = new() { - AllocatedAddress = new Address(0x7FF6_5555_0000), DeallocationResult = false + AllocatedAddress = new Address(0x7FF6_5555_0000), + DeallocationResult = false }; TargetMemoryAllocator allocator = new(operations); @@ -444,7 +484,10 @@ public void TryAllocate_with_only_the_compatibility_seam_refuses_without_an_effe [Fact] public void TryAllocate_success_without_an_address_is_a_marshalling_failure_with_unknown_effect() { - AllocationOperationsFake operations = new() { AllocatedAddress = Address.Zero }; + AllocationOperationsFake operations = new() + { + AllocatedAddress = Address.Zero + }; TargetMemoryAllocator allocator = new(operations); TargetAllocationAcquireOutcome outcome = @@ -463,7 +506,8 @@ public void TryAllocate_failure_that_still_carries_an_address_keeps_it_and_repor { AllocationOperationsFake operations = new() { - AllocationResult = false, AllocatedAddress = new Address(0x1234) + AllocationResult = false, + AllocatedAddress = new Address(0x1234) }; TargetMemoryAllocator allocator = new(operations); @@ -522,7 +566,10 @@ public void TryAllocate_turns_a_binding_exception_into_an_outcome_without_parsin EngineFailureKind.BindingFailure => new EngineBindingException("TargetMemoryAllocate", "incompatible"), _ => new EngineMarshallingException("TargetMemoryAllocate", EngineMarshallingDirection.Result, "a", "b") }; - AllocationOperationsFake operations = new() { AllocationException = failure }; + AllocationOperationsFake operations = new() + { + AllocationException = failure + }; TargetMemoryAllocator allocator = new(operations); TargetAllocationAcquireOutcome outcome = diff --git a/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerDisableInfoSnapshotTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerDisableInfoSnapshotTests.cs index 64dcc917..e1a2bb3c 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerDisableInfoSnapshotTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Assembly/AutoAssemblerDisableInfoSnapshotTests.cs @@ -146,7 +146,11 @@ public void Snapshot_truncates_at_the_entry_and_name_limits() symbols = { short = 1, far_too_long_a_name = 2 }, } """u8); - AutoAssemblerOptions options = new() { MaxDisableInfoEntries = 2, MaxDisableInfoNameBytes = 8 }; + AutoAssemblerOptions options = new() + { + MaxDisableInfoEntries = 2, + MaxDisableInfoNameBytes = 8 + }; AutoAssemblerApplyOutcome outcome = AutoAssemblerPatcher.TryApplyWithOutcome("success", options, out AutoAssemblerPatch? patch); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Assembly/InstructionOperationsTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Assembly/InstructionOperationsTests.cs index 57332b70..07ca4452 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Assembly/InstructionOperationsTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Assembly/InstructionOperationsTests.cs @@ -420,9 +420,9 @@ public void assemble_reports_a_target_change_after_the_effect_without_copying_by InstallInstructionGlobals(scope.State); InstructionTargetProfile targetProfile = Observe(scope.State); EngineTest.Run(scope.State, Encoding.UTF8.GetBytes("instruction_assemble_behavior = \"target-change\"\n" + - "instruction_assemble_next_process_id = " + - selectionAfterEffect.ToString(CultureInfo - .InvariantCulture))); + "instruction_assemble_next_process_id = " + + selectionAfterEffect.ToString(CultureInfo + .InvariantCulture))); Span destination = stackalloc byte[1]; destination[0] = 0xA5; diff --git a/tests/CheatEngine.SDK.Engine.Tests/Inspection/EngineInspectionTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Inspection/EngineInspectionTests.cs index 9985a1d8..df4752eb 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Inspection/EngineInspectionTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Inspection/EngineInspectionTests.cs @@ -245,8 +245,14 @@ public void ResolveAddress_reports_an_unavailable_global_without_entering_lua() [Fact] public void AddressResolutionOptions_supports_init_and_with() { - AddressResolutionOptions options = new() { Shallow = true }; - AddressResolutionOptions updated = options with { Shallow = false }; + AddressResolutionOptions options = new() + { + Shallow = true + }; + AddressResolutionOptions updated = options with + { + Shallow = false + }; Assert.True(options.Shallow); Assert.False(updated.Shallow); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolListTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolListTests.cs index c3bf4aa6..3504b9e7 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolListTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Inspection/SymbolListTests.cs @@ -362,13 +362,13 @@ public void Main_symbol_list_is_borrowed_only() foreach (Type type in typeof(SymbolList).Assembly.GetExportedTypes()) { foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | - BindingFlags.Static | BindingFlags.DeclaredOnly)) + BindingFlags.Static | BindingFlags.DeclaredOnly)) { bool takesBorrowedList = (type == typeof(SymbolList) && !method.IsStatic) || - Array.Exists(method.GetParameters(), - static parameter => parameter.ParameterType == typeof(SymbolList)); + Array.Exists(method.GetParameters(), + static parameter => parameter.ParameterType == typeof(SymbolList)); bool lifecycleName = method.Name.Contains("register", StringComparison.OrdinalIgnoreCase) || - method.Name.Contains("destroy", StringComparison.OrdinalIgnoreCase); + method.Name.Contains("destroy", StringComparison.OrdinalIgnoreCase); if (takesBorrowedList && lifecycleName) { offenders.Add(type.Name + "." + method.Name); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Memory/AddressTypeSeparationTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Memory/AddressTypeSeparationTests.cs index d289f6c6..357fa4db 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Memory/AddressTypeSeparationTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Memory/AddressTypeSeparationTests.cs @@ -29,7 +29,7 @@ public void Address_types_expose_no_conversion_to_each_other_or_to_double() string[] conversions = [ .. types.SelectMany(static type => type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.DeclaredOnly)) + BindingFlags.Static | BindingFlags.DeclaredOnly)) .Where(static method => method.Name is "op_Implicit" or "op_Explicit") .Select(Describe) .Order(StringComparer.Ordinal) diff --git a/tests/CheatEngine.SDK.Engine.Tests/Memory/MemoryScalarsFidelityTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Memory/MemoryScalarsFidelityTests.cs index 9834e73e..f7fbc3cf 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Memory/MemoryScalarsFidelityTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Memory/MemoryScalarsFidelityTests.cs @@ -1,6 +1,7 @@ using System.Globalization; using System.Text; +using CheatEngine.SDK.Engine.Generated; using CheatEngine.SDK.Engine.Tests.Support; using CheatEngine.SDK.Engine.Values; using CheatEngine.SDK.Tests.Shared.NativeLua; diff --git a/tests/CheatEngine.SDK.Engine.Tests/Objects/OwnershipSurfaceTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Objects/OwnershipSurfaceTests.cs index 576714b0..377e057e 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Objects/OwnershipSurfaceTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Objects/OwnershipSurfaceTests.cs @@ -56,7 +56,7 @@ public void No_public_property_or_get_method_returns_an_owner() foreach (MethodInfo method in type.GetMethods(PublicMembers)) { if (!method.IsSpecialName && method.Name.StartsWith("Get", StringComparison.Ordinal) && - IsOwner(method.ReturnType)) + IsOwner(method.ReturnType)) { offenders.Add(type.Name + "." + method.Name); } @@ -84,7 +84,7 @@ public void Memory_records_are_never_wrapped_in_an_owner() foreach (MethodInfo method in type.GetMethods(PublicMembers)) { if (method.ReturnType == ownedRecord || Array.Exists(method.GetParameters(), - parameter => UnderlyingType(parameter.ParameterType) == ownedRecord)) + parameter => UnderlyingType(parameter.ParameterType) == ownedRecord)) { offenders.Add(type.Name + "." + method.Name); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Processes/RuntimeProcessOperationsTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Processes/RuntimeProcessOperationsTests.cs index fbde4027..0233766b 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Processes/RuntimeProcessOperationsTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Processes/RuntimeProcessOperationsTests.cs @@ -851,7 +851,7 @@ local function forbidden(name) private static void InstallCurrentProcessGlobals(LuaState state, int processId, bool is64Bit) { string source = "function getOpenedProcessID() return " + processId + " end\n" + - "function targetIs64Bit() return " + LuaBoolean(is64Bit) + " end"; + "function targetIs64Bit() return " + LuaBoolean(is64Bit) + " end"; EngineTest.Run(state, Encoding.UTF8.GetBytes(source)); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeCapabilityProbesTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeCapabilityProbesTests.cs index 206bb99a..36c6567b 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeCapabilityProbesTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeCapabilityProbesTests.cs @@ -1,5 +1,6 @@ using System.Text; +using CheatEngine.SDK.Engine.Generated; using CheatEngine.SDK.Engine.Processes; using CheatEngine.SDK.Engine.Runtime; using CheatEngine.SDK.Engine.Tests.Support; diff --git a/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeContractsTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeContractsTests.cs index 2396aab3..9242b80c 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeContractsTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Runtime/RuntimeContractsTests.cs @@ -280,7 +280,10 @@ public void cheat_engine_host_observation_keeps_each_fact_separate() { CheatEngineHostObservation host = new(null, CheatEngineArchitecture.X64, null, CheatEngineOperatingSystem.Unknown); - CheatEngineHostObservation reported = host with { CheatEngineIs64Bit = false }; + CheatEngineHostObservation reported = host with + { + CheatEngineIs64Bit = false + }; Assert.Null(host.FileVersion); Assert.Null(host.CheatEngineIs64Bit); @@ -428,7 +431,10 @@ public void runtime_info_created_from_observations_uses_the_configured_pointer_s RuntimeInfo info = new(host, narrowed, RuntimeCapabilities.Empty); RuntimeInfo widenedInfo = new(host, widened, RuntimeCapabilities.Empty); - RuntimeInfo withoutTarget = new(host with { FileVersion = null }, null, RuntimeCapabilities.Empty); + RuntimeInfo withoutTarget = new(host with + { + FileVersion = null + }, null, RuntimeCapabilities.Empty); RuntimeInfo unknown = new(host, unknownFamilies, RuntimeCapabilities.Empty); Assert.Equal(host, info.Host); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobBoundedScanTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobBoundedScanTests.cs index b94c2df0..161c3c47 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobBoundedScanTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobBoundedScanTests.cs @@ -573,8 +573,8 @@ public void TryScanWithinBounds_target_change_during_the_scan_is_target_changed_ MemScanTestHost.HostObjects objects = MemScanTestHost.Install(L); SetAddresses(L, "100000000"); MemScanTestHost.Run(L, "scan_first_hook = function() opened_process_id = " + - MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture) + - " end"); + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture) + + " end"); Address[] destination = [new(0xA11CE)]; AobBoundedScanResult result = Scan(ModuleBounds, destination); @@ -850,8 +850,8 @@ private static int Occurrences(string text, string value) { int count = 0; for (int index = text.IndexOf(value, StringComparison.Ordinal); - index >= 0; - index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) + index >= 0; + index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) { count++; } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobFirstFoundScanTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobFirstFoundScanTests.cs index 51dd2478..96b4d002 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobFirstFoundScanTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Aob/AobFirstFoundScanTests.cs @@ -263,9 +263,9 @@ public void TryFindFirstFoundWithinBounds_target_change_during_the_scan_reports_ LuaState L = scope.State; _ = MemScanTestHost.Install(L); MemScanTestHost.Run(L, "only_result_mode = 'value'; only_result_value = 0x100000000; " + - "scan_first_hook = function() opened_process_id = " + - MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture) + - " end"); + "scan_first_hook = function() opened_process_id = " + + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture) + + " end"); AobFirstFoundResult result = Find(ModuleBounds); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemScanTestHost.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemScanTestHost.cs index 3b0d23a7..1b13a45f 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemScanTestHost.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemScanTestHost.cs @@ -298,7 +298,7 @@ public static int FindOtherQualifiedProcessId() } } catch (Exception exception) when (exception is InvalidOperationException or Win32Exception - or NotSupportedException) + or NotSupportedException) { // Not readable by this user (protected or already exited): not a qualifiable target. } @@ -318,8 +318,8 @@ public static int FindOtherQualifiedProcessId() public static void ReplaceCapturedTarget(MemoryScanSession session, TargetProcessIncarnation incarnation) { FieldInfo field = typeof(MemoryScanSession).GetField("_targetObservation", - BindingFlags.Instance | BindingFlags.NonPublic) - ?? throw new InvalidOperationException("The session's captured target field was not found."); + BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException("The session's captured target field was not found."); field.SetValue(session, TargetSelectionObservation.Qualified(incarnation)); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionFactoryTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionFactoryTests.cs index 23e8185c..6cada640 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionFactoryTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionFactoryTests.cs @@ -448,8 +448,8 @@ function getOpenedProcessID() private static void InstallCurrentTarget(LuaState state) { EngineTest.Run(state, Encoding.UTF8.GetBytes("function getOpenedProcessID() return " + - Environment.ProcessId.ToString(CultureInfo.InvariantCulture) + - " end")); + Environment.ProcessId.ToString(CultureInfo.InvariantCulture) + + " end")); EngineTest.Run(state, FakeHost.LocalTargetBackendChunk); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionTests.cs index c2f1ec25..650aebed 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/MemoryScanSessionTests.cs @@ -871,8 +871,8 @@ private static MemoryScanSession CreateSession(LuaState state, bool firstScanRai private static void InstallCurrentTarget(LuaState state) { EngineTest.Run(state, Encoding.UTF8.GetBytes("opened_process_id = " + - Environment.ProcessId.ToString(CultureInfo.InvariantCulture) + - "; function getOpenedProcessID() return opened_process_id end")); + Environment.ProcessId.ToString(CultureInfo.InvariantCulture) + + "; function getOpenedProcessID() return opened_process_id end")); EngineTest.Run(state, FakeHost.LocalTargetBackendChunk); } @@ -895,14 +895,14 @@ private static string FoundListInitializer(bool invalidAddress = false, string r string firstAddress = invalidAddress ? "'not-an-address'" : "'00001234'"; string destroyFailure = destroyRaises ? "; error('found-list destroy rejected')" : string.Empty; return "o.props.initialize = function() table.insert(trace, 'list.initialize') end\n" + - "o.props.deinitialize = function() table.insert(trace, 'list.deinitialize') end\n" + - "o.props.Count = " + resultCountLiteral + "\n" + - "o.props.getCount = function() table.insert(trace, 'results.getCount'); return o.props.Count end\n" + - "o.props.getAddress = function(index) table.insert(trace, 'results.getAddress:' .. index); if index == 0 then return " + - firstAddress + " end; return 'FFFFFFFFFFFFFFFF' end\n" + - "o.props.getValue = function(index) table.insert(trace, 'results.getValue:' .. index); return '100' end\n" + - "o.getters.destroy = function(o) return function() o.destroyed = true; table.insert(trace, 'list.destroy')" + - destroyFailure + " end end"; + "o.props.deinitialize = function() table.insert(trace, 'list.deinitialize') end\n" + + "o.props.Count = " + resultCountLiteral + "\n" + + "o.props.getCount = function() table.insert(trace, 'results.getCount'); return o.props.Count end\n" + + "o.props.getAddress = function(index) table.insert(trace, 'results.getAddress:' .. index); if index == 0 then return " + + firstAddress + " end; return 'FFFFFFFFFFFFFFFF' end\n" + + "o.props.getValue = function(index) table.insert(trace, 'results.getValue:' .. index); return '100' end\n" + + "o.getters.destroy = function(o) return function() o.destroyed = true; table.insert(trace, 'list.destroy')" + + destroyFailure + " end end"; } private static string ReadTrace(LuaState state) diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/ScanExperimentalApiTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/ScanExperimentalApiTests.cs index be857a39..4d4d35e7 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/ScanExperimentalApiTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/ScanExperimentalApiTests.cs @@ -43,7 +43,7 @@ public void Scanning_experimental_members_are_exactly_the_documented_gates() foreach (Type type in typeof(AobScanner).Assembly.GetExportedTypes()) { if (type.Namespace is null || - !type.Namespace.StartsWith("CheatEngine.SDK.Engine.Scanning", StringComparison.Ordinal)) + !type.Namespace.StartsWith("CheatEngine.SDK.Engine.Scanning", StringComparison.Ordinal)) { continue; } @@ -54,7 +54,7 @@ public void Scanning_experimental_members_are_exactly_the_documented_gates() } foreach (MemberInfo member in type.GetMembers(BindingFlags.Public | BindingFlags.Instance | - BindingFlags.Static | BindingFlags.DeclaredOnly)) + BindingFlags.Static | BindingFlags.DeclaredOnly)) { if (member.GetCustomAttribute() is { } attribute) { diff --git a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionDeadlineTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionDeadlineTests.cs index 5bed132a..d302ec5f 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionDeadlineTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Scanning/Values/MemoryScanSessionDeadlineTests.cs @@ -344,7 +344,7 @@ public void TryTerminateScan_unconfirmed_stop_is_kept_by_a_refused_release_witho MemScanTestHost.Run(L, "scan_wait_mode = 'false'"); Assert.Equal(MemoryScanTerminationStatus.WaitTimedOut, session.TryTerminateScan(Deadline)); MemScanTestHost.Run(L, "opened_process_id = " + - MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); MemScanTestHost.ClearTrace(L); MemoryScanReleaseOutcome outcome = session.ReleaseWithOutcome(); @@ -504,7 +504,7 @@ public void TryGetHostErrorText_with_a_replaced_target_returns_false_without_a_s LuaState L = scope.State; MemoryScanSession session = StartScanning(L); MemScanTestHost.Run(L, "scan_error_string = 'unread'; opened_process_id = " + - MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); + MemScanTestHost.FindOtherQualifiedProcessId().ToString(CultureInfo.InvariantCulture)); bool read = session.TryGetHostErrorText(out string? text, out bool truncated); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.Rt.cs b/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.Rt.cs index 00b68f35..709b6509 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.Rt.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Support/FakeHost.Rt.cs @@ -173,7 +173,7 @@ private static List ReadStringSequence(LuaState state, ReadOnlySpan) &ObservePCall); tableField.SetValue(null, _table); @@ -411,8 +411,8 @@ private static int ObservePCall(lua_State* state, int argumentCount, int resultC { PCallProbe? probe = s_activePCallProbe; if (probe is not null && - (nint) lua_tocfunction(state, -argumentCount - 1) == - (nint) (delegate* unmanaged[Cdecl]) &WaitTillDone) + (nint) lua_tocfunction(state, -argumentCount - 1) == + (nint) (delegate* unmanaged[Cdecl]) &WaitTillDone) { probe.Observe(argumentCount, resultCount); } diff --git a/tests/CheatEngine.SDK.Engine.Tests/Tables/CheatTableFilesTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Tables/CheatTableFilesTests.cs index 5ad10af1..a8990cda 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Tables/CheatTableFilesTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Tables/CheatTableFilesTests.cs @@ -101,10 +101,10 @@ public void TryLoad_marks_address_list_mutations_as_refused_while_it_runs() List observed = []; MemoryRecordMutationOutcome refused = default; using (FakeHost.InstallReentrantHook(L, "table_script", () => - { - observed.Add(CheatTableFiles.IsLoadInProgressOnCurrentThread); - refused = AddressListMutations.Delete(new MemoryRecordId(1)); - })) + { + observed.Add(CheatTableFiles.IsLoadInProgressOnCurrentThread); + refused = AddressListMutations.Delete(new MemoryRecordId(1)); + })) { EngineTest.Run(L, "loadTable = function(path, merge) table_script() end"u8); diff --git a/tests/CheatEngine.SDK.Engine.Tests/Targets/TargetSelectionTests.cs b/tests/CheatEngine.SDK.Engine.Tests/Targets/TargetSelectionTests.cs index cbd23cb4..04279482 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/Targets/TargetSelectionTests.cs +++ b/tests/CheatEngine.SDK.Engine.Tests/Targets/TargetSelectionTests.cs @@ -28,8 +28,8 @@ public void ObserveCurrent_with_the_current_process_id_returns_a_qualified_incar Assert.True(observation.Incarnation.HasValue); Assert.Equal(Environment.ProcessId, observation.Incarnation.Value.ProcessId); Assert.Equal(TargetIdentityEvidence.CheatEngineSelectedProcessId | - TargetIdentityEvidence.LocalBackendConfirmed | - TargetIdentityEvidence.LocalProcessStartTime, observation.Evidence); + TargetIdentityEvidence.LocalBackendConfirmed | + TargetIdentityEvidence.LocalProcessStartTime, observation.Evidence); Assert.Equal(TargetBackend.LocalProcess, observation.Backend); Assert.True(TargetSelection.ValidateCurrent(observation.Incarnation.Value).IsCurrent); Assert.Equal(0, scope.State.Top); diff --git a/tests/CheatEngine.SDK.Engine.Tests/packages.lock.json b/tests/CheatEngine.SDK.Engine.Tests/packages.lock.json index ee88a87c..35041e9f 100644 --- a/tests/CheatEngine.SDK.Engine.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.Engine.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.Testing.Extensions.CodeCoverage": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/CoexistencePluginLayout.cs b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/CoexistencePluginLayout.cs index a1f5554e..bea15933 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/CoexistencePluginLayout.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/CoexistencePluginLayout.cs @@ -76,7 +76,7 @@ private static void CopyDirectoryInto(string sourceDirectory, string destination private static string RequireMetadata(string key) { foreach (AssemblyMetadataAttribute attribute in typeof(CoexistencePluginLayout).Assembly - .GetCustomAttributes()) + .GetCustomAttributes()) { if (string.Equals(attribute.Key, key, StringComparison.Ordinal) && !string.IsNullOrEmpty(attribute.Value)) { diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorRunner.cs b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorRunner.cs index 556cfdcf..80000dcf 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorRunner.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Coexistence/NativeHostEmulatorRunner.cs @@ -48,7 +48,10 @@ internal static NativeHostEmulatorResult Run( AddArgument(startInfo, "--alc", route == NativeHostEmulatorAlcRoute.Default ? "default" : "component"); AddArgument(startInfo, "--facts", factsPath); - using Process process = new() { StartInfo = startInfo }; + using Process process = new() + { + StartInfo = startInfo + }; process.Start(); string standardOutput = process.StandardOutput.ReadToEnd(); string standardError = process.StandardError.ReadToEnd(); diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/HostLogContainmentTests.cs b/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/HostLogContainmentTests.cs index b122b048..8cba803f 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/HostLogContainmentTests.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Diagnostics/HostLogContainmentTests.cs @@ -120,7 +120,7 @@ public void A_sink_that_acquires_a_Lua_operation_during_a_lifecycle_transition_i HostLog.Sink = new CallbackLogSink(message => { if (string.Equals(message, "RecordingPlugin.OnDisable observed", StringComparison.Ordinal) - && acquiredDuringOnDisable is null) + && acquiredDuringOnDisable is null) { // OnDisable still runs on the captured main thread while the runtime is attached (operation // admission itself does not close until after OnDisable returns): the acquisition succeeds and diff --git a/tests/CheatEngine.SDK.Hosting.Tests/Support/RecordingPlugin.cs b/tests/CheatEngine.SDK.Hosting.Tests/Support/RecordingPlugin.cs index 05c7ba75..8ae7aea4 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/Support/RecordingPlugin.cs +++ b/tests/CheatEngine.SDK.Hosting.Tests/Support/RecordingPlugin.cs @@ -269,15 +269,15 @@ protected internal override void OnEnable() if (CreateCallbacksInOnEnable) { if (!LuaCallback.TryCreate(L, new LuaNativeFunction(&NoOpThunk), new object(), - out LuaCallback? first).IsOk - || first is null) + out LuaCallback? first).IsOk + || first is null) { throw new InvalidOperationException("first callback creation failed"); } if (!LuaCallback.TryCreate(L, new LuaNativeFunction(&NoOpThunk), new object(), - out LuaCallback? second).IsOk - || second is null) + out LuaCallback? second).IsOk + || second is null) { throw new InvalidOperationException("second callback creation failed"); } diff --git a/tests/CheatEngine.SDK.Hosting.Tests/packages.lock.json b/tests/CheatEngine.SDK.Hosting.Tests/packages.lock.json index a2e6b3bd..a73955e9 100644 --- a/tests/CheatEngine.SDK.Hosting.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.Hosting.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.Testing.Extensions.CodeCoverage": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/CoexistencePluginAFunctions.cs b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/CoexistencePluginAFunctions.cs index df5e6a69..df5cb67a 100644 --- a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/CoexistencePluginAFunctions.cs +++ b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/CoexistencePluginAFunctions.cs @@ -2,7 +2,7 @@ namespace LivePlugin.Coexistence.PluginA; -internal static class CoexistencePluginAFunctions +internal static partial class CoexistencePluginAFunctions { private static long s_pingCount; diff --git a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/packages.lock.json b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/packages.lock.json index 67bcb512..bf6a3511 100644 --- a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/packages.lock.json +++ b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginA/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "MinVer": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/CoexistencePluginBFunctions.cs b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/CoexistencePluginBFunctions.cs index fd2ffe6c..ee848e91 100644 --- a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/CoexistencePluginBFunctions.cs +++ b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/CoexistencePluginBFunctions.cs @@ -2,7 +2,7 @@ namespace LivePlugin.Coexistence.PluginB; -internal static class CoexistencePluginBFunctions +internal static partial class CoexistencePluginBFunctions { private static long s_pingCount; diff --git a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/packages.lock.json b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/packages.lock.json index 67bcb512..bf6a3511 100644 --- a/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/packages.lock.json +++ b/tests/CheatEngine.SDK.LivePlugin.Coexistence/PluginB/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "MinVer": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.LivePlugin/LiveFunctions.cs b/tests/CheatEngine.SDK.LivePlugin/LiveFunctions.cs index 804f9d15..b929bf00 100644 --- a/tests/CheatEngine.SDK.LivePlugin/LiveFunctions.cs +++ b/tests/CheatEngine.SDK.LivePlugin/LiveFunctions.cs @@ -11,7 +11,7 @@ namespace LivePlugin; /// ; /// unregisters them through UnregisterLuaFunctions. /// -internal static class LiveFunctions +internal static partial class LiveFunctions { private static long s_pingCount; diff --git a/tests/CheatEngine.SDK.LivePlugin/packages.lock.json b/tests/CheatEngine.SDK.LivePlugin/packages.lock.json index 67bcb512..bf6a3511 100644 --- a/tests/CheatEngine.SDK.LivePlugin/packages.lock.json +++ b/tests/CheatEngine.SDK.LivePlugin/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "MinVer": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStatusTests.cs b/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStatusTests.cs index 45918a73..21d943ab 100644 --- a/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStatusTests.cs +++ b/tests/CheatEngine.SDK.LiveProbe.Tests/LiveProbeStatusTests.cs @@ -53,7 +53,11 @@ public void Status_reports_the_exports_size_and_the_raw_second_bootstrap_integer [Fact] public void Status_without_an_enabled_context_reports_none_instead_of_zero_values() { - LiveProbeHostFacts host = Facts(0, 0, 0, 0) with { HasContext = false, Phase = "Registered" }; + LiveProbeHostFacts host = Facts(0, 0, 0, 0) with + { + HasContext = false, + Phase = "Registered" + }; string text = LiveProbeState.GetStatus(host); using JsonDocument json = JsonDocument.Parse(LiveProbeState.GetStatusJson(host)); diff --git a/tests/CheatEngine.SDK.LiveProbe.Tests/ProbeHostGlobals.cs b/tests/CheatEngine.SDK.LiveProbe.Tests/ProbeHostGlobals.cs index 73e3ee53..bc916c33 100644 --- a/tests/CheatEngine.SDK.LiveProbe.Tests/ProbeHostGlobals.cs +++ b/tests/CheatEngine.SDK.LiveProbe.Tests/ProbeHostGlobals.cs @@ -1,4 +1,4 @@ -namespace CheatEngine.SDK.LiveProbe.Tests; +namespace LiveProbe; // The source-linked LiveProbe sources call ProbeHostGlobals.GetOpenedProcessId, which the plugin project generates from // [LuaGlobal("getOpenedProcessID")]. The tests inject the PID reader and never call it; this stub keeps the same diff --git a/tests/CheatEngine.SDK.LiveProbe.Tests/packages.lock.json b/tests/CheatEngine.SDK.LiveProbe.Tests/packages.lock.json index 9a8731e7..ea6892d9 100644 --- a/tests/CheatEngine.SDK.LiveProbe.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.LiveProbe.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.Testing.Extensions.CodeCoverage": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.LiveProbe/CE77LiveProbeBootstrap.cs b/tests/CheatEngine.SDK.LiveProbe/CE77LiveProbeBootstrap.cs index 2e3bfc2d..52b62975 100644 --- a/tests/CheatEngine.SDK.LiveProbe/CE77LiveProbeBootstrap.cs +++ b/tests/CheatEngine.SDK.LiveProbe/CE77LiveProbeBootstrap.cs @@ -2,7 +2,9 @@ using CheatEngine.SDK.Hosting.Bootstrap; using CheatEngine.SDK.Hosting.Diagnostics; -namespace LiveProbe; +using LiveProbe; + +namespace CESDK; /// /// The intentionally hand-written CE managed bootstrap used only by the CE 7.7 live-probe plugin. diff --git a/tests/CheatEngine.SDK.LiveProbe/HostProfileObservation.cs b/tests/CheatEngine.SDK.LiveProbe/HostProfileObservation.cs index 9997fdba..d3fe445d 100644 --- a/tests/CheatEngine.SDK.LiveProbe/HostProfileObservation.cs +++ b/tests/CheatEngine.SDK.LiveProbe/HostProfileObservation.cs @@ -85,7 +85,7 @@ private static void WriteFileIdentityFields(Utf8JsonWriter writer, string? path, writer.WriteString("machine", reader.PEHeaders.CoffHeader.Machine.ToString()); } catch (Exception exception) when (exception is BadImageFormatException or IOException - or UnauthorizedAccessException) + or UnauthorizedAccessException) { writer.WriteString("machine", "unavailable: " + exception.GetType().Name); } @@ -132,7 +132,7 @@ internal static string ObserveFileVersion(string path, Func get return getFileVersion(path) ?? "not-present"; } catch (Exception exception) when (exception is ArgumentException or Win32Exception - or IOException or UnauthorizedAccessException) + or IOException or UnauthorizedAccessException) { return "unavailable: " + exception.GetType().Name; } @@ -152,7 +152,7 @@ internal static string ObserveFileVersion(string path, Func get } } catch (Exception exception) when (exception is InvalidOperationException or NotSupportedException - or Win32Exception) + or Win32Exception) { HostLog.Write(HostLogLevel.Warning, "CE 7.7 host-profile probe could not enumerate loaded modules.", exception); diff --git a/tests/CheatEngine.SDK.LiveProbe/LiveProbeAuthorization.cs b/tests/CheatEngine.SDK.LiveProbe/LiveProbeAuthorization.cs index d10b460b..e85be096 100644 --- a/tests/CheatEngine.SDK.LiveProbe/LiveProbeAuthorization.cs +++ b/tests/CheatEngine.SDK.LiveProbe/LiveProbeAuthorization.cs @@ -189,17 +189,17 @@ private static bool TryReadManifest(string path, out AuthorizationManifest manif using JsonDocument document = JsonDocument.Parse(stream); JsonElement root = document.RootElement; if (root.ValueKind != JsonValueKind.Object || !TryString(root, "schema", out string schema) || - !string.Equals(schema, "ce77-live-probe-v1", StringComparison.Ordinal) || - !TryString(root, "acknowledgement", out string acknowledgement) || - !TryString(root, "hostSha256", out string hostSha256) || - !TryString(root, "targetSha256", out string targetSha256) || - !TryString(root, "expiresUtc", out string expiresText) || - !root.TryGetProperty("targetProcessId", out JsonElement pid) || - !pid.TryGetInt32(out int targetProcessId) || - !root.TryGetProperty("disposable", out JsonElement disposable) || - disposable.ValueKind is not JsonValueKind.True and not JsonValueKind.False || - !DateTimeOffset.TryParse(expiresText, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, - out DateTimeOffset expiresUtc)) + !string.Equals(schema, "ce77-live-probe-v1", StringComparison.Ordinal) || + !TryString(root, "acknowledgement", out string acknowledgement) || + !TryString(root, "hostSha256", out string hostSha256) || + !TryString(root, "targetSha256", out string targetSha256) || + !TryString(root, "expiresUtc", out string expiresText) || + !root.TryGetProperty("targetProcessId", out JsonElement pid) || + !pid.TryGetInt32(out int targetProcessId) || + !root.TryGetProperty("disposable", out JsonElement disposable) || + disposable.ValueKind is not JsonValueKind.True and not JsonValueKind.False || + !DateTimeOffset.TryParse(expiresText, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, + out DateTimeOffset expiresUtc)) { failure = "The authorization manifest is missing a required ce77-live-probe-v1 field."; return false; @@ -210,7 +210,7 @@ disposable.ValueKind is not JsonValueKind.True and not JsonValueKind.False || return true; } catch (Exception exception) when (exception is IOException or UnauthorizedAccessException or JsonException - or ArgumentException) + or ArgumentException) { failure = exception.GetType().Name + ": " + exception.Message; return false; @@ -246,7 +246,7 @@ private static bool TryGetProcessImage(int processId, out string path, out strin return true; } catch (Exception exception) when (exception is ArgumentException or InvalidOperationException - or NotSupportedException or Win32Exception) + or NotSupportedException or Win32Exception) { failure = exception.GetType().Name + ": " + exception.Message; return false; @@ -275,7 +275,7 @@ private static bool IsAmd64Pe(string path, out string failure) return false; } catch (Exception exception) when (exception is BadImageFormatException or IOException - or UnauthorizedAccessException) + or UnauthorizedAccessException) { failure = exception.GetType().Name + ": " + exception.Message; return false; diff --git a/tests/CheatEngine.SDK.LiveProbe/LiveProbeFaultInjection.cs b/tests/CheatEngine.SDK.LiveProbe/LiveProbeFaultInjection.cs index 427127a9..2b458941 100644 --- a/tests/CheatEngine.SDK.LiveProbe/LiveProbeFaultInjection.cs +++ b/tests/CheatEngine.SDK.LiveProbe/LiveProbeFaultInjection.cs @@ -79,7 +79,7 @@ internal static LiveProbeFaultDecision Evaluate(Func eval text = readFile(path); } catch (Exception exception) when (exception is IOException or UnauthorizedAccessException - or ArgumentException or NotSupportedException) + or ArgumentException or NotSupportedException) { return new LiveProbeFaultDecision(LiveProbeFaultStage.None, "Fault switch ignored: " + FileName + " could not be read (" + exception.GetType().Name + ").", true); @@ -147,7 +147,7 @@ internal static void EnterOnDisable() private static LiveProbeFaultDecision EvaluateForEnable() { string pluginDirectory = Path.GetDirectoryName(typeof(LiveProbeFaultInjection).Assembly.Location) ?? - AppContext.BaseDirectory; + AppContext.BaseDirectory; LiveProbeFaultDecision decision = Evaluate(LiveProbeAuthorization.Evaluate, pluginDirectory, ReadIfPresent); int sequence; lock (Gate) @@ -184,7 +184,7 @@ private static LiveProbeFaultDecision Parse(string text) using JsonDocument document = JsonDocument.Parse(text); JsonElement root = document.RootElement; if (root.ValueKind != JsonValueKind.Object || - !root.TryGetProperty("schema", out JsonElement schema) || schema.ValueKind != JsonValueKind.String) + !root.TryGetProperty("schema", out JsonElement schema) || schema.ValueKind != JsonValueKind.String) { return Ignored("it has no schema string"); } @@ -234,7 +234,7 @@ private static LiveProbeFaultDecision Ignored(string why) if (file.Length > MaximumFileBytes) { throw new IOException("The fault switch is larger than " + - MaximumFileBytes.ToString(CultureInfo.InvariantCulture) + " bytes."); + MaximumFileBytes.ToString(CultureInfo.InvariantCulture) + " bytes."); } return File.ReadAllText(path); diff --git a/tests/CheatEngine.SDK.LiveProbe/LiveProbeState.cs b/tests/CheatEngine.SDK.LiveProbe/LiveProbeState.cs index a7ef57d5..fc1bf1f3 100644 --- a/tests/CheatEngine.SDK.LiveProbe/LiveProbeState.cs +++ b/tests/CheatEngine.SDK.LiveProbe/LiveProbeState.cs @@ -97,7 +97,10 @@ internal static void TryWriteTailCanaryAfterPackedRecord(nint initRecord, int bo { lock (Gate) { - s_bootstrap = s_bootstrap with { TailFailure = Describe(exception) }; + s_bootstrap = s_bootstrap with + { + TailFailure = Describe(exception) + }; } HostLog.Write(HostLogLevel.Error, "CE 7.7 live-probe tail canary failed.", exception); @@ -370,7 +373,8 @@ internal static string BeginSynchronizeProbe() Thread thread = new(RunSynchronizeProbe) { - IsBackground = true, Name = "CheatEngine.SDK CE77 synchronize probe" + IsBackground = true, + Name = "CheatEngine.SDK CE77 synchronize probe" }; thread.Start(); return "Synchronize probe started. Do not block the CE GUI thread; poll ce77_live_probe_synchronize_status()."; @@ -416,7 +420,11 @@ internal static string BeginLuaThreadProbe() // The delayed worker starts only after this Lua callback has returned its string to CE. It is still a live, // opt-in observation against CE's per-thread state contract, never a general concurrency guarantee for Lua. - Thread thread = new(RunLuaThreadProbe) { IsBackground = true, Name = "CheatEngine.SDK CE77 Lua thread probe" }; + Thread thread = new(RunLuaThreadProbe) + { + IsBackground = true, + Name = "CheatEngine.SDK CE77 Lua thread probe" + }; thread.Start(); return "Lua thread/registry probe started. Do not run other Lua code for one second; poll ce77_live_probe_lua_threads_status()."; @@ -635,21 +643,34 @@ private static void RunSynchronizeProbe() { MainThread.Invoke( static _ => throw new InvalidOperationException("CE77-live-probe expected dispatch failure."), 0); - observation = observation with { ExceptionResult = "unexpectedly returned" }; + observation = observation with + { + ExceptionResult = "unexpectedly returned" + }; } catch (InvalidOperationException exception) { - observation = observation with { ExceptionResult = "re-thrown: " + exception.Message }; + observation = observation with + { + ExceptionResult = "re-thrown: " + exception.Message + }; } } catch (Exception exception) { - observation = observation with { Completion = "failed", Failure = Describe(exception) }; + observation = observation with + { + Completion = "failed", + Failure = Describe(exception) + }; } lock (Gate) { - s_synchronize = observation with { IsRunning = false }; + s_synchronize = observation with + { + IsRunning = false + }; } } @@ -686,12 +707,19 @@ private static void RunLuaThreadProbe() } catch (Exception exception) { - observation = observation with { Completion = "failed", Failure = Describe(exception) }; + observation = observation with + { + Completion = "failed", + Failure = Describe(exception) + }; } lock (Gate) { - s_luaThread = observation with { IsRunning = false }; + s_luaThread = observation with + { + IsRunning = false + }; } } diff --git a/tests/CheatEngine.SDK.LiveProbe/ProbeConsole.cs b/tests/CheatEngine.SDK.LiveProbe/ProbeConsole.cs index 7da402ba..76a0b596 100644 --- a/tests/CheatEngine.SDK.LiveProbe/ProbeConsole.cs +++ b/tests/CheatEngine.SDK.LiveProbe/ProbeConsole.cs @@ -6,7 +6,7 @@ namespace LiveProbe; /// Lua-console commands for the CE 7.7 live-probe plugin. Every command returns a self-contained status record; /// commands that initiate a probe first require the exact host and disposable-target authorization gate. /// -internal static class ProbeConsole +internal static partial class ProbeConsole { /// Returns the gate decision and all observations accumulated in this process. [LuaFunction("ce77_live_probe_status")] diff --git a/tests/CheatEngine.SDK.LiveProbe/packages.lock.json b/tests/CheatEngine.SDK.LiveProbe/packages.lock.json index ca4a72fd..fa8a73e9 100644 --- a/tests/CheatEngine.SDK.LiveProbe/packages.lock.json +++ b/tests/CheatEngine.SDK.LiveProbe/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "MinVer": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Lua.FailureProbe/Program.cs b/tests/CheatEngine.SDK.Lua.FailureProbe/Program.cs index 046c6f97..6fad5749 100644 --- a/tests/CheatEngine.SDK.Lua.FailureProbe/Program.cs +++ b/tests/CheatEngine.SDK.Lua.FailureProbe/Program.cs @@ -95,9 +95,9 @@ public static int Main(string[] arguments) private static bool HasValidArguments(string[] arguments) { return arguments.Length is >= 1 and <= 2 && - (arguments.Length != 2 || - string.Equals(arguments[1], CheckStackGrowthMode, StringComparison.Ordinal) || - string.Equals(arguments[1], GeneratedFunctionAllocationMode, StringComparison.Ordinal)); + (arguments.Length != 2 || + string.Equals(arguments[1], CheckStackGrowthMode, StringComparison.Ordinal) || + string.Equals(arguments[1], GeneratedFunctionAllocationMode, StringComparison.Ordinal)); } private static int RunRequestedProbe(LuaState state, nint module, string[] arguments) @@ -507,7 +507,7 @@ private static int VerifyUncheckedFunctionReservationFailure(LuaState state, Lua catch (InvalidOperationException exception) { if (!string.Equals(exception.Message, UncheckedFunctionReservationFailureMessage, - StringComparison.Ordinal)) + StringComparison.Ordinal)) { return Fail("PushUncheckedFunction returned an unstable reservation failure message"); } @@ -1055,7 +1055,7 @@ private static int ProbeHostObjectPusherLongJump( } if (!state.TryReadString(-1, out string? error) || - !error.Contains("bad argument #1", StringComparison.Ordinal)) + !error.Contains("bad argument #1", StringComparison.Ordinal)) { return Fail("PushHostObject did not leave the native luaL_checkinteger failure message on the stack"); } diff --git a/tests/CheatEngine.SDK.Lua.FailureProbe/packages.lock.json b/tests/CheatEngine.SDK.Lua.FailureProbe/packages.lock.json index 6dd54051..5356f467 100644 --- a/tests/CheatEngine.SDK.Lua.FailureProbe/packages.lock.json +++ b/tests/CheatEngine.SDK.Lua.FailureProbe/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "MinVer": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/Initialization/LuaApiBoundTableTests.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/Initialization/LuaApiBoundTableTests.cs index 9a5a420c..7aaf14b9 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/Initialization/LuaApiBoundTableTests.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/Initialization/LuaApiBoundTableTests.cs @@ -41,7 +41,7 @@ public void Every_slot_holds_an_address_inside_the_process() object table = typeof(LuaApi).GetField("s_table", BindingFlags.Static | BindingFlags.NonPublic)!.GetValue(null)!; FieldInfo[] slots = typeof(LuaApi.Table).GetFields(BindingFlags.Instance | BindingFlags.Public | - BindingFlags.NonPublic); + BindingFlags.NonPublic); Assert.NotEmpty(slots); foreach (FieldInfo slot in slots) diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs index bafac348..bca49f83 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaBridgeContractTests.cs @@ -96,7 +96,7 @@ private static bool HasDelayImports(string path) int delayImportDirectoryOffset = optionalOffset + 112 + (13 * 8); return ReadUInt32(image, delayImportDirectoryOffset) != 0 || - ReadUInt32(image, delayImportDirectoryOffset + sizeof(uint)) != 0; + ReadUInt32(image, delayImportDirectoryOffset + sizeof(uint)) != 0; } private static List ReadExportedNames(string path) diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaInteropPrimitiveMatrixTests.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaInteropPrimitiveMatrixTests.cs index 721a7f16..041dc966 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaInteropPrimitiveMatrixTests.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/Protected/LuaInteropPrimitiveMatrixTests.cs @@ -23,7 +23,10 @@ public sealed partial class LuaInteropPrimitiveMatrixTests private static readonly Dictionary RaisesFromRemark = new(StringComparer.Ordinal) { - ["never"] = "Never", ["memory"] = "Memory", ["any"] = "Any", ["always"] = "Always" + ["never"] = "Never", + ["memory"] = "Memory", + ["any"] = "Any", + ["always"] = "Always" }; [Fact] @@ -68,7 +71,7 @@ public void Matrix_raises_class_equals_the_documented_raises_remark() ? null : row.GetProperty("stackEffect").GetString(); if (!string.Equals(expectedRaises, row.GetProperty("raises").GetString(), StringComparison.Ordinal) || - !string.Equals(expectedStack, stack, StringComparison.Ordinal)) + !string.Equals(expectedStack, stack, StringComparison.Ordinal)) { problems.Add( $"{member}: documented {expectedStack ?? "no stack"} / {expectedRaises}, matrix {stack ?? "no stack"} / {row.GetProperty("raises").GetString()}."); @@ -129,9 +132,9 @@ private static void CheckPolicy(string member, JsonElement policy, JsonElement r ? "ConditionallyDirect" : "BridgeRequired"; if (!string.Equals(expectedDecision, decision, StringComparison.Ordinal) || - !string.Equals(Optional(policy, "bridgeOperation"), bridge, StringComparison.Ordinal) || - !string.Equals(policy.GetProperty("nativeSymbol").GetString(), Optional(row, "nativeSymbol"), - StringComparison.Ordinal)) + !string.Equals(Optional(policy, "bridgeOperation"), bridge, StringComparison.Ordinal) || + !string.Equals(policy.GetProperty("nativeSymbol").GetString(), Optional(row, "nativeSymbol"), + StringComparison.Ordinal)) { problems.Add( $"{member}: the policy route ({expectedDecision}, {Optional(policy, "bridgeOperation")}) differs from the row ({decision}, {bridge})."); @@ -142,7 +145,7 @@ private static void CheckPolicy(string member, JsonElement policy, JsonElement r // The policy may only be more conservative than the documented class, and only where the bridge operation // records the source conflict that justifies it (luaL_unref: documented never, implemented with lua_rawseti). bool conflictRecorded = bridge is not null && operations.TryGetValue(bridge, out JsonElement operation) && - operation.TryGetProperty("provenanceConflict", out _); + operation.TryGetProperty("provenanceConflict", out _); if (policyRank != rowRank && !(policyRank > rowRank && conflictRecorded)) { problems.Add( @@ -179,7 +182,7 @@ private static HashSet PublicMembers() // The LUA_* properties are header constants (library names, the signature), not callable primitives. foreach (PropertyInfo property in typeof(LuaApi).GetProperties(Flags) - .Where(static property => !property.Name.StartsWith("LUA_", StringComparison.Ordinal))) + .Where(static property => !property.Name.StartsWith("LUA_", StringComparison.Ordinal))) { members.Add(property.Name); } @@ -216,7 +219,7 @@ private static JsonElement[] Rows() private static JsonDocument Load(string resource) { using Stream stream = typeof(LuaInteropPrimitiveMatrixTests).Assembly.GetManifestResourceStream(resource) - ?? throw new InvalidOperationException($"The embedded resource {resource} is missing."); + ?? throw new InvalidOperationException($"The embedded resource {resource} is missing."); return JsonDocument.Parse(stream); } diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/RoundTrips/CallTests.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/RoundTrips/CallTests.cs index 567703ed..20510f5f 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/RoundTrips/CallTests.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/RoundTrips/CallTests.cs @@ -189,7 +189,13 @@ public void Load_pulls_the_chunk_through_a_managed_reader() fixed (byte* second = "* 7"u8) fixed (byte* name = "=pieces"u8) { - ReaderState pieces = new() { First = first, FirstSize = 9, Second = second, SecondSize = 3 }; + ReaderState pieces = new() + { + First = first, + FirstSize = 9, + Second = second, + SecondSize = 3 + }; Assert.Equal(LUA_OK, lua_load(L, &ReadPieces, &pieces, name, null)); Assert.Equal(3, pieces.Calls); diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs b/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs index 3f31c105..3ec93411 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/Support/IlReader.cs @@ -19,7 +19,7 @@ internal static class IlReader public static List<(OpCode Code, int Operand)> Read(MethodBase method) { byte[] il = method.GetMethodBody()?.GetILAsByteArray() ?? - throw new InvalidOperationException(method.Name + " has no IL body."); + throw new InvalidOperationException(method.Name + " has no IL body."); List<(OpCode Code, int Operand)> instructions = []; int offset = 0; diff --git a/tests/CheatEngine.SDK.Lua.Interop.Tests/packages.lock.json b/tests/CheatEngine.SDK.Lua.Interop.Tests/packages.lock.json index c149a719..321c8dd6 100644 --- a/tests/CheatEngine.SDK.Lua.Interop.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.Lua.Interop.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.Testing.Extensions.CodeCoverage": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Lua.Tests/Allocation/ZeroAllocationTests.cs b/tests/CheatEngine.SDK.Lua.Tests/Allocation/ZeroAllocationTests.cs index c2325fb5..c96aa5f8 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Allocation/ZeroAllocationTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Allocation/ZeroAllocationTests.cs @@ -73,13 +73,13 @@ private static long ReadEachScalar(LuaState state, int top) // Exact on purpose: the round trip through the Lua stack must not change a single bit, // so the bit patterns are compared. if (!DoubleMarshaller.TryRead(state, top + 3, out double d) || - BitConverter.DoubleToInt64Bits(d) != BitConverter.DoubleToInt64Bits(2.5)) + BitConverter.DoubleToInt64Bits(d) != BitConverter.DoubleToInt64Bits(2.5)) { Fail(); } if (!SingleMarshaller.TryRead(state, top + 4, out float f) || - BitConverter.SingleToInt32Bits(f) != BitConverter.SingleToInt32Bits(1.5f)) + BitConverter.SingleToInt32Bits(f) != BitConverter.SingleToInt32Bits(1.5f)) { Fail(); } @@ -90,7 +90,7 @@ private static long ReadEachScalar(LuaState state, int top) } if (!AddressMarshaller.TryRead(state, top + 6, out UIntPtr a) || - a != unchecked((nuint) 0xFFFF_FFFF_FFFF_FFF0UL)) + a != unchecked((nuint) 0xFFFF_FFFF_FFFF_FFF0UL)) { Fail(); } diff --git a/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaCallbackTests.cs b/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaCallbackTests.cs index ee8469da..2eb6a62d 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaCallbackTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaCallbackTests.cs @@ -215,7 +215,10 @@ public void Two_callbacks_of_the_same_thunk_have_independent_state() using NativeLuaState state = new(); LuaState L = LuaTest.View(state); Counter a = new(); - Counter b = new() { Value = 100 }; + Counter b = new() + { + Value = 100 + }; Assert.True(LuaCallback.TryCreate(L, Thunks.Count, a, out LuaCallback? callbackA).IsOk); Assert.True(LuaCallback.TryCreate(L, Thunks.Count, b, out LuaCallback? callbackB).IsOk); Assert.True(callbackA!.TryRegister(L, "countA"u8).IsOk); diff --git a/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaHostSubscriptionTests.cs b/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaHostSubscriptionTests.cs index 9b40b874..1ea1b1f9 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaHostSubscriptionTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Callbacks/LuaHostSubscriptionTests.cs @@ -434,24 +434,24 @@ public void Dispose() public bool Register() { if (!LuaHostSubscription.TryRegister(state, RunAdmittedCallback, - (registrationState, callback) => - { - HostCallback = callback; - return static _ => - { - }; - }, out LuaHostSubscription? firstSubscription)) + (registrationState, callback) => + { + HostCallback = callback; + return static _ => + { + }; + }, out LuaHostSubscription? firstSubscription)) { return false; } FirstSubscription = firstSubscription; return LuaHostSubscription.TryRegister(state, static () => - { - }, - (registrationState, callback) => releaseState => SecondUnregisters++, - out LuaHostSubscription? secondSubscription) - && (SecondSubscription = secondSubscription) is not null; + { + }, + (registrationState, callback) => releaseState => SecondUnregisters++, + out LuaHostSubscription? secondSubscription) + && (SecondSubscription = secondSubscription) is not null; } private void RunAdmittedCallback() diff --git a/tests/CheatEngine.SDK.Lua.Tests/CompilerServices/LuaCallSupportOptionalTests.cs b/tests/CheatEngine.SDK.Lua.Tests/CompilerServices/LuaCallSupportOptionalTests.cs index 31d34e60..2aad6ad1 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/CompilerServices/LuaCallSupportOptionalTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/CompilerServices/LuaCallSupportOptionalTests.cs @@ -130,8 +130,8 @@ public void Optional_helpers_allocate_nothing_when_warm() LuaCallSupport.PushOptional(L, LuaOptional.Of(5L)); LuaCallSupport.PushOptional(L, LuaOptional.Of(6L)); if (!LuaCallSupport.TryReadOptional(L, 1, out LuaOptional value) - || !LuaCallSupport.ReadResults(L, 1, buffer, out int count).IsSuccess - || count != 2) + || !LuaCallSupport.ReadResults(L, 1, buffer, out int count).IsSuccess + || count != 2) { throw new InvalidOperationException("wrong read"); } diff --git a/tests/CheatEngine.SDK.Lua.Tests/Generated/MemoryBindings.cs b/tests/CheatEngine.SDK.Lua.Tests/Generated/MemoryBindings.cs index 194a1a52..9bc11a9f 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Generated/MemoryBindings.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Generated/MemoryBindings.cs @@ -49,7 +49,7 @@ private static partial bool TryReadInt32Raw(nuint address, bool signed, out int LuaState L = LuaRuntime.AcquireState(); // one state acquisition per operation int top = L.Top; // explicit settop: no EH region on the success path if (!LuaGlobalFunctions.TryPush(L, s_readInteger, - "readInteger"u8)) // rawgeti on the cached ref; resolve + type-check + luaL_ref on first use + "readInteger"u8)) // rawgeti on the cached ref; resolve + type-check + luaL_ref on first use { return LuaCallSupport.Fail(L, top, out value); // cold, NoInlining: restore top, default the result } diff --git a/tests/CheatEngine.SDK.Lua.Tests/Protected/NativeFailureProcessTests.cs b/tests/CheatEngine.SDK.Lua.Tests/Protected/NativeFailureProcessTests.cs index 4feb335e..28089e69 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/Protected/NativeFailureProcessTests.cs +++ b/tests/CheatEngine.SDK.Lua.Tests/Protected/NativeFailureProcessTests.cs @@ -150,12 +150,12 @@ public async Task Every_catalogued_raising_operation_reports_its_failure_marker( } Assert.True(operation.TryGetProperty("failureEvidence", out JsonElement evidence) && - evidence.GetArrayLength() > 0, + evidence.GetArrayLength() > 0, $"Protected operation {id} can raise but names no failure evidence."); foreach (JsonElement item in evidence.EnumerateArray()) { if (string.Equals(item.GetProperty("kind").GetString(), "FailureProbeMarker", - StringComparison.Ordinal)) + StringComparison.Ordinal)) { markers.Add(item.GetProperty("marker").GetString()!); } @@ -175,8 +175,8 @@ private static JsonDocument LoadCatalogue() { const string ResourceName = "CheatEngine.SDK.Lua.Tests.ProtectedOperations.json"; using Stream stream = typeof(NativeFailureProcessTests).Assembly.GetManifestResourceStream(ResourceName) - ?? throw new InvalidOperationException( - $"The embedded resource {ResourceName} is missing."); + ?? throw new InvalidOperationException( + $"The embedded resource {ResourceName} is missing."); return JsonDocument.Parse(stream); } diff --git a/tests/CheatEngine.SDK.Lua.Tests/packages.lock.json b/tests/CheatEngine.SDK.Lua.Tests/packages.lock.json index be8d8b17..8db749f6 100644 --- a/tests/CheatEngine.SDK.Lua.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.Lua.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.Testing.Extensions.CodeCoverage": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.NativeAotLibraryProbe/packages.lock.json b/tests/CheatEngine.SDK.NativeAotLibraryProbe/packages.lock.json index d4ea7a8d..42b84e54 100644 --- a/tests/CheatEngine.SDK.NativeAotLibraryProbe/packages.lock.json +++ b/tests/CheatEngine.SDK.NativeAotLibraryProbe/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.DotNet.ILCompiler": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/LibraryProbeContractTests.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/LibraryProbeContractTests.cs index 1ea12dbe..b3cca7ff 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/LibraryProbeContractTests.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/LibraryProbeContractTests.cs @@ -40,7 +40,7 @@ public void Refuses_a_CEPlugin_export_read_from_the_bytes_of_a_patched_image() Assert.Contains("CEPlugin_GetVersion", names, StringComparer.Ordinal); Assert.Contains(LibraryProbeContract.FindViolations(names), static violation => violation.Contains("'CEPlugin_GetVersion'", StringComparison.Ordinal) && - violation.Contains("native-plugin entry point", StringComparison.Ordinal)); + violation.Contains("native-plugin entry point", StringComparison.Ordinal)); } [Theory] diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/Support/BridgeImage.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/Support/BridgeImage.cs index 202ec915..551b39aa 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/Support/BridgeImage.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/Support/BridgeImage.cs @@ -32,8 +32,8 @@ public static IReadOnlyList ExportNames public static byte[] Load() { using Stream stream = typeof(BridgeImage).Assembly.GetManifestResourceStream(ResourceName) - ?? throw new InvalidOperationException( - $"The embedded resource {ResourceName} is missing."); + ?? throw new InvalidOperationException( + $"The embedded resource {ResourceName} is missing."); using MemoryStream copy = new(); stream.CopyTo(copy); return copy.ToArray(); diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/packages.lock.json b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/packages.lock.json index fe279b25..b254c5b5 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.Testing.Extensions.CodeCoverage": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness/LibraryProbeContract.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness/LibraryProbeContract.cs index 1b2e7500..11f91a64 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness/LibraryProbeContract.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness/LibraryProbeContract.cs @@ -54,8 +54,8 @@ internal static IReadOnlyList FindViolations(IReadOnlyList expor foreach (string exportName in exportNames) { if (!exportName.StartsWith(NativePluginPrefix, StringComparison.Ordinal) && - !Contains(NativeAotLibraryProbeExportNames.Required, exportName) && - !Contains(AllowedRuntimeExports, exportName)) + !Contains(NativeAotLibraryProbeExportNames.Required, exportName) && + !Contains(AllowedRuntimeExports, exportName)) { violations.Add($"The file exposes the unexpected export '{exportName}'."); } diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness/Program.cs b/tests/CheatEngine.SDK.NativeAotLoaderHarness/Program.cs index 47630394..a7711af1 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness/Program.cs +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness/Program.cs @@ -45,7 +45,7 @@ private static int Run(string[] arguments) } if (arguments.Length == 2 && string.Equals(arguments[0], LoadMode, StringComparison.Ordinal) && - string.Equals(arguments[1], AcknowledgeProcessResidentLoad, StringComparison.Ordinal)) + string.Equals(arguments[1], AcknowledgeProcessResidentLoad, StringComparison.Ordinal)) { LoadAndQueryNames(); return 0; diff --git a/tests/CheatEngine.SDK.NativeAotLoaderHarness/packages.lock.json b/tests/CheatEngine.SDK.NativeAotLoaderHarness/packages.lock.json index 254741a9..b22b07c7 100644 --- a/tests/CheatEngine.SDK.NativeAotLoaderHarness/packages.lock.json +++ b/tests/CheatEngine.SDK.NativeAotLoaderHarness/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "MinVer": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.QualificationTarget/ImageScanner.cs b/tests/CheatEngine.SDK.QualificationTarget/ImageScanner.cs index d31579b1..93c2a56c 100644 --- a/tests/CheatEngine.SDK.QualificationTarget/ImageScanner.cs +++ b/tests/CheatEngine.SDK.QualificationTarget/ImageScanner.cs @@ -16,7 +16,7 @@ internal static (nint Base, int Size) MainImage() { using Process process = Process.GetCurrentProcess(); ProcessModule module = process.MainModule - ?? throw new InvalidOperationException("The main module is not available."); + ?? throw new InvalidOperationException("The main module is not available."); return (module.BaseAddress, module.ModuleMemorySize); } diff --git a/tests/CheatEngine.SDK.QualificationTarget/Program.cs b/tests/CheatEngine.SDK.QualificationTarget/Program.cs index df188a5d..33cd9243 100644 --- a/tests/CheatEngine.SDK.QualificationTarget/Program.cs +++ b/tests/CheatEngine.SDK.QualificationTarget/Program.cs @@ -82,7 +82,7 @@ private static bool TryParse(string[] args, out int heapCopies, out int repetiti break; default: error = "Invalid argument '" + args[index] + - "'. Use --heap-copies 1-1024, --repetitions 1-1000000 and --ready-file PATH."; + "'. Use --heap-copies 1-1024, --repetitions 1-1000000 and --ready-file PATH."; return false; } } @@ -93,6 +93,6 @@ private static bool TryParse(string[] args, out int heapCopies, out int repetiti private static bool TryRange(string? text, int minimum, int maximum, out int value) { return int.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out value) && value >= minimum && - value <= maximum; + value <= maximum; } } diff --git a/tests/CheatEngine.SDK.QualificationTarget/packages.lock.json b/tests/CheatEngine.SDK.QualificationTarget/packages.lock.json index 12907abb..35f0a982 100644 --- a/tests/CheatEngine.SDK.QualificationTarget/packages.lock.json +++ b/tests/CheatEngine.SDK.QualificationTarget/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.DotNet.ILCompiler": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryDocumentTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryDocumentTests.cs index ca3eca61..13b3da97 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryDocumentTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Abi/ClassicSlotRegistryDocumentTests.cs @@ -239,7 +239,7 @@ .. divergences.Where(static row => // Lot observations are extra rows, never replacements: each is a source observation of the pinned source. foreach (JsonElement row in divergences.Where(static row => - string.Equals(row.GetProperty("origin").GetString(), "LotObservation", StringComparison.Ordinal))) + string.Equals(row.GetProperty("origin").GetString(), "LotObservation", StringComparison.Ordinal))) { Assert.Equal("ObservedSource", row.GetProperty("evidenceKind").GetString()); } @@ -277,7 +277,7 @@ .. slotsById.Where(pair => pair.Value.Contains(index)).Select(static pair => pai // D12: every slot of the cell section that the host assigns a direct @ expression (not @@, not nil). int[] direct = SlotsWhere(static slot => slot.GetProperty("slot").GetInt32() is >= 18 and <= 81 && - IsKind(slot, "FunctionAddress")); + IsKind(slot, "FunctionAddress")); Assert.Equal(direct, slotsById["D12"]); } @@ -360,7 +360,7 @@ public void Authority_is_plugin_pas_and_mirrors_carry_their_hashes() Assert.Equal("ObservedSource", slot.GetProperty("evidenceKind").GetString()); }); Assert.All(Slots.Where(static slot => IsKind(slot, "FunctionAddress") && - slot.GetProperty("hostImplementation").ValueKind == JsonValueKind.Null), + slot.GetProperty("hostImplementation").ValueKind == JsonValueKind.Null), static slot => Assert.Equal("ToQualify", slot.GetProperty("evidenceKind").GetString())); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Abi/NativeAotProfileDocumentTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Abi/NativeAotProfileDocumentTests.cs index fd06fbc4..0d9b3b6c 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Abi/NativeAotProfileDocumentTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Abi/NativeAotProfileDocumentTests.cs @@ -28,10 +28,10 @@ public void NativeAot_profile_page_cites_the_microsoft_unload_restriction_and_li StringComparison.Ordinal); Assert.Contains("LocalModified", page, StringComparison.Ordinal); foreach (string profile in (string[]) - [ - "| Historical CLR route", "| **Managed hostfxr route**", "| NativeAOT plugin DLL", - "| Classic native plugin exporting `CEPlugin_*`", "| x86 or ARM64 host" - ]) + [ + "| Historical CLR route", "| **Managed hostfxr route**", "| NativeAOT plugin DLL", + "| Classic native plugin exporting `CEPlugin_*`", "| x86 or ARM64 host" + ]) { Assert.Contains(profile, page, StringComparison.Ordinal); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Abi/RepositoryDocument.cs b/tests/CheatEngine.SDK.Repository.Tests/Abi/RepositoryDocument.cs index fb3eb955..48aabcc3 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Abi/RepositoryDocument.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Abi/RepositoryDocument.cs @@ -67,7 +67,10 @@ public static string Canonical(JsonElement element) { JsonWriterOptions writerOptions = new() { - Indented = true, IndentSize = 2, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, NewLine = "\n" + Indented = true, + IndentSize = 2, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + NewLine = "\n" }; using MemoryStream stream = new(); using (Utf8JsonWriter writer = new(stream, writerOptions)) diff --git a/tests/CheatEngine.SDK.Repository.Tests/ApiGates/ApiGateDiagnosticTests.cs b/tests/CheatEngine.SDK.Repository.Tests/ApiGates/ApiGateDiagnosticTests.cs index 45d1fa04..3b2657c7 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/ApiGates/ApiGateDiagnosticTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/ApiGates/ApiGateDiagnosticTests.cs @@ -159,7 +159,7 @@ private static List LoadShippingAssemblies() List assemblies = []; foreach (string dll in Directory.EnumerateFiles(directory, "CheatEngine.SDK*.dll", - SearchOption.TopDirectoryOnly)) + SearchOption.TopDirectoryOnly)) { assemblies.Add(Assembly.LoadFrom(dll)); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Diagnostics/ApiDiagnosticIdTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Diagnostics/ApiDiagnosticIdTests.cs index c0c5c38e..7f52ab7b 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Diagnostics/ApiDiagnosticIdTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Diagnostics/ApiDiagnosticIdTests.cs @@ -39,8 +39,8 @@ public void the_source_scan_finds_the_declared_api_diagnostic_ids() IReadOnlyList ids = ScanApiDiagnosticIds(); Assert.Contains(ids, static id => id is { Kind: ApiDiagnosticKind.Obsolete, Id: "CESDK7001" } && - string.Equals(id.File, "libs/CheatEngine.SDK.Engine/Runtime/PointerSize.cs", - StringComparison.Ordinal)); + string.Equals(id.File, "libs/CheatEngine.SDK.Engine/Runtime/PointerSize.cs", + StringComparison.Ordinal)); } [Fact] @@ -241,7 +241,7 @@ private static List ScanApiDiagnosticIds() foreach (string file in RepositoryRoot.EnumerateSourceFiles("*.cs")) { if (!file.StartsWith("libs/", StringComparison.Ordinal) && - !file.StartsWith("src/", StringComparison.Ordinal)) + !file.StartsWith("src/", StringComparison.Ordinal)) { continue; } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Generation/GeneratorInventoryTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Generation/GeneratorInventoryTests.cs index ba31960c..0d2ee319 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Generation/GeneratorInventoryTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Generation/GeneratorInventoryTests.cs @@ -89,8 +89,8 @@ public void Generators_never_embed_a_local_cheat_engine_path() { string text = Read(path); if (text.Contains("Program Files", StringComparison.OrdinalIgnoreCase) || - text.Contains("celua.txt", StringComparison.OrdinalIgnoreCase) || - DriveRootedPath().IsMatch(text)) + text.Contains("celua.txt", StringComparison.OrdinalIgnoreCase) || + DriveRootedPath().IsMatch(text)) { offences.Add(path); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/DependabotConfigurationTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/DependabotConfigurationTests.cs index 1879ca6e..26f4eaeb 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/DependabotConfigurationTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/DependabotConfigurationTests.cs @@ -52,8 +52,8 @@ public void Every_ecosystem_has_a_cooldown_of_at_least_seven_days() { string? value = YamlDocument.Scalar(cooldown, key); if (value is not null && - (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out int days) || - days < MinimumCooldownDays)) + (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out int days) || + days < MinimumCooldownDays)) { problems.Add($"{ecosystem}: {key} is {value}"); } @@ -96,7 +96,7 @@ public void Roslyn_ignores_cover_every_package_pinned_to_the_roslyn_floor() { string id = (string?) version.Attribute("Include") ?? ""; if (id.StartsWith("Microsoft.CodeAnalysis.", StringComparison.Ordinal) - && string.Equals((string?) version.Attribute("Version"), floor, StringComparison.Ordinal)) + && string.Equals((string?) version.Attribute("Version"), floor, StringComparison.Ordinal)) { pinnedToFloor.Add(id); } @@ -120,8 +120,8 @@ public void Dotnet_sdk_ecosystem_ignores_major_updates() foreach (YamlMappingNode rule in YamlDocument.Mappings(sdk, "ignore")) { if (string.Equals(YamlDocument.Scalar(rule, "dependency-name"), "*", StringComparison.Ordinal) - && YamlDocument.Scalars(rule, "update-types") - .Contains("version-update:semver-major", StringComparer.Ordinal)) + && YamlDocument.Scalars(rule, "update-types") + .Contains("version-update:semver-major", StringComparer.Ordinal)) { ignoresMajor = true; } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceDocumentTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceDocumentTests.cs index 894c5418..d3e9f64d 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceDocumentTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceDocumentTests.cs @@ -279,8 +279,8 @@ public void Issue_forms_never_instruct_editing_the_cheat_engine_runtime_configur foreach (string sentence in Sentences(text)) { if (sentence.Contains("runtimeconfig", StringComparison.OrdinalIgnoreCase) - && EditInstruction().IsMatch(sentence) - && !NegationPattern().IsMatch(sentence)) + && EditInstruction().IsMatch(sentence) + && !NegationPattern().IsMatch(sentence)) { offenders.Add($"{path}: '{sentence}'"); } @@ -302,7 +302,7 @@ private static List Level2Headings(string text) string line = rawLine.TrimEnd(); string trimmedStart = line.TrimStart(); if (trimmedStart.StartsWith("```", StringComparison.Ordinal) || - trimmedStart.StartsWith("~~~", StringComparison.Ordinal)) + trimmedStart.StartsWith("~~~", StringComparison.Ordinal)) { inFence = !inFence; continue; diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceWorkflowTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceWorkflowTests.cs index 18e79c7b..ba9f6680 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceWorkflowTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/GovernanceWorkflowTests.cs @@ -31,8 +31,8 @@ public void Governance_workflows_pin_every_action_by_full_sha_with_a_version_com { Match uses = UsesLine().Match(lines[i]); if (uses.Success && !uses.Groups["reference"].Value.StartsWith("./", StringComparison.Ordinal) - && !(PinnedReference().IsMatch(uses.Groups["reference"].Value) - && VersionComment().IsMatch(uses.Groups["comment"].Value))) + && !(PinnedReference().IsMatch(uses.Groups["reference"].Value) + && VersionComment().IsMatch(uses.Groups["comment"].Value))) { offenders.Add($"{path}:{i + 1}: {lines[i].Trim()}"); } @@ -82,7 +82,7 @@ public void Governance_workflows_start_read_only_and_comment_every_job_elevation string name = ((YamlScalarNode) scope.Key).Value ?? ""; string access = ((YamlScalarNode) scope.Value).Value ?? ""; if (string.Equals(name, "contents", StringComparison.Ordinal) - && string.Equals(access, "read", StringComparison.Ordinal)) + && string.Equals(access, "read", StringComparison.Ordinal)) { continue; } @@ -131,7 +131,7 @@ public void Governance_multi_line_scripts_stop_on_the_first_error() string[] lines = (YamlDocument.Scalar(step, "run") ?? "").ReplaceLineEndings("\n").Trim() .Split('\n'); if (lines.Length > 1 && !string.Equals(lines[0].Trim(), "$ErrorActionPreference = 'Stop'", - StringComparison.Ordinal)) + StringComparison.Ordinal)) { offenders.Add($"{path} job {job.Key} step '{YamlDocument.Scalar(step, "name")}'"); } @@ -170,7 +170,7 @@ public void Governance_scripts_check_the_exit_code_of_every_native_command() } if (next >= lines.Length || !lines[next].TrimStart() - .StartsWith("if ($LASTEXITCODE -ne 0)", StringComparison.Ordinal)) + .StartsWith("if ($LASTEXITCODE -ne 0)", StringComparison.Ordinal)) { offenders.Add($"{path} job {job.Key}: '{lines[i].Trim()}'"); } @@ -289,11 +289,11 @@ public void Codeql_csharp_job_builds_the_product_graph_manually_without_shared_c YamlMappingNode build = Assert.Single(steps, static step => YamlDocument.Scalar(step, "run") is not null); string run = YamlDocument.NormalizeWhitespace(YamlDocument.Scalar(build, "run")!); foreach (string fragment in (string[]) - [ - "dotnet build src/CheatEngine.SDK/CheatEngine.SDK.csproj", "-c Release", "--no-restore", - "--no-incremental", - "--disable-build-servers", "-p:UseSharedCompilation=false", "$LASTEXITCODE" - ]) + [ + "dotnet build src/CheatEngine.SDK/CheatEngine.SDK.csproj", "-c Release", "--no-restore", + "--no-incremental", + "--disable-build-servers", "-p:UseSharedCompilation=false", "$LASTEXITCODE" + ]) { Assert.Contains(fragment, run, StringComparison.Ordinal); } @@ -383,7 +383,7 @@ public void Scorecard_steps_use_only_the_actions_the_verifier_allows() "github/codeql-action/upload-sarif", "step-security/harden-runner" ]; foreach (YamlMappingNode step in YamlDocument.Steps(YamlDocument.Load(GovernanceWorkflows.Scorecard) - .Job("analysis"))) + .Job("analysis"))) { string uses = YamlDocument.Uses(step) ?? ""; string action = uses.Split('@')[0]; @@ -414,7 +414,7 @@ public void Only_the_scorecard_job_requests_an_id_token() foreach (string holder in holders) { Assert.True(string.Equals(holder, GovernanceWorkflows.Scorecard + "#analysis", StringComparison.Ordinal) - || holder.StartsWith(".github/workflows/release.yml#", StringComparison.Ordinal), + || holder.StartsWith(".github/workflows/release.yml#", StringComparison.Ordinal), $"{holder} requests an id-token; only the Scorecard analysis job and the release workflow may."); } @@ -491,8 +491,8 @@ public void Only_the_dependency_submit_job_holds_contents_write() foreach (KeyValuePair job in YamlDocument.Load(path).Jobs) { if (YamlDocument.Permissions(job.Value) is { } permissions - && permissions.TryGetValue("contents", out string? access) - && string.Equals(access, "write", StringComparison.Ordinal)) + && permissions.TryGetValue("contents", out string? access) + && string.Equals(access, "write", StringComparison.Ordinal)) { writers.Add($"{path}#{job.Key}"); } @@ -568,32 +568,7 @@ public async Task Dependency_submit_step_submits_only_a_snapshot_of_this_run(str const string Ref = "refs/heads/main"; using TemporaryDirectory directory = new(); Directory.CreateDirectory(directory.File("snapshot")); - Dictionary snapshot = new(StringComparer.Ordinal) - { - ["version"] = 0, - ["sha"] = Is(variant, "other_commit") ? new string('f', 40) : Sha, - ["ref"] = Is(variant, "other_ref") ? "refs/heads/feature" : Ref, - ["job"] = new Dictionary(StringComparer.Ordinal) - { - ["correlator"] = Is(variant, "other_correlator") ? "other" : "sdk-nuget", ["id"] = "1" - }, - ["detector"] = - new Dictionary(StringComparer.Ordinal) - { - ["name"] = "d", ["version"] = "1", ["url"] = "u" - }, - ["scanned"] = "2026-09-23T00:00:00Z", - ["manifests"] = Is(variant, "no_manifest") - ? new Dictionary(StringComparer.Ordinal) - : new Dictionary(StringComparer.Ordinal) - { - ["src/A.csproj"] = new Dictionary(StringComparer.Ordinal) - } - }; - if (Is(variant, "extra_property")) - { - snapshot["extra"] = 1; - } + Dictionary snapshot = BuildDependencySnapshot(variant, Sha, Ref); await File.WriteAllTextAsync(directory.File("snapshot/snapshot.json"), JsonSerializer.Serialize(snapshot), TestContext.Current.CancellationToken); @@ -602,8 +577,8 @@ await File.WriteAllTextAsync(directory.File("snapshot/snapshot.json"), JsonSeria YamlDocument.Steps(YamlDocument.Load(GovernanceWorkflows.DependencySubmission).Job("submit"))[1]; string marker = directory.File("gh-called.txt"); string script = $"Set-Location -LiteralPath {PwshScript.Quote(directory.Path)}" + Environment.NewLine + - $"function gh {{ $args -join ' ' | Set-Content -LiteralPath {PwshScript.Quote(marker)}; $global:LASTEXITCODE = 0 }}" + - Environment.NewLine + YamlDocument.Scalar(submit, "run"); + $"function gh {{ $args -join ' ' | Set-Content -LiteralPath {PwshScript.Quote(marker)}; $global:LASTEXITCODE = 0 }}" + + Environment.NewLine + YamlDocument.Scalar(submit, "run"); Dictionary environment = new(StringComparer.Ordinal) { ["REPOSITORY"] = "CheatEngineNet/CheatEngine.SDK", @@ -633,11 +608,46 @@ private static bool Is(string value, string expected) return string.Equals(value, expected, StringComparison.Ordinal); } + private static Dictionary BuildDependencySnapshot(string variant, string sha, string @ref) + { + Dictionary snapshot = new(StringComparer.Ordinal) + { + ["version"] = 0, + ["sha"] = Is(variant, "other_commit") ? new string('f', 40) : sha, + ["ref"] = Is(variant, "other_ref") ? "refs/heads/feature" : @ref, + ["job"] = new Dictionary(StringComparer.Ordinal) + { + ["correlator"] = Is(variant, "other_correlator") ? "other" : "sdk-nuget", + ["id"] = "1" + }, + ["detector"] = + new Dictionary(StringComparer.Ordinal) + { + ["name"] = "d", + ["version"] = "1", + ["url"] = "u" + }, + ["scanned"] = "2026-09-23T00:00:00Z", + ["manifests"] = Is(variant, "no_manifest") + ? new Dictionary(StringComparer.Ordinal) + : new Dictionary(StringComparer.Ordinal) + { + ["src/A.csproj"] = new Dictionary(StringComparer.Ordinal) + } + }; + if (Is(variant, "extra_property")) + { + snapshot["extra"] = 1; + } + + return snapshot; + } + private static YamlNode? WithOf(YamlMappingNode job, string action) { YamlMappingNode step = Assert.Single(YamlDocument.Steps(job), step => YamlDocument.UsesAction(step, action) - || string.Equals(YamlDocument.Uses(step), - action, StringComparison.Ordinal)); + || string.Equals(YamlDocument.Uses(step), + action, StringComparison.Ordinal)); return YamlDocument.Child(step, "with"); } @@ -646,7 +656,7 @@ private static int IndexOf(IReadOnlyList steps, string action) for (int i = 0; i < steps.Count; i++) { if (YamlDocument.UsesAction(steps[i], action) - || string.Equals(YamlDocument.Uses(steps[i]), action, StringComparison.Ordinal)) + || string.Equals(YamlDocument.Uses(steps[i]), action, StringComparison.Ordinal)) { return i; } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshScript.cs b/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshScript.cs index fd3253b5..bdd9f3f3 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshScript.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Governance/PwshScript.cs @@ -35,7 +35,7 @@ public static async Task RunTextAsync(string scriptText, using TemporaryDirectory directory = new(); string scriptPath = Path.Combine(directory.Path, "script.ps1"); string preamble = "Set-StrictMode -Version Latest" + Environment.NewLine + - "$ErrorActionPreference = 'Stop'" + Environment.NewLine; + "$ErrorActionPreference = 'Stop'" + Environment.NewLine; await File.WriteAllTextAsync(scriptPath, preamble + scriptText, new UTF8Encoding(false), TestContext.Current.CancellationToken); return await RunFileAsync(scriptPath, [], environment); @@ -86,7 +86,7 @@ public static async Task RunFileAsync(string scriptPath, IReadOnlyLi timeout.CancelAfter(s_timeout); using Process process = Process.Start(startInfo) - ?? throw new InvalidOperationException($"'{startInfo.FileName}' did not start."); + ?? throw new InvalidOperationException($"'{startInfo.FileName}' did not start."); process.StandardInput.Close(); Task standardOutput = process.StandardOutput.ReadToEndAsync(timeout.Token); Task standardError = process.StandardError.ReadToEndAsync(timeout.Token); diff --git a/tests/CheatEngine.SDK.Repository.Tests/HostContract/ConcurrencyContractDocumentationTests.cs b/tests/CheatEngine.SDK.Repository.Tests/HostContract/ConcurrencyContractDocumentationTests.cs index 4b3f54f4..fab5fc93 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/HostContract/ConcurrencyContractDocumentationTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/HostContract/ConcurrencyContractDocumentationTests.cs @@ -25,12 +25,12 @@ public void Sources_and_readmes_never_claim_one_runtime_or_load_context_per_plug { List offenders = []; foreach (string relative in RepositoryRoot.EnumerateSourceFiles("*.cs") - .Concat(RepositoryRoot.EnumerateSourceFiles("*.md")) - .Where(static path => (path.StartsWith("libs/", StringComparison.Ordinal) - || path.StartsWith("tests/", StringComparison.Ordinal)) - && !string.Equals(path, SelfPath, StringComparison.Ordinal)) - .Distinct(StringComparer.Ordinal) - .Order(StringComparer.Ordinal)) + .Concat(RepositoryRoot.EnumerateSourceFiles("*.md")) + .Where(static path => (path.StartsWith("libs/", StringComparison.Ordinal) + || path.StartsWith("tests/", StringComparison.Ordinal)) + && !string.Equals(path, SelfPath, StringComparison.Ordinal)) + .Distinct(StringComparer.Ordinal) + .Order(StringComparer.Ordinal)) { string text = File.ReadAllText(Path.Combine(RepositoryRoot.Path, relative)); foreach (Match match in UnqualifiedCardinalityClaim.Matches(text)) diff --git a/tests/CheatEngine.SDK.Repository.Tests/Infrastructure/RepositoryRoot.cs b/tests/CheatEngine.SDK.Repository.Tests/Infrastructure/RepositoryRoot.cs index 69741d72..d561edb2 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Infrastructure/RepositoryRoot.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Infrastructure/RepositoryRoot.cs @@ -51,8 +51,8 @@ private static bool IsExcluded(string relativePath) private static string FindRoot() { for (DirectoryInfo? directory = new(AppContext.BaseDirectory); - directory is not null; - directory = directory.Parent) + directory is not null; + directory = directory.Parent) { if (File.Exists(System.IO.Path.Combine(directory.FullName, SolutionFileName))) { diff --git a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaInteropPrimitiveMatrixDocumentTests.cs b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaInteropPrimitiveMatrixDocumentTests.cs index 8d37f94f..707bf018 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaInteropPrimitiveMatrixDocumentTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/LuaInteropPrimitiveMatrixDocumentTests.cs @@ -183,7 +183,7 @@ private static void CheckRoute(JsonElement row, HashSet operations, List } if (string.Equals(decision, "BridgeRequired", StringComparison.Ordinal) && bridge is null && - !string.Equals(member, "lua_error", StringComparison.Ordinal)) + !string.Equals(member, "lua_error", StringComparison.Ordinal)) { problems.Add( $"{member}: BridgeRequired names no bridge operation (only lua_error, raised by the bridge's C code, may)."); @@ -225,12 +225,12 @@ private static void CheckProvenance(JsonElement row, Dictionary ProductionSources() { return RepositoryRoot.EnumerateSourceFiles("*.cs") .Where(static file => file.StartsWith("libs/", StringComparison.Ordinal) && - !file.StartsWith(RawApiDirectory, StringComparison.Ordinal)) + !file.StartsWith(RawApiDirectory, StringComparison.Ordinal)) .Order(StringComparer.Ordinal); } } diff --git a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/ProtectedOperationCatalogTests.cs b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/ProtectedOperationCatalogTests.cs index fcae737e..a7e20e32 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/ProtectedOperationCatalogTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/LuaBridge/ProtectedOperationCatalogTests.cs @@ -123,7 +123,7 @@ public void Direct_api_policy_routes_are_exclusive_explicit_and_never_direct_for } if (policy.TryGetProperty("conditionalDirectUse", out JsonElement conditional) && - (direct || !bridge || !conditional.GetProperty("allowed").GetBoolean())) + (direct || !bridge || !conditional.GetProperty("allowed").GetBoolean())) { problems.Add( $"{symbol}: a conditional direct use keeps the bridge as its default route and opts in explicitly."); @@ -144,7 +144,7 @@ public void Every_raising_operation_names_a_failure_test() bool raises = !string.Equals(operation.GetProperty("raises").GetString(), "never", StringComparison.Ordinal); if (raises && (!operation.TryGetProperty("failureEvidence", out JsonElement evidence) || - evidence.GetArrayLength() == 0)) + evidence.GetArrayLength() == 0)) { problems.Add($"{id} can raise but names no failure evidence (a failure-probe marker or a Q13 test)."); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Ownership/OwnershipPolicyTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Ownership/OwnershipPolicyTests.cs index c27e7b55..0667ce1d 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Ownership/OwnershipPolicyTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Ownership/OwnershipPolicyTests.cs @@ -40,12 +40,12 @@ public void No_shipping_library_binds_delete_all_registered_symbols() foreach (string file in RepositoryRoot.EnumerateSourceFiles("*")) { bool shippingCode = (file.StartsWith("libs/", StringComparison.Ordinal) || - file.StartsWith("src/", StringComparison.Ordinal)) && - file.EndsWith(".cs", StringComparison.Ordinal); + file.StartsWith("src/", StringComparison.Ordinal)) && + file.EndsWith(".cs", StringComparison.Ordinal); bool generatorSpec = file.StartsWith("source-generators/", StringComparison.Ordinal) && - file.Contains("/Specs/", StringComparison.Ordinal); + file.Contains("/Specs/", StringComparison.Ordinal); if ((shippingCode || generatorSpec) && - File.ReadAllText(Absolute(file)).Contains(DeleteAllRegisteredSymbols, StringComparison.Ordinal)) + File.ReadAllText(Absolute(file)).Contains(DeleteAllRegisteredSymbols, StringComparison.Ordinal)) { offenders.Add(file); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/EnumContractTests.cs b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/EnumContractTests.cs index eeb907a4..6d15c9d0 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/EnumContractTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/EnumContractTests.cs @@ -125,7 +125,7 @@ public void Enums_mirroring_cheat_engine_constants_or_client_signatures_keep_the foreach (string added in library.Added) { if (IsMemberOfFrozenEnum(added, out string enumType) - && PublicApiDeclarations.TryParseEnumMember(added, out _, out string member, out _)) + && PublicApiDeclarations.TryParseEnumMember(added, out _, out string member, out _)) { Assert.True(s_reviewedFrozenEnumAdditions.Contains($"{enumType}.{member}"), $"{library.UnshippedPath}: '{added}' adds a member to the frozen enum {enumType} without a reviewed entry."); @@ -212,7 +212,7 @@ private static Dictionary> EnumMembers( foreach (string line in lines(library)) { if (PublicApiDeclarations.TryParseEnumMember(line, out string enumType, out string member, - out long value)) + out long value)) { if (!enums.TryGetValue(enumType, out SortedDictionary? members)) { diff --git a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiDeclarations.cs b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiDeclarations.cs index ddfea00a..cae772db 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiDeclarations.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiDeclarations.cs @@ -90,7 +90,7 @@ public static IReadOnlySet CandidateKeysOf(string docId) keys.Add($"{type}.{SimpleName(type)}"); break; case 'M' when member.StartsWith("get_", StringComparison.Ordinal) - || member.StartsWith("set_", StringComparison.Ordinal): + || member.StartsWith("set_", StringComparison.Ordinal): AddPropertyKeys(keys, type, accessorName); break; case 'M' when member.StartsWith("add_", StringComparison.Ordinal): diff --git a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiLibrary.cs b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiLibrary.cs index f7b66036..7ad821fd 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiLibrary.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/PublicApi/PublicApiLibrary.cs @@ -113,7 +113,7 @@ public static IReadOnlyList LoadAll() foreach (string directory in EnumerateLibraryDirectories()) { if (File.Exists(FullPath($"{directory}/{ShippedFileName}")) - && File.Exists(FullPath($"{directory}/{UnshippedFileName}"))) + && File.Exists(FullPath($"{directory}/{UnshippedFileName}"))) { libraries.Add(new PublicApiLibrary(directory)); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflowContractTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflowContractTests.cs index ba5a4531..07160c30 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflowContractTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Release/ReleaseWorkflowContractTests.cs @@ -102,8 +102,8 @@ public void Publication_jobs_run_only_for_tags_of_this_repository() foreach (YamlMappingNode step in ReleaseWorkflow.Steps(attest)) { bool signsOrVerifies = attestations.Contains(step) - || (ReleaseWorkflow.Scalar(step, "run") ?? "").Contains("gh attestation verify", - StringComparison.Ordinal); + || (ReleaseWorkflow.Scalar(step, "run") ?? "").Contains("gh attestation verify", + StringComparison.Ordinal); if (signsOrVerifies) { Assert.Equal(TagGuard, ReleaseWorkflow.Normalize(ReleaseWorkflow.Scalar(step, "if"))); @@ -209,7 +209,7 @@ public void Release_is_created_as_a_draft_and_published_only_by_finalize() bool creates = run.Contains("gh release create", StringComparison.Ordinal); bool edits = run.Contains("gh release edit", StringComparison.Ordinal); bool clobbers = run.Contains("--clobber", StringComparison.Ordinal) && - run.Contains("gh release upload", StringComparison.Ordinal); + run.Contains("gh release upload", StringComparison.Ordinal); bool publishes = run.Contains("--draft=false", StringComparison.Ordinal); Assert.True(!creates || id is "draft-release", $"Job '{id}' creates a release; only 'draft-release' may."); Assert.True(!edits || id is "finalize-release", @@ -296,8 +296,8 @@ public void Release_jobs_have_a_timeout_and_a_pinned_runner() string? runsOn = ReleaseWorkflow.Scalar(job, "runs-on"); Assert.True(runsOn is not null && s_runnerLabels.Contains(runsOn), $"Job '{id}' runs on '{runsOn}'."); Assert.True(int.TryParse(ReleaseWorkflow.Scalar(job, "timeout-minutes"), NumberStyles.None, - CultureInfo.InvariantCulture, out int minutes) - && minutes is > 0 and <= 60, + CultureInfo.InvariantCulture, out int minutes) + && minutes is > 0 and <= 60, $"Job '{id}' needs a timeout-minutes between 1 and 60."); } } @@ -363,7 +363,7 @@ private static void AssertWriteScope(string scope, string[] allowed) foreach (string id in Ids()) { if (ReleaseWorkflow.Permissions(workflow.Job(id)).TryGetValue(scope, out string? value) - && string.Equals(value, "write", StringComparison.Ordinal)) + && string.Equals(value, "write", StringComparison.Ordinal)) { granted.Add(id); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Runtime/RuntimeCapabilitySpecTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Runtime/RuntimeCapabilitySpecTests.cs index 6bab619b..6cc815a2 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Runtime/RuntimeCapabilitySpecTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Runtime/RuntimeCapabilitySpecTests.cs @@ -123,7 +123,7 @@ public void target_backend_members_are_the_readme_backend_rows_and_only_local_pr SortedSet rows = new(StringComparer.Ordinal); List qualified = []; foreach (string[] cells in BackendTableRows( - File.ReadAllLines(Path.Combine(RepositoryRoot.Path, EngineReadmePath)))) + File.ReadAllLines(Path.Combine(RepositoryRoot.Path, EngineReadmePath)))) { string backend = cells[0].Trim('`'); Assert.True(rows.Add(backend), $"Duplicate backend row {backend}."); @@ -158,7 +158,7 @@ private static List BackendTableRows(string[] lines) string[] cells = Cells(lines[index]); if (string.Equals(cells[0], "Backend", StringComparison.Ordinal) - && string.Equals(cells[^1], "Qualified backend", StringComparison.Ordinal)) + && string.Equals(cells[^1], "Qualified backend", StringComparison.Ordinal)) { Assert.Equal(-1, header); header = index; diff --git a/tests/CheatEngine.SDK.Repository.Tests/Solution/QualificationHarnessShapeTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Solution/QualificationHarnessShapeTests.cs index cb355de2..e6f46f1d 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Solution/QualificationHarnessShapeTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Solution/QualificationHarnessShapeTests.cs @@ -68,7 +68,7 @@ public void QualificationTarget_references_no_SDK_project() Assert.Empty(project.Descendants("ProjectReference")); Assert.Empty(project.Descendants("PackageReference")); foreach (string source in Directory.EnumerateFiles( - Absolute("tests/CheatEngine.SDK.QualificationTarget"), "*.cs")) + Absolute("tests/CheatEngine.SDK.QualificationTarget"), "*.cs")) { Assert.DoesNotContain("CheatEngine.SDK.", File.ReadAllText(source), StringComparison.Ordinal); } @@ -77,7 +77,7 @@ public void QualificationTarget_references_no_SDK_project() private static XElement Project(string path) { return XDocument.Load(Absolute(path)).Root ?? - throw new InvalidOperationException(path + " has no root element."); + throw new InvalidOperationException(path + " has no root element."); } private static string? Property(XElement project, string name) @@ -116,7 +116,7 @@ private static HashSet SolutionProjects() foreach (XElement project in XDocument.Load(RepositoryRoot.SolutionPath).Descendants("Project")) { if (string.Equals(((string?) project.Attribute("Path"))?.Replace('\\', '/'), projectPath, - StringComparison.Ordinal)) + StringComparison.Ordinal)) { return (string?) project.Element("Platform")?.Attribute("Project"); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Toolchain/ToolchainPinTests.cs b/tests/CheatEngine.SDK.Repository.Tests/Toolchain/ToolchainPinTests.cs index 5fb656a4..6635ed33 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Toolchain/ToolchainPinTests.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Toolchain/ToolchainPinTests.cs @@ -231,7 +231,11 @@ private static HashSet ExpandCodes(XDocument document, string value) private static JsonElement ReadGlobalJsonSdk() { - JsonDocumentOptions options = new() { CommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true }; + JsonDocumentOptions options = new() + { + CommentHandling = JsonCommentHandling.Skip, + AllowTrailingCommas = true + }; using JsonDocument document = JsonDocument.Parse(File.ReadAllText(RepositoryFile(GlobalJson)), options); return document.RootElement.GetProperty("sdk").Clone(); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContract.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContract.cs index d9cf2b13..3f56aaa4 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContract.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContract.cs @@ -151,8 +151,8 @@ public static void AssertNoViolations(string rule, IReadOnlyCollection= 0; - index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) + index >= 0; + index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) { count++; } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Gate.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Gate.cs index df2f5df8..ac13ed51 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Gate.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Gate.cs @@ -31,7 +31,7 @@ public void Callers_invoke_ci_through_job_ci_named_CI() if (string.Equals(job.Uses, PipelineUses, StringComparison.Ordinal)) { Assert.True(string.Equals(job.Id, WorkflowContract.CallerJobId, StringComparison.Ordinal) && - string.Equals(job.Name, WorkflowContract.CallerJobName, StringComparison.Ordinal), + string.Equals(job.Name, WorkflowContract.CallerJobName, StringComparison.Ordinal), $"{job.Location} calls ci.yml; only a job 'ci' named 'CI' may."); } } @@ -206,10 +206,10 @@ public void Sonar_excludes_non_product_trees_from_analysis_and_coverage() HashSet exclusions = new(SonarProperty(begin, "sonar.exclusions").Split(','), StringComparer.Ordinal); foreach (string tree in new[] - { - "artifacts/**", "tests/CheatEngine.SDK.QualificationTarget/**", - "tests/native-host-emulator/**", "eng/tools/**", "docs/**" - }) + { + "artifacts/**", "tests/CheatEngine.SDK.QualificationTarget/**", + "tests/native-host-emulator/**", "eng/tools/**", "docs/**" + }) { Assert.True(exclusions.Contains(tree), $"sonar.exclusions must list {tree}."); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Hygiene.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Hygiene.cs index 80fcdb24..e4a9a711 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Hygiene.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Hygiene.cs @@ -30,7 +30,7 @@ public void Every_job_has_a_timeout_and_a_pinned_runner_label() string? timeout = WorkflowFile.Scalar(job.Node, "timeout-minutes"); if (!int.TryParse(timeout, NumberStyles.None, CultureInfo.InvariantCulture, out int minutes) || - minutes <= 0) + minutes <= 0) { violations.Add(new Violation(workflow.FileName, job.Id, $"{job.Location} has no positive timeout-minutes ('{timeout}').")); @@ -190,7 +190,7 @@ public void Every_native_command_in_a_workflow_script_checks_its_exit_code() } if (next >= lines.Length || - !lines[next].TrimStart().StartsWith("if ($LASTEXITCODE -ne 0)", StringComparison.Ordinal)) + !lines[next].TrimStart().StartsWith("if ($LASTEXITCODE -ne 0)", StringComparison.Ordinal)) { violations.Add(new Violation(file.FileName, subject, $"{file.RelativePath} ({subject}): '{lines[index].Trim()}' must be followed by if ($LASTEXITCODE -ne 0) {{ throw ... }}.")); @@ -260,7 +260,7 @@ public void No_workflow_passes_ApiCompatGenerateSuppressionFile() { // Suppressions are regenerated by the integrator only; CI must fail on an undeclared break instead. Assert.False(file.Text.Contains("ApiCompatGenerateSuppressionFile", StringComparison.OrdinalIgnoreCase) || - file.Text.Contains("GenerateCompatibilitySuppressionFile", StringComparison.OrdinalIgnoreCase), + file.Text.Contains("GenerateCompatibilitySuppressionFile", StringComparison.OrdinalIgnoreCase), $"{file.RelativePath} generates an ApiCompat suppression file; CI must fail on an undeclared break instead."); } } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Restore.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Restore.cs index ac011c8f..af646a79 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Restore.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Restore.cs @@ -105,8 +105,8 @@ public void Every_dotnet_job_uses_the_composite_setup_action() for (int index = 0; index < steps.Count; index++) { if (setupStep < 0 && - string.Equals(WorkflowFile.Scalar(steps[index], "uses"), WorkflowContract.SetupAction, - StringComparison.Ordinal)) + string.Equals(WorkflowFile.Scalar(steps[index], "uses"), WorkflowContract.SetupAction, + StringComparison.Ordinal)) { setupStep = index; } diff --git a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Supply.cs b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Supply.cs index afcc5714..7b69487b 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Supply.cs +++ b/tests/CheatEngine.SDK.Repository.Tests/Workflows/WorkflowContractTests.Supply.cs @@ -52,7 +52,7 @@ public void Dependency_review_configuration_blocks_advisories_and_unreviewed_lic WorkflowFile.ScalarValues(Assert.IsType(WorkflowFile.Sequence(config, "allow-licenses"))), StringComparer.Ordinal); foreach (string purl in WorkflowFile.ScalarValues( - Assert.IsType(WorkflowFile.Sequence(config, "allow-dependencies-licenses")))) + Assert.IsType(WorkflowFile.Sequence(config, "allow-dependencies-licenses")))) { Assert.StartsWith("pkg:nuget/", purl, StringComparison.Ordinal); } diff --git a/tests/CheatEngine.SDK.Repository.Tests/packages.lock.json b/tests/CheatEngine.SDK.Repository.Tests/packages.lock.json index 105b4eff..737cc69e 100644 --- a/tests/CheatEngine.SDK.Repository.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.Repository.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.Testing.Extensions.CodeCoverage": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/DiagnosticsTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/DiagnosticsTests.cs index a63a0b21..be76f1d8 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/DiagnosticsTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/DiagnosticsTests.cs @@ -105,12 +105,12 @@ public void Conflicting_member_and_cache_identities_are_diagnosed_on_both_spec_f run.AssertNoGeneratedSource(); Assert.Contains(run.GeneratorDiagnostics, static diagnostic => string.Equals(diagnostic.Id, "CESDK3002", StringComparison.Ordinal) - && diagnostic.GetMessage(CultureInfo.InvariantCulture) - .Contains("member", StringComparison.Ordinal)); + && diagnostic.GetMessage(CultureInfo.InvariantCulture) + .Contains("member", StringComparison.Ordinal)); Assert.Contains(run.GeneratorDiagnostics, static diagnostic => string.Equals(diagnostic.Id, "CESDK3002", StringComparison.Ordinal) - && diagnostic.GetMessage(CultureInfo.InvariantCulture) - .Contains("cache field", StringComparison.Ordinal)); + && diagnostic.GetMessage(CultureInfo.InvariantCulture) + .Contains("cache field", StringComparison.Ordinal)); AssertConflictLocation(run, "Generated member", "Specs/first.cheatengine-sdk-api.txt", 10, 10); AssertConflictLocation(run, "Generated member", "Specs/second.cheatengine-sdk-api.txt", 10, 10); AssertConflictLocation(run, "Generated cache field", "Specs/first.cheatengine-sdk-api.txt", 9, 10); @@ -160,7 +160,7 @@ public void An_argument_after_an_optional_one_reports_CESDK3004_at_the_argument( { const string Path = "Specs/optional.cheatengine-sdk-api.txt"; string text = SpecSources.Ce77Header("Demo", "Optional") + - "global: g\nmethod: G\nform: throwing\nopt: a:int32\narg: b:int64\nnil: none\ndoc: d.\n"; + "global: g\nmethod: G\nform: throwing\nopt: a:int32\narg: b:int64\nnil: none\ndoc: d.\n"; GeneratorRun run = roslyn.Run(Path, text); @@ -173,7 +173,7 @@ public void A_required_result_after_an_optional_one_reports_CESDK3005_at_the_res { const string Path = "Specs/results.cheatengine-sdk-api.txt"; string text = SpecSources.Ce77Header("Demo", "Results") + - "global: g\nmethod: G\nform: outcome\nopt-result: a:int32\nresult: b:int64\nnil: none\ndoc: d.\n"; + "global: g\nmethod: G\nform: outcome\nopt-result: a:int32\nresult: b:int64\nnil: none\ndoc: d.\n"; GeneratorRun run = roslyn.Run(Path, text); @@ -201,7 +201,7 @@ private static void AssertConflictLocation(GeneratorRun run, string messageFragm foreach (Diagnostic diagnostic in run.GeneratorDiagnostics) { if (!diagnostic.GetMessage(CultureInfo.InvariantCulture) - .Contains(messageFragment, StringComparison.Ordinal)) + .Contains(messageFragment, StringComparison.Ordinal)) { continue; } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EmissionTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EmissionTests.cs index 0bce01d0..d52ea8d6 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EmissionTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EmissionTests.cs @@ -230,7 +230,7 @@ public void Address_arguments_and_try_results_keep_the_complete_public_signature public void Optional_address_argument_is_converted_by_the_facade_without_losing_its_state() { string text = SpecSources.Ce77Header("Demo", "Allocation") + - "global: allocateMemory\nmethod: TryAllocate\nform: try\narg: size:int64\nopt: preferredBaseAddress:address\nopt: protection:int32\nresult: address:address\nnil: expected-failure\ndoc: Allocates.\n"; + "global: allocateMemory\nmethod: TryAllocate\nform: try\narg: size:int64\nopt: preferredBaseAddress:address\nopt: protection:int32\nresult: address:address\nnil: expected-failure\ndoc: Allocates.\n"; GeneratorRun run = roslyn.Run("allocation.cheatengine-sdk-api.txt", text); @@ -256,7 +256,7 @@ public void Optional_address_argument_is_converted_by_the_facade_without_losing_ public void Outcome_form_with_address_results_is_exposed_through_the_facade() { string text = SpecSources.Ce77Header("Demo", "Symbols") + - "global: getAddressSafe\nmethod: ResolveAddress\nform: outcome\narg: expression:string\nresult: address:address\nopt-result: alternate:address\nnil: absence\ndoc: Resolves.\n"; + "global: getAddressSafe\nmethod: ResolveAddress\nform: outcome\narg: expression:string\nresult: address:address\nopt-result: alternate:address\nnil: absence\ndoc: Resolves.\n"; GeneratorRun run = roslyn.Run("symbols.cheatengine-sdk-api.txt", text); @@ -285,7 +285,7 @@ public void Outcome_form_with_address_results_is_exposed_through_the_facade() public void Rest_result_is_a_span_and_a_count_in_the_outcome_form() { string text = SpecSources.Ce77Header("Demo", "Bytes") + - "global: readBytes\nmethod: ReadBytes\nform: outcome\narg: address:address\narg: count:int32\nrest: values:int32\nnil: expected-failure\ndoc: Reads bytes.\n"; + "global: readBytes\nmethod: ReadBytes\nform: outcome\narg: address:address\narg: count:int32\nrest: values:int32\nnil: expected-failure\ndoc: Reads bytes.\n"; GeneratorRun run = roslyn.Run("bytes.cheatengine-sdk-api.txt", text); @@ -332,8 +332,8 @@ public void Memory_scalars_output_is_unchanged_by_the_new_grammar() private static string ExpectedText(string fileName) { using Stream stream = typeof(EmissionTests).Assembly.GetManifestResourceStream( - "CheatEngine.SDK.EngineApi.Tests.Expected." + fileName) - ?? throw new InvalidOperationException("Missing expected text " + fileName + "."); + "CheatEngine.SDK.EngineApi.Tests.Expected." + fileName) + ?? throw new InvalidOperationException("Missing expected text " + fileName + "."); using StreamReader reader = new(stream); return reader.ReadToEnd().ReplaceLineEndings("\n"); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EngineApiDiagnosticCatalogTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EngineApiDiagnosticCatalogTests.cs index b4c9682b..2883a65d 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EngineApiDiagnosticCatalogTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/EngineApiDiagnosticCatalogTests.cs @@ -62,8 +62,8 @@ .. typeof(EngineApiGenerator).Assembly.GetType( private static string RepositoryRoot() { for (DirectoryInfo? directory = new(AppContext.BaseDirectory); - directory is not null; - directory = directory.Parent) + directory is not null; + directory = directory.Parent) { if (File.Exists(Path.Combine(directory.FullName, "CheatEngine.SDK.slnx"))) { diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/IncrementalityTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/IncrementalityTests.cs index e4934c3b..def3f8ca 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/IncrementalityTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Generator/IncrementalityTests.cs @@ -121,7 +121,7 @@ public void Pipeline_removing_a_spec_file_removes_only_its_output() public void Pipeline_editing_an_optional_argument_reruns_only_that_files_output() { string optional = SpecSources.Ce77Header("Demo.Optional", "Optional") + - "global: load\nmethod: Load\nform: throwing\narg: path:string\nopt: merge:boolean\nnil: none\ndoc: Loads.\n"; + "global: load\nmethod: Load\nform: throwing\narg: path:string\nopt: merge:boolean\nnil: none\ndoc: Loads.\n"; InMemoryAdditionalText original = new("a.cheatengine-sdk-api.txt", optional); InMemoryAdditionalText other = new("b.cheatengine-sdk-api.txt", SpecSources.BeepOnly); CSharpCompilation compilation = roslyn.CreateCompilation(); @@ -146,7 +146,7 @@ public void Pipeline_editing_an_optional_argument_reruns_only_that_files_output( public void Pipeline_step_values_hold_no_roslyn_objects() { string optional = SpecSources.Ce77Header("Demo.Optional", "Optional") + - "global: g\nmethod: G\nform: outcome\narg: a:address\nopt: b:int32\nresult: r:int64\nopt-result: s:address\nrest: values:double\nnil: absence\ndoc: d.\n"; + "global: g\nmethod: G\nform: outcome\narg: a:address\nopt: b:int32\nresult: r:int64\nopt-result: s:address\nrest: values:double\nnil: absence\ndoc: d.\n"; GeneratorRun run = roslyn.Run(("a.cheatengine-sdk-api.txt", SpecSources.Memory), ("b.cheatengine-sdk-api.txt", optional)); Assert.Equal(2, run.GeneratedSources.Length); @@ -155,7 +155,7 @@ public void Pipeline_step_values_hold_no_roslyn_objects() foreach (string stepName in EngineApiTrackingNames.All) { if (string.Equals(stepName, EngineApiTrackingNames.SpecTextFile, StringComparison.Ordinal)) - // Legitimately holds the raw AdditionalText: that is the point of this filter step. + // Legitimately holds the raw AdditionalText: that is the point of this filter step. { continue; } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/GeneratedAssembly.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/GeneratedAssembly.cs index 99962168..49ab4a53 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/GeneratedAssembly.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/GeneratedAssembly.cs @@ -43,7 +43,7 @@ public static GeneratedAssembly Load(GeneratorRun run) image.Position = 0; string assemblyName = "CheatEngine.SDK.EngineApi.Tests." + - Interlocked.Increment(ref s_counter).ToString(CultureInfo.InvariantCulture); + Interlocked.Increment(ref s_counter).ToString(CultureInfo.InvariantCulture); AssemblyLoadContext context = new(assemblyName); return new GeneratedAssembly(context.LoadFromStream(image)); } @@ -56,7 +56,7 @@ public TDelegate Delegate(string typeName, string methodName) Type[] parameterTypes = [.. parameters.Select(static parameter => parameter.ParameterType)]; Type type = Assembly.GetType(typeName, true)!; MethodInfo method = type.GetMethod(methodName, StaticMembers, parameterTypes) ?? - throw new MissingMethodException(typeName, methodName); + throw new MissingMethodException(typeName, methodName); return method.CreateDelegate(); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/LocalFrameworkReferences.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/LocalFrameworkReferences.cs index b9de061c..0a34b77d 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/LocalFrameworkReferences.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/LocalFrameworkReferences.cs @@ -61,8 +61,8 @@ public static ImmutableArray FromTargetingPack() { string candidate = Path.Combine(pack, "ref", TargetFrameworkFolder); if (Directory.Exists(candidate) - && TryParsePackVersion(Path.GetFileName(pack), out Version? version) - && (bestVersion is null || version > bestVersion)) + && TryParsePackVersion(Path.GetFileName(pack), out Version? version) + && (bestVersion is null || version > bestVersion)) { best = candidate; bestVersion = version; diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ModelGraph.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ModelGraph.cs index a4030574..3a7c5c80 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ModelGraph.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ModelGraph.cs @@ -69,7 +69,7 @@ private static void Visit(object? value, string path, HashSet visited, i } foreach (FieldInfo field in - type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { Visit(field.GetValue(value), $"{path}.{field.Name}", visited, depth + 1); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ProductionSpecs.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ProductionSpecs.cs index a445f854..e64aef7a 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ProductionSpecs.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Infrastructure/ProductionSpecs.cs @@ -61,7 +61,7 @@ public static IReadOnlySet WiredFileNames() private static string Read(string resourceName) { using Stream stream = Resources.GetManifestResourceStream(resourceName) - ?? throw new InvalidOperationException("Missing embedded resource " + resourceName + "."); + ?? throw new InvalidOperationException("Missing embedded resource " + resourceName + "."); using StreamReader reader = new(stream); return reader.ReadToEnd(); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/SpecFileParserTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/SpecFileParserTests.cs index 67fc81bc..ee6cb31a 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/SpecFileParserTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/Parsing/SpecFileParserTests.cs @@ -106,8 +106,8 @@ public void Indentation_and_CRLF_line_endings_are_tolerated() string text = SpecSources.SingleTry.Replace("\r\n", "\n", StringComparison.Ordinal) .Replace("\n", "\r\n", StringComparison.Ordinal); text = " namespace: Demo.One\r\n type: One\r\n" + - SpecSources.Ce77.Replace("\n", "\r\n ", StringComparison.Ordinal) + "\r\n" + - text[text.IndexOf("global:", StringComparison.Ordinal)..]; + SpecSources.Ce77.Replace("\n", "\r\n ", StringComparison.Ordinal) + "\r\n" + + text[text.IndexOf("global:", StringComparison.Ordinal)..]; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -352,7 +352,7 @@ public void A_duplicate_entry_key_drops_the_entry() public void An_invalid_lua_global_name_drops_the_entry(string badName) { string text = "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + "\nglobal: " + badName + - "\nmethod: M\nform: try\narg: address:address\nresult: value:int32\nnil: none\ndoc: d.\n"; + "\nmethod: M\nform: try\narg: address:address\nresult: value:int32\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -569,8 +569,8 @@ public void A_throwing_entry_without_a_return_is_a_void_wrapper() public void A_malformed_or_unknown_kind_argument_drops_the_entry(string argLine) { string text = "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + - "\nglobal: readInteger\nmethod: M\nform: try\n" + argLine + - "\nresult: value:int32\nnil: none\ndoc: d.\n"; + "\nglobal: readInteger\nmethod: M\nform: try\n" + argLine + + "\nresult: value:int32\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -585,8 +585,8 @@ public void A_malformed_or_unknown_kind_argument_drops_the_entry(string argLine) public void A_fixed_argument_accepts_only_boolean_literals(string fixedLine) { string text = "namespace: Demo\ntype: T\n" + SpecSources.Ce77 + - "\nglobal: readInteger\nmethod: M\nform: try\narg: address:address\n" + - fixedLine + "\nresult: value:int32\nnil: none\ndoc: d.\n"; + "\nglobal: readInteger\nmethod: M\nform: try\narg: address:address\n" + + fixedLine + "\nresult: value:int32\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -935,7 +935,7 @@ public void Spec_with_entries_without_contract_reports_the_missing_ce77_contract public void Fixed_and_optional_arguments_keep_their_declaration_order() { string text = SpecSources.Ce77Header("Demo", "T") + - "global: g\nmethod: G\nform: throwing\narg: a:int32\nfixed: boolean:true\narg: b:int64\nopt: c:address\nopt: d:string\nnil: none\ndoc: d.\n"; + "global: g\nmethod: G\nform: throwing\narg: a:int32\nfixed: boolean:true\narg: b:int64\nopt: c:address\nopt: d:string\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -956,7 +956,7 @@ public void Fixed_and_optional_arguments_keep_their_declaration_order() public void Argument_after_an_optional_argument_is_refused(string arguments, string message) { string text = SpecSources.Ce77Header("Demo", "T") + "global: g\nmethod: G\nform: throwing\n" + arguments + - "nil: none\ndoc: d.\n"; + "nil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -976,7 +976,7 @@ public void Argument_after_an_optional_argument_is_refused(string arguments, str public void Optional_result_before_a_required_result_is_refused(string form, string results, string message) { string text = SpecSources.Ce77Header("Demo", "T") + "global: g\nmethod: G\nform: " + form + "\n" + results + - "nil: none\ndoc: d.\n"; + "nil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -990,8 +990,8 @@ public void Optional_result_before_a_required_result_is_refused(string form, str public void Outcome_form_is_parsed() { string text = SpecSources.Ce77Header("Demo", "T") + - "global: g\nmethod: G\nform: outcome\narg: a:address\nresult: first:int64\nopt-result: second:address\nrest: values:double\nnil: absence\ndoc: d.\n\n" + - "global: beep\nmethod: Beep\nform: outcome\nnil: none\ndoc: d.\n"; + "global: g\nmethod: G\nform: outcome\narg: a:address\nresult: first:int64\nopt-result: second:address\nrest: values:double\nnil: absence\ndoc: d.\n\n" + + "global: beep\nmethod: Beep\nform: outcome\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -1012,7 +1012,7 @@ public void Outcome_form_is_parsed() public void Rest_result_requires_the_outcome_form() { string text = SpecSources.Ce77Header("Demo", "T") + - "global: g\nmethod: TryG\nform: try\nresult: first:int32\nrest: values:int32\nnil: none\ndoc: d.\n"; + "global: g\nmethod: TryG\nform: try\nresult: first:int32\nrest: values:int32\nnil: none\ndoc: d.\n"; SpecFileModel spec = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", text); @@ -1028,13 +1028,13 @@ public void Rest_result_requires_the_outcome_form() public void Reformatting_a_spec_keeps_its_contract_and_call_model() { string compact = SpecSources.Ce77Header("Demo", "T") + - "global: g\nmethod: G\nform: outcome\narg: a:int32\nopt: b:address\nresult: r:int64\nopt-result: s:string\nnil: absence\ndoc: Reads.\n"; + "global: g\nmethod: G\nform: outcome\narg: a:int32\nopt: b:address\nresult: r:int64\nopt-result: s:string\nnil: absence\ndoc: Reads.\n"; string reformatted = "# reformatted\r\n namespace: Demo \r\n\ttype: T\r\n" + - SpecSources.Ce77.Replace("\n", "\r\n # a comment inside the header\r\n", - StringComparison.Ordinal) + - "\r\n\r\n # a comment before the entry\r\n global: g\r\n method: G\r\n # a comment inside the entry\r\n" + - " form:outcome\r\n arg: a:int32\r\n opt: b:address \r\n result: r:int64\r\n opt-result: s:string\r\n" + - " nil: absence\r\n doc: Reads.\r\n\r\n"; + SpecSources.Ce77.Replace("\n", "\r\n # a comment inside the header\r\n", + StringComparison.Ordinal) + + "\r\n\r\n # a comment before the entry\r\n global: g\r\n method: G\r\n # a comment inside the entry\r\n" + + " form:outcome\r\n arg: a:int32\r\n opt: b:address \r\n result: r:int64\r\n opt-result: s:string\r\n" + + " nil: absence\r\n doc: Reads.\r\n\r\n"; SpecFileModel first = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", compact); SpecFileModel second = SpecFileParser.Parse("x.cheatengine-sdk-api.txt", reformatted); diff --git a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/packages.lock.json b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/packages.lock.json index 4902922c..51588b64 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.SourceGenerators.EngineApi.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.CSharp": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/ContractIdentityTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/ContractIdentityTests.cs index 5399c285..eb0bdbdc 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/ContractIdentityTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/ContractIdentityTests.cs @@ -187,8 +187,8 @@ private static void AssertNoSourceErrors(GeneratorRun run) Assert.DoesNotContain( run.OutputCompilation.GetDiagnostics(TestContext.Current.CancellationToken), static diagnostic => diagnostic.Severity == DiagnosticSeverity.Error - && (diagnostic.Location.SourceTree is null - || !diagnostic.Location.SourceTree.FilePath.EndsWith(".g.cs", - StringComparison.Ordinal))); + && (diagnostic.Location.SourceTree is null + || !diagnostic.Location.SourceTree.FilePath.EndsWith(".g.cs", + StringComparison.Ordinal))); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs index 2803321c..e4cb4d9d 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NameEscapingTests.cs @@ -61,7 +61,7 @@ public void Generator_display_name_is_escaped_into_a_u8_literal(string caseKey) // Holds because the plugin type of these cases (Demo.DemoPlugin) is ASCII: whatever the display name is, the // literal adds no other character. Identifiers are written as declared (PluginLocationTests, non-ASCII case). Assert.All(generated, - static c => Assert.True(c is '\n' or >= ' ' and <= '~', + static c => Assert.True(c is '\n' or (>= ' ' and <= '~'), $"Non-ASCII character U+{(int) c:X4} in generated text.")); run.AssertCompilesClean(); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NominalOutputTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NominalOutputTests.cs index 4ff28570..78c21747 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NominalOutputTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/NominalOutputTests.cs @@ -106,10 +106,10 @@ public void Generator_bootstrap_constructs_the_plugin_without_reflection() string text = run.SingleGeneratedText; foreach (string reflective in (string[]) - [ - "Activator", "CreateInstance", "GetTypes", "GetType(", "typeof(", - "System.Reflection", "Assembly." - ]) + [ + "Activator", "CreateInstance", "GetTypes", "GetType(", "typeof(", + "System.Reflection", "Assembly." + ]) { Assert.DoesNotContain(reflective, text, StringComparison.Ordinal); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/RealAssemblyCompilationTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/RealAssemblyCompilationTests.cs index d6c8333c..025f7679 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/RealAssemblyCompilationTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Generator/RealAssemblyCompilationTests.cs @@ -87,7 +87,7 @@ [new EntryPointGenerator().AsSourceGenerator()], .. outputCompilation .GetDiagnostics(TestContext.Current.CancellationToken) .Where(static diagnostic => diagnostic.Severity >= DiagnosticSeverity.Warning && - !IsMissingDocumentationInTestInput(diagnostic)) + !IsMissingDocumentationInTestInput(diagnostic)) ]; Assert.True( @@ -101,7 +101,7 @@ .. outputCompilation private static bool IsMissingDocumentationInTestInput(Diagnostic diagnostic) { return string.Equals(diagnostic.Id, "CS1591", StringComparison.Ordinal) - && diagnostic.Location.SourceTree is { FilePath: string path } - && !path.EndsWith(".g.cs", StringComparison.Ordinal); + && diagnostic.Location.SourceTree is { FilePath: string path } + && !path.EndsWith(".g.cs", StringComparison.Ordinal); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/GeneratorRun.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/GeneratorRun.cs index ff87ce3a..fcf3ffe4 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/GeneratorRun.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/GeneratorRun.cs @@ -76,7 +76,7 @@ public void AssertCompilesClean() .. OutputCompilation .GetDiagnostics(TestContext.Current.CancellationToken) .Where(static diagnostic => diagnostic.Severity >= DiagnosticSeverity.Warning && - !IsMissingDocumentationInTestInput(diagnostic)) + !IsMissingDocumentationInTestInput(diagnostic)) ]; Assert.True(problems.Length == 0, @@ -88,7 +88,7 @@ .. OutputCompilation private static bool IsMissingDocumentationInTestInput(Diagnostic diagnostic) { return string.Equals(diagnostic.Id, "CS1591", StringComparison.Ordinal) - && diagnostic.Location.SourceTree is { FilePath: string path } - && !path.EndsWith(".g.cs", StringComparison.Ordinal); + && diagnostic.Location.SourceTree is { FilePath: string path } + && !path.EndsWith(".g.cs", StringComparison.Ordinal); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LoadedBootstrap.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LoadedBootstrap.cs index 138fd492..3a6d4aa7 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LoadedBootstrap.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LoadedBootstrap.cs @@ -25,7 +25,7 @@ private LoadedBootstrap(AssemblyLoadContext context, Assembly hosting, Assembly // Same lookup as the host: type 'CESDK.CESDK' in the plugin assembly, static method 'CEPluginInitialize'. Type entryPoint = plugin.GetType("CESDK.CESDK", true)!; MethodInfo method = entryPoint.GetMethod("CEPluginInitialize", BindingFlags.Public | BindingFlags.Static) - ?? throw new MissingMethodException("CESDK.CESDK", "CEPluginInitialize"); + ?? throw new MissingMethodException("CESDK.CESDK", "CEPluginInitialize"); _initialize = method.CreateDelegate>(); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LocalFrameworkReferences.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LocalFrameworkReferences.cs index 5cb4b2ef..678a7dff 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LocalFrameworkReferences.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/LocalFrameworkReferences.cs @@ -63,8 +63,8 @@ public static ImmutableArray FromTargetingPack() { string candidate = Path.Combine(pack, "ref", TargetFrameworkFolder); if (Directory.Exists(candidate) - && TryParsePackVersion(Path.GetFileName(pack), out Version? version) - && (bestVersion is null || version > bestVersion)) + && TryParsePackVersion(Path.GetFileName(pack), out Version? version) + && (bestVersion is null || version > bestVersion)) { best = candidate; bestVersion = version; diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/ModelGraph.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/ModelGraph.cs index ee75bfd1..357f5c77 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/ModelGraph.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Infrastructure/ModelGraph.cs @@ -69,7 +69,7 @@ private static void Visit(object? value, string path, HashSet visited, i } foreach (FieldInfo field in - type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { Visit(field.GetValue(value), $"{path}.{field.Name}", visited, depth + 1); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Model/BootstrapModelTests.cs b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Model/BootstrapModelTests.cs index eaf158ee..cbb2c58a 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Model/BootstrapModelTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/Model/BootstrapModelTests.cs @@ -68,17 +68,32 @@ public void PluginModel_is_valid_only_without_issues() { Assert.True(ValidA.IsValid); Assert.False(Invalid.IsValid); - Assert.False((ValidA with { Issues = PluginShapeIssues.InvalidName }).IsValid); + Assert.False((ValidA with + { + Issues = PluginShapeIssues.InvalidName + }).IsValid); } [Fact] public void Models_compare_by_value() { Assert.Equal(new PluginModel("global::A", "Plugin A", "", PluginShapeIssues.None), ValidA); - Assert.NotEqual(ValidA with { DisplayName = "other" }, ValidA); - Assert.NotEqual(ValidA with { FullyQualifiedTypeName = "global::Z" }, ValidA); - Assert.NotEqual(ValidA with { DeclaredDiagnosticIds = "EXP001" }, ValidA); - Assert.NotEqual(ValidA with { Issues = PluginShapeIssues.Static }, ValidA); + Assert.NotEqual(ValidA with + { + DisplayName = "other" + }, ValidA); + Assert.NotEqual(ValidA with + { + FullyQualifiedTypeName = "global::Z" + }, ValidA); + Assert.NotEqual(ValidA with + { + DeclaredDiagnosticIds = "EXP001" + }, ValidA); + Assert.NotEqual(ValidA with + { + Issues = PluginShapeIssues.Static + }, ValidA); Assert.Equal(new EntryPointOptions(true), On); Assert.NotEqual(Off, On); Assert.Equal( diff --git a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/packages.lock.json b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/packages.lock.json index 482ceb2a..2643f431 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.SourceGenerators.EntryPoint.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.CSharp": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalOptionalArgumentEndToEndTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalOptionalArgumentEndToEndTests.cs index 4b1dfc51..872f31b9 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalOptionalArgumentEndToEndTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalOptionalArgumentEndToEndTests.cs @@ -133,11 +133,11 @@ public void Warm_optional_argument_form_allocates_nothing() AllocationGate.AssertZero(() => { if (!tryArity(1, LuaOptional.Of(2L), out long present) || present != 2 - || !tryArity(1, default, out long omitted) || - omitted != 1 - || !detailed(1, LuaOptional.Nil(), - LuaOptional.Of(true), out long nil).IsSuccess || - nil != 3) + || !tryArity(1, default, out long omitted) || + omitted != 1 + || !detailed(1, LuaOptional.Nil(), + LuaOptional.Of(true), out long nil).IsSuccess || + nil != 3) { throw new InvalidOperationException("wrong count"); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalResultCountEndToEndTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalResultCountEndToEndTests.cs index bde33255..0550814d 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalResultCountEndToEndTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/EndToEnd/LuaGlobalResultCountEndToEndTests.cs @@ -253,7 +253,7 @@ public void Warm_optional_result_and_variadic_forms_allocate_nothing() AllocationGate.AssertZero(() => { if (!pair(3, out long first, out LuaOptional second).IsSuccess || !second.TryGetValue(out long value) - || !sequence(3, default, buffer, out int count).IsSuccess || count != 3) + || !sequence(3, default, buffer, out int count).IsSuccess || count != 3) { throw new InvalidOperationException("wrong results"); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/ContainingTypeTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/ContainingTypeTests.cs index 19d9becc..26790695 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/ContainingTypeTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/ContainingTypeTests.cs @@ -45,7 +45,7 @@ internal static partial class Bindings public void Generator_global_namespace_has_no_namespace_block() { GeneratorRun run = roslyn.Run(Usings + - "public static partial class Top { [LuaFunction(\"f\")] public static int F(int a) => a; }"); + "public static partial class Top { [LuaFunction(\"f\")] public static int F(int a) => a; }"); run.AssertCompilesClean(); string text = run.GeneratedText("Top.LuaFunctions.g.cs"); @@ -66,7 +66,7 @@ public void Generator_global_namespace_has_no_namespace_block() public void Generator_type_kinds_are_reopened_with_their_keyword(string declaration, string expectedPart) { GeneratorRun run = roslyn.Run(Usings + "namespace Demo; " + declaration + - " Holder { [LuaFunction(\"f\")] public static int F(int a) => a; [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, out int v); }"); + " Holder { [LuaFunction(\"f\")] public static int F(int a) => a; [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, out int v); }"); run.AssertCompilesClean(); Assert.Contains("\n " + expectedPart + " Holder\n {\n", @@ -109,7 +109,7 @@ public void Generator_types_differing_only_by_case_get_distinct_hint_names() // cannot tell "DemoType" and "demoType" apart (neither has a replaced character), so without disambiguation // AddSource throws ArgumentException on the second one and the whole generation pass crashes. const string Source = Usings + - "namespace Demo; public static partial class DemoType { [LuaFunction(\"f1\")] public static int F(int a) => a; } public static partial class demoType { [LuaFunction(\"f2\")] public static int F(int a) => a; }"; + "namespace Demo; public static partial class DemoType { [LuaFunction(\"f1\")] public static int F(int a) => a; } public static partial class demoType { [LuaFunction(\"f2\")] public static int F(int a) => a; }"; GeneratorRun run = roslyn.Run(Source); @@ -124,7 +124,7 @@ public void Generator_types_differing_only_by_case_get_distinct_hint_names() public void Generator_non_ascii_type_name_gets_a_hashed_hint_name_and_an_unescaped_declaration() { GeneratorRun run = roslyn.Run(Usings + - "namespace Demo; public static partial class Caf\u00E9 { [LuaFunction(\"f\")] public static int F(int a) => a; }"); + "namespace Demo; public static partial class Caf\u00E9 { [LuaFunction(\"f\")] public static int F(int a) => a; }"); run.AssertCompilesClean(); string hintName = Assert.Single(run.HintNames); @@ -186,8 +186,8 @@ public void Generator_type_split_across_files_gets_one_file() public void Generator_repeats_the_defining_declarations_modifiers(string declared, string emitted) { GeneratorRun run = roslyn.Run(Usings + "namespace Demo; public partial class Holder { [LuaGlobal(\"g\")] " + - declared + - " bool TryG(nuint a, out int v); }"); + declared + + " bool TryG(nuint a, out int v); }"); run.AssertCompilesClean(); Assert.Contains("\n " + emitted + " bool TryG(nuint a, out int v)\n", run.SingleGeneratedText, @@ -214,7 +214,7 @@ namespace Demo; public void Generator_old_style_partial_void_without_accessibility_is_implemented_without_one() { GeneratorRun run = roslyn.Run(Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"beep\")] static partial void Beep(); }"); + "namespace Demo; public static partial class Holder { [LuaGlobal(\"beep\")] static partial void Beep(); }"); run.AssertCompilesClean(); Assert.Contains("\n static partial void Beep()\n", run.SingleGeneratedText, StringComparison.Ordinal); @@ -224,7 +224,7 @@ public void Generator_old_style_partial_void_without_accessibility_is_implemente public void Generator_private_target_is_reachable_from_the_thunk() { GeneratorRun run = roslyn.Run(Usings + - "namespace Demo; internal static partial class Holder { [LuaFunction(\"f\")] private static int F(int a) => a; }"); + "namespace Demo; internal static partial class Holder { [LuaFunction(\"f\")] private static int F(int a) => a; }"); run.AssertCompilesClean(); Assert.Contains("global::Demo.Holder.F(__arg0)", run.SingleGeneratedText, StringComparison.Ordinal); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/DefaultVerifierTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/DefaultVerifierTests.cs index b6415ec7..53a0bcc1 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/DefaultVerifierTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/DefaultVerifierTests.cs @@ -50,7 +50,8 @@ private static CSharpSourceGeneratorTest { // A framework moniker WITHOUT a reference-assembly package: nothing is resolved through NuGet; the // framework and the SDK come from the local installation and this process (no network). - ReferenceAssemblies = new ReferenceAssemblies("net10.0"), CompilerDiagnostics = CompilerDiagnostics.Warnings + ReferenceAssemblies = new ReferenceAssemblies("net10.0"), + CompilerDiagnostics = CompilerDiagnostics.Warnings }; // The test declarations are undocumented public members: CS1591 is theirs, not the generated file's. diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/IncrementalityTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/IncrementalityTests.cs index 6a038773..b3550523 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/IncrementalityTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/IncrementalityTests.cs @@ -37,8 +37,8 @@ public void Pipeline_first_run_tracks_every_named_step() GeneratorRun run = roslyn.Run(BindingSources.Functions, BindingSources.Globals, ObjectBindings); foreach (string stepName in run.Result.TrackedSteps.Keys - .Where(TrackingNames.IsCheatEngineSdkStep) - .Order(StringComparer.Ordinal)) + .Where(TrackingNames.IsCheatEngineSdkStep) + .Order(StringComparer.Ordinal)) { Assert.All(StepAssert.Reasons(run.Result, stepName), static reason => Assert.Equal(IncrementalStepRunReason.New, reason)); @@ -329,8 +329,8 @@ public void Pipeline_step_values_hold_no_roslyn_objects() int visited = 0; foreach (string stepName in run.Result.TrackedSteps.Keys - .Where(TrackingNames.IsCheatEngineSdkStep) - .Order(StringComparer.Ordinal)) + .Where(TrackingNames.IsCheatEngineSdkStep) + .Order(StringComparer.Ordinal)) { Assert.True( run.Result.TrackedSteps.TryGetValue(stepName, out ImmutableArray steps), diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaFunctionOutputTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaFunctionOutputTests.cs index 3c2d7e43..abc96665 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaFunctionOutputTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaFunctionOutputTests.cs @@ -49,10 +49,10 @@ public void Generator_function_suite_compiles_clean_and_declares_one_thunk_per_f run.AssertCompilesClean(); string text = run.SingleGeneratedText; foreach (string name in new[] - { - "add", "greet", "ping", "isint", "boom", "echo", "half", "negate", "step", "small", "scale", - "maybe" - }) + { + "add", "greet", "ping", "isint", "boom", "echo", "half", "negate", "step", "small", "scale", + "maybe" + }) { Assert.Contains("private static int __LuaThunk_" + name + "(nint __handle)", text, StringComparison.Ordinal); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaGlobalOutputTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaGlobalOutputTests.cs index 8b65c81e..f16ce313 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaGlobalOutputTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaGlobalOutputTests.cs @@ -238,9 +238,9 @@ public void Generator_unannotated_out_string_result_gets_exactly_cs8601_the_docu .. run.OutputCompilation .GetDiagnostics(TestContext.Current.CancellationToken) .Where(static diagnostic => diagnostic.Severity >= DiagnosticSeverity.Warning - && !(string.Equals(diagnostic.Id, "CS1591", StringComparison.Ordinal) - && diagnostic.Location.SourceTree is { FilePath: string path } && - !path.EndsWith(".g.cs", StringComparison.Ordinal))) + && !(string.Equals(diagnostic.Id, "CS1591", StringComparison.Ordinal) + && diagnostic.Location.SourceTree is { FilePath: string path } && + !path.EndsWith(".g.cs", StringComparison.Ordinal))) ]; Diagnostic problem = Assert.Single(problems); Assert.Equal("CS8601", problem.Id); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaObjectOutputTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaObjectOutputTests.cs index 7a50be69..d8e451f5 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaObjectOutputTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/LuaObjectOutputTests.cs @@ -615,7 +615,7 @@ private static MethodDeclarationSyntax FindGeneratedMethod(CompilationUnitSyntax foreach (SyntaxNode node in root.DescendantNodes()) { if (node is MethodDeclarationSyntax candidate - && string.Equals(candidate.Identifier.ValueText, methodName, StringComparison.Ordinal)) + && string.Equals(candidate.Identifier.ValueText, methodName, StringComparison.Ordinal)) { Assert.Null(result); result = candidate; diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/NoOutputTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/NoOutputTests.cs index e9bcce09..7d4ab3c8 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/NoOutputTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/NoOutputTests.cs @@ -461,8 +461,8 @@ public static TheoryData InvalidGlobals public void Generator_non_trailing_optional_argument_emits_nothing() { const string Source = "using CheatEngine.SDK.Annotations.Lua;\nusing CheatEngine.SDK.Lua.Marshalling;\n" + - "namespace Demo; public static partial class T { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a, int b); " + - "[LuaFunction(\"f\")] public static int F(LuaOptional a, long b) => 0; }"; + "namespace Demo; public static partial class T { [LuaGlobal(\"g\")] public static partial int G(LuaOptional a, int b); " + + "[LuaFunction(\"f\")] public static int F(LuaOptional a, long b) => 0; }"; roslyn.Run(Source).AssertNoOutput(); } @@ -562,7 +562,7 @@ public void Generator_invalid_global_shape_emits_nothing(string shape, string so public void Generator_no_attribute_emits_nothing() { GeneratorRun run = roslyn.Run(Usings + - "public static partial class T { public static int F(int a) => a; public static partial int G(int a); public static partial int G(int a) => a; }"); + "public static partial class T { public static int F(int a) => a; public static partial int G(int a); public static partial int G(int a) => a; }"); run.AssertNoOutput(); } @@ -575,7 +575,7 @@ public void Generator_same_name_source_LuaState_without_the_sdk_runtime_emits_no foreach (MetadataReference reference in roslyn.Environment.SdkReferences) { if (string.Equals(reference.Display, typeof(LuaState).Assembly.Location, - StringComparison.OrdinalIgnoreCase)) + StringComparison.OrdinalIgnoreCase)) { continue; } @@ -729,8 +729,8 @@ private static int Count(string text, string needle) { int count = 0; for (int index = text.IndexOf(needle, StringComparison.Ordinal); - index >= 0; - index = text.IndexOf(needle, index + needle.Length, StringComparison.Ordinal)) + index >= 0; + index = text.IndexOf(needle, index + needle.Length, StringComparison.Ordinal)) { count++; } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/PartialMethodSignatureTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/PartialMethodSignatureTests.cs index 7b214cb6..9f641df7 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/PartialMethodSignatureTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Generator/PartialMethodSignatureTests.cs @@ -15,7 +15,7 @@ public sealed class PartialMethodSignatureTests(RoslynFixture roslyn) : IClassFi public void Generator_repeats_an_explicit_scoped_readonlyspan_argument() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(scoped System.ReadOnlySpan data, out int v); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(scoped System.ReadOnlySpan data, out int v); }"; GeneratorRun run = roslyn.Run(Source); @@ -31,8 +31,8 @@ public void Generator_repeats_an_explicit_scoped_readonlyspan_argument() public void Generator_repeats_optional_argument_and_result_types_exactly(string declared, string generated) { string source = Usings + "using CheatEngine.SDK.Lua.Calls;\nusing CheatEngine.SDK.Lua.Marshalling;\n" + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(int first, " + - declared + ", out LuaOptional result); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(int first, " + + declared + ", out LuaOptional result); }"; GeneratorRun run = roslyn.Run(source); @@ -47,7 +47,7 @@ public void Generator_repeats_optional_argument_and_result_types_exactly(string public void Generator_repeats_an_explicit_scoped_variadic_span() { const string Source = Usings + "using CheatEngine.SDK.Lua.Calls;\n" + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial LuaOperationStatus G(scoped System.Span values, out int count); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial LuaOperationStatus G(scoped System.Span values, out int count); }"; GeneratorRun run = roslyn.Run(Source); @@ -61,7 +61,7 @@ public void Generator_repeats_an_explicit_scoped_variadic_span() public void Generator_omits_scoped_when_the_defining_declaration_did() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(System.ReadOnlySpan data, out int v); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(System.ReadOnlySpan data, out int v); }"; GeneratorRun run = roslyn.Run(Source); @@ -76,7 +76,7 @@ public void Generator_omits_scoped_when_the_defining_declaration_did() public void Generator_repeats_an_explicit_scoped_copyout_destination() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, scoped System.Span destination, out int written); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, scoped System.Span destination, out int written); }"; GeneratorRun run = roslyn.Run(Source); @@ -89,7 +89,7 @@ public void Generator_repeats_an_explicit_scoped_copyout_destination() public void Generator_omits_scoped_on_the_copyout_destination_when_the_defining_declaration_did() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, System.Span destination, out int written); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, System.Span destination, out int written); }"; GeneratorRun run = roslyn.Run(Source); @@ -105,7 +105,7 @@ public void Generator_scoped_out_result_of_a_non_ref_struct_type_needs_no_specia // 'scoped' on an 'out' parameter of a non-ref-struct type does not affect partial-signature matching (the // compiler accepts a mismatch there), so the emitter never needs to repeat it; this pins that down. const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, scoped out int v); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint a, scoped out int v); }"; GeneratorRun run = roslyn.Run(Source); @@ -118,7 +118,7 @@ public void Generator_scoped_out_result_of_a_non_ref_struct_type_needs_no_specia public void Generator_preserves_the_extension_receiver_in_the_implementing_declaration() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(this nuint address, out int value); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(this nuint address, out int value); }"; GeneratorRun run = roslyn.Run(Source); @@ -131,7 +131,7 @@ public void Generator_preserves_the_extension_receiver_in_the_implementing_decla public void Generator_preserves_the_extension_receiver_on_a_copyout_destination() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(this System.Span destination, out int written); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(this System.Span destination, out int written); }"; GeneratorRun run = roslyn.Run(Source); @@ -144,7 +144,7 @@ public void Generator_preserves_the_extension_receiver_on_a_copyout_destination( public void Generator_qualifies_the_cache_when_a_parameter_uses_its_name() { const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial void G(int s_luaGlobal_g); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial void G(int s_luaGlobal_g); }"; GeneratorRun run = roslyn.Run(Source); @@ -159,7 +159,7 @@ public void Generator_parameter_named_like_a_generated_local_is_skipped_without_ // A generated partial body shares its parameter scope with the defining declaration. Do not emit CS0136 and // leave the analyzer to report the precise CESDK2007 collision at the author declaration. const string Source = Usings + - "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint __L, out int v); }"; + "namespace Demo; public static partial class Holder { [LuaGlobal(\"g\")] public static partial bool TryG(nuint __L, out int v); }"; GeneratorRun run = roslyn.Run(Source); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/GeneratorRun.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/GeneratorRun.cs index 72cd2bc4..959c4c4f 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/GeneratorRun.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/GeneratorRun.cs @@ -94,7 +94,7 @@ public void AssertCompilesClean() .. OutputCompilation .GetDiagnostics(TestContext.Current.CancellationToken) .Where(static diagnostic => diagnostic.Severity >= DiagnosticSeverity.Warning && - !IsMissingDocumentationInTestInput(diagnostic)) + !IsMissingDocumentationInTestInput(diagnostic)) ]; Assert.True(problems.Length == 0, @@ -106,7 +106,7 @@ .. OutputCompilation private static bool IsMissingDocumentationInTestInput(Diagnostic diagnostic) { return string.Equals(diagnostic.Id, "CS1591", StringComparison.Ordinal) - && diagnostic.Location.SourceTree is { FilePath: string path } - && !path.EndsWith(".g.cs", StringComparison.Ordinal); + && diagnostic.Location.SourceTree is { FilePath: string path } + && !path.EndsWith(".g.cs", StringComparison.Ordinal); } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/LocalFrameworkReferences.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/LocalFrameworkReferences.cs index 8b157554..b179ad3a 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/LocalFrameworkReferences.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/LocalFrameworkReferences.cs @@ -63,8 +63,8 @@ public static ImmutableArray FromTargetingPack() { string candidate = Path.Combine(pack, "ref", TargetFrameworkFolder); if (Directory.Exists(candidate) - && TryParsePackVersion(Path.GetFileName(pack), out Version? version) - && (bestVersion is null || version > bestVersion)) + && TryParsePackVersion(Path.GetFileName(pack), out Version? version) + && (bestVersion is null || version > bestVersion)) { best = candidate; bestVersion = version; diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/ModelGraph.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/ModelGraph.cs index 27df8352..4517cfd2 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/ModelGraph.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Infrastructure/ModelGraph.cs @@ -70,7 +70,7 @@ private static void Visit(object? value, string path, HashSet visited, i } foreach (FieldInfo field in - type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { Visit(field.GetValue(value), $"{path}.{field.Name}", visited, depth + 1); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaFunctionTablesTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaFunctionTablesTests.cs index 2b56bfe2..21d707fa 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaFunctionTablesTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaFunctionTablesTests.cs @@ -58,10 +58,14 @@ public void Group_skips_invalid_members_and_types_left_without_a_valid_one() { LuaFunctionModel invalid = Function(Alpha, "bad") with { - Issues = LuaFunctionShapeIssues.NotStatic, Thunk = null + Issues = LuaFunctionShapeIssues.NotStatic, + Thunk = null }; LuaFunctionModel invalidType = - Function(Zeta, "ok") with { ContainingTypeIssues = ContainingTypeIssues.NotPartial }; + Function(Zeta, "ok") with + { + ContainingTypeIssues = ContainingTypeIssues.NotPartial + }; EquatableArray tables = LuaFunctionTables.Group([invalid, invalidType, Function(Alpha, "good")]); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaGlobalTablesTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaGlobalTablesTests.cs index b990fdae..c32ad926 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaGlobalTablesTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/Model/LuaGlobalTablesTests.cs @@ -38,7 +38,8 @@ public void Group_skips_invalid_members_and_empty_inputs() { LuaGlobalModel invalid = Global("g", "G()") with { - Issues = LuaGlobalShapeIssues.NotPartialDefinition, Call = null + Issues = LuaGlobalShapeIssues.NotPartialDefinition, + Call = null }; Assert.True(LuaGlobalTables.Group([invalid]).IsEmpty); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/HintNamesTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/HintNamesTests.cs index 27ecdc26..49049442 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/HintNamesTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/HintNamesTests.cs @@ -91,6 +91,6 @@ public void AllocateUnique_rejects_a_case_sensitive_reservation_set() private static string WithOrdinal(string hintName, string suffix, int ordinal) { return hintName[..^suffix.Length] + "_" + ordinal.ToString(CultureInfo.InvariantCulture) + - suffix; + suffix; } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaApiNamesTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaApiNamesTests.cs index 732aa358..38aac32d 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaApiNamesTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaApiNamesTests.cs @@ -42,7 +42,7 @@ public void Every_CheatEngine_SDK_name_written_into_generated_code_denotes_a_rea { int dot = text.LastIndexOf('.'); Type owner = FindType(text[..dot]) - ?? throw new InvalidOperationException($"{name}: no such type in the SDK assemblies."); + ?? throw new InvalidOperationException($"{name}: no such type in the SDK assemblies."); Assert.NotEmpty(owner.GetMember( text[(dot + 1)..^2], MemberTypes.Method, @@ -51,7 +51,7 @@ public void Every_CheatEngine_SDK_name_written_into_generated_code_denotes_a_rea else { _ = FindType(text) - ?? throw new InvalidOperationException($"{name}: no such type in the SDK assemblies."); + ?? throw new InvalidOperationException($"{name}: no such type in the SDK assemblies."); } } } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaGlobalCallEmitterTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaGlobalCallEmitterTests.cs index 6f8ed9d2..6220f3d2 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaGlobalCallEmitterTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaGlobalCallEmitterTests.cs @@ -187,7 +187,10 @@ public void ResultCount_follows_the_form() LuaGlobalCallModel throwingVoid = new("g", "s", "static", "G", string.Empty, EquatableArray.Empty, LuaCallForm.Throwing, EquatableArray.Empty, null, false); - LuaGlobalCallModel throwingValue = throwingVoid with { ReturnKind = LuaValueKind.Double }; + LuaGlobalCallModel throwingValue = throwingVoid with + { + ReturnKind = LuaValueKind.Double + }; Assert.Equal(0, throwingVoid.ResultCount); Assert.Equal(1, throwingValue.ResultCount); @@ -287,10 +290,10 @@ public void Optional_and_variadic_shapes_are_reported_by_the_model_and_their_loc writer.ToString()); foreach (string local in (string[]) - [ - "__L", "__operation", "__top", "__ok", "__status", "__result", - "__resolution", "__exception", "__argc", "__rest" - ]) + [ + "__L", "__operation", "__top", "__ok", "__status", "__result", + "__resolution", "__exception", "__argc", "__rest" + ]) { Assert.True(LuaGlobalCallEmitter.IsReservedLocal(local), local); } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaThunkEmitterTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaThunkEmitterTests.cs index dd241522..d4a38e64 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaThunkEmitterTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/SharedCode/LuaThunkEmitterTests.cs @@ -190,8 +190,8 @@ private static int CountOccurrences(string text, string value) { int count = 0; for (int index = text.IndexOf(value, StringComparison.Ordinal); - index >= 0; - index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) + index >= 0; + index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal)) { count++; } diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/packages.lock.json b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/packages.lock.json index ffda23d3..c599bc14 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBindings.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.CSharp": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogDiagnosticsTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogDiagnosticsTests.cs index 13f7de22..a0db3bef 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogDiagnosticsTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogDiagnosticsTests.cs @@ -76,16 +76,16 @@ public void A_valid_and_malformed_catalogue_both_receive_the_ambiguity_diagnosti Assert.Equal(3, run.GeneratorDiagnostics.Length); Assert.Contains(run.GeneratorDiagnostics, static diagnostic => string.Equals(diagnostic.Id, "CESDK4001", StringComparison.Ordinal) - && string.Equals(diagnostic.Location.GetLineSpan().Path, InvalidPath, - StringComparison.Ordinal)); + && string.Equals(diagnostic.Location.GetLineSpan().Path, InvalidPath, + StringComparison.Ordinal)); Assert.Contains(run.GeneratorDiagnostics, static diagnostic => string.Equals(diagnostic.Id, "CESDK4002", StringComparison.Ordinal) - && string.Equals(diagnostic.Location.GetLineSpan().Path, ValidPath, - StringComparison.Ordinal)); + && string.Equals(diagnostic.Location.GetLineSpan().Path, ValidPath, + StringComparison.Ordinal)); Assert.Contains(run.GeneratorDiagnostics, static diagnostic => string.Equals(diagnostic.Id, "CESDK4002", StringComparison.Ordinal) - && string.Equals(diagnostic.Location.GetLineSpan().Path, InvalidPath, - StringComparison.Ordinal)); + && string.Equals(diagnostic.Location.GetLineSpan().Path, InvalidPath, + StringComparison.Ordinal)); } [Fact] diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogEmissionTests.cs b/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogEmissionTests.cs index 25ee0184..e21b69a1 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogEmissionTests.cs +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/Generator/CatalogEmissionTests.cs @@ -21,7 +21,7 @@ public void Catalog_operations_emit_a_numeric_sorted_enum_and_required_bitmap() Assert.Contains("PushBytes = 0", generated, StringComparison.Ordinal); Assert.Contains("PushHostObject = 10", generated, StringComparison.Ordinal); Assert.True(generated.IndexOf("PushBytes = 0", StringComparison.Ordinal) - < generated.IndexOf("PushHostObject = 10", StringComparison.Ordinal)); + < generated.IndexOf("PushHostObject = 10", StringComparison.Ordinal)); Assert.Contains("internal const int Count = 2;", generated, StringComparison.Ordinal); Assert.Contains("internal const ulong RequiredBitmap = 0x0000000000000401UL;", generated, StringComparison.Ordinal); diff --git a/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/packages.lock.json b/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/packages.lock.json index 6d46d526..1e2f345b 100644 --- a/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.SourceGenerators.LuaBridgeContract.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.CodeAnalysis.CSharp": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Tests.Shared/NativeLua/NativeLuaProbe.cs b/tests/CheatEngine.SDK.Tests.Shared/NativeLua/NativeLuaProbe.cs index eb90ba44..5f3393ed 100644 --- a/tests/CheatEngine.SDK.Tests.Shared/NativeLua/NativeLuaProbe.cs +++ b/tests/CheatEngine.SDK.Tests.Shared/NativeLua/NativeLuaProbe.cs @@ -65,7 +65,7 @@ private static bool TryGetFullPath(string candidate, out string fullPath) return true; } catch (Exception exception) when (exception is ArgumentException or NotSupportedException - or PathTooLongException or SecurityException) + or PathTooLongException or SecurityException) { fullPath = string.Empty; return false; diff --git a/tests/CheatEngine.SDK.Tests.Shared/NativeLua/PartialLuaModule.cs b/tests/CheatEngine.SDK.Tests.Shared/NativeLua/PartialLuaModule.cs index f1b74d74..d4b7055f 100644 --- a/tests/CheatEngine.SDK.Tests.Shared/NativeLua/PartialLuaModule.cs +++ b/tests/CheatEngine.SDK.Tests.Shared/NativeLua/PartialLuaModule.cs @@ -101,7 +101,7 @@ internal static void RenameExport(byte[] image, string existing, string replacem int signature = BinaryPrimitives.ReadInt32LittleEndian(image.AsSpan(PeHeaderPointerOffset)); int optionalHeader = signature + OptionalHeaderOffsetFromSignature; if (BinaryPrimitives.ReadUInt32LittleEndian(image.AsSpan(signature)) != 0x4550 || - BinaryPrimitives.ReadUInt16LittleEndian(image.AsSpan(optionalHeader)) != Pe32PlusMagic) + BinaryPrimitives.ReadUInt16LittleEndian(image.AsSpan(optionalHeader)) != Pe32PlusMagic) { throw new InvalidOperationException("The Lua fixture is not a PE32+ image."); } @@ -132,8 +132,8 @@ internal static void RenameExport(byte[] image, string existing, string replacem } bool staysSorted = (target == 0 || string.CompareOrdinal(names[target - 1].Name, replacement) < 0) && - (target == names.Count - 1 || - string.CompareOrdinal(replacement, names[target + 1].Name) < 0); + (target == names.Count - 1 || + string.CompareOrdinal(replacement, names[target + 1].Name) < 0); if (!staysSorted) { throw new InvalidOperationException($"'{replacement}' would leave the export name table unsorted."); diff --git a/tests/CheatEngine.SDK.Tests.Shared/packages.lock.json b/tests/CheatEngine.SDK.Tests.Shared/packages.lock.json index dabc335c..0fcd840b 100644 --- a/tests/CheatEngine.SDK.Tests.Shared/packages.lock.json +++ b/tests/CheatEngine.SDK.Tests.Shared/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "MinVer": { "type": "Direct", diff --git a/tests/CheatEngine.SDK.Tests/Architecture/ProjectDependencyDirectionTests.cs b/tests/CheatEngine.SDK.Tests/Architecture/ProjectDependencyDirectionTests.cs index 733381ad..39c8ddd6 100644 --- a/tests/CheatEngine.SDK.Tests/Architecture/ProjectDependencyDirectionTests.cs +++ b/tests/CheatEngine.SDK.Tests/Architecture/ProjectDependencyDirectionTests.cs @@ -80,7 +80,7 @@ public void Shipping_libraries_keep_the_declared_lower_layer_runtime_graph() discoveredLibraryProjects.Add(projectRelativePath); if (!ExpectedLibraryRuntimeDependencies.TryGetValue(projectRelativePath, - out string[]? expectedDependencies)) + out string[]? expectedDependencies)) { violations.Add($"{projectRelativePath}: is not declared in the shipping library graph."); continue; @@ -266,7 +266,7 @@ private static void AddForbiddenDependencyViolations(List violations, st } if (value.Contains("CheatEngine.Client", StringComparison.OrdinalIgnoreCase) || - value.Contains("CheatEngine.Mcp", StringComparison.OrdinalIgnoreCase)) + value.Contains("CheatEngine.Mcp", StringComparison.OrdinalIgnoreCase)) { violations.Add( $"{GetRepositoryRelativePath(metadataPath)}: {node.LocalName} {attributeName}='{value}' references a higher layer."); @@ -329,7 +329,7 @@ private static IEnumerable EnumerateBuildMetadataFiles() private static IEnumerable EnumerateRepositoryFiles(string searchPattern) { foreach (string path in - Directory.EnumerateFiles(RepositoryLayout.Root, searchPattern, SearchOption.AllDirectories)) + Directory.EnumerateFiles(RepositoryLayout.Root, searchPattern, SearchOption.AllDirectories)) { string relativePath = GetRepositoryRelativePath(path); if (!IsGeneratedPath(relativePath)) @@ -353,20 +353,20 @@ private static string GetRepositoryRelativePath(string fullPath) private static bool IsGeneratedPath(string relativePath) { return relativePath.StartsWith("artifacts/", StringComparison.Ordinal) || - relativePath.Contains("/bin/", StringComparison.Ordinal) || - relativePath.Contains("/obj/", StringComparison.Ordinal); + relativePath.Contains("/bin/", StringComparison.Ordinal) || + relativePath.Contains("/obj/", StringComparison.Ordinal); } private static bool IsRoslynComponent(string projectRelativePath) { return projectRelativePath.StartsWith("analyzers/", StringComparison.Ordinal) || - projectRelativePath.StartsWith("source-generators/", StringComparison.Ordinal); + projectRelativePath.StartsWith("source-generators/", StringComparison.Ordinal); } private static bool IsShippingProject(string projectRelativePath) { return projectRelativePath.StartsWith("libs/", StringComparison.Ordinal) || - string.Equals(projectRelativePath, UmbrellaProject, StringComparison.Ordinal); + string.Equals(projectRelativePath, UmbrellaProject, StringComparison.Ordinal); } private static XmlDocument LoadProjectDocument(string projectPath) diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/CommittedFile.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/CommittedFile.cs index 66f50e93..61b8dbc6 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/CommittedFile.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/CommittedFile.cs @@ -36,7 +36,10 @@ public static async Task ReadBytesAsync(string repoRelativePath) startInfo.ArgumentList.Add("blob"); startInfo.ArgumentList.Add($"HEAD:{repoRelativePath}"); - using Process process = new() { StartInfo = startInfo }; + using Process process = new() + { + StartInfo = startInfo + }; try { process.Start(); diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/EntryPointProbe.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/EntryPointProbe.cs index ac57aa94..2997b0f7 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/EntryPointProbe.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/EntryPointProbe.cs @@ -27,7 +27,7 @@ public static (bool TypeExists, bool MethodExists) Probe(string assemblyPath) { TypeDefinition type = reader.GetTypeDefinition(typeHandle); if (!string.Equals(reader.GetString(type.Namespace), TypeNamespace, StringComparison.Ordinal) - || !string.Equals(reader.GetString(type.Name), TypeName, StringComparison.Ordinal)) + || !string.Equals(reader.GetString(type.Name), TypeName, StringComparison.Ordinal)) { continue; } @@ -36,7 +36,7 @@ public static (bool TypeExists, bool MethodExists) Probe(string assemblyPath) { MethodDefinition method = reader.GetMethodDefinition(methodHandle); if (string.Equals(reader.GetString(method.Name), MethodName, StringComparison.Ordinal) && - method.GetParameters().Count == 2) + method.GetParameters().Count == 2) { return (TypeExists: true, MethodExists: true); } diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/PackagedUmbrellaFixture.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/PackagedUmbrellaFixture.cs index 40d63157..1f86b27e 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/PackagedUmbrellaFixture.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/PackagedUmbrellaFixture.cs @@ -549,10 +549,10 @@ await Task.Delay(TimeSpan.FromSeconds(20 * attempt), TestContext.Current.Cancell private static bool LooksLikeFileLockContention(string output) { return output.Contains("being used by another process", StringComparison.OrdinalIgnoreCase) - || output.Contains("cannot access the file", StringComparison.OrdinalIgnoreCase) - || output.Contains("MSB3021", StringComparison.Ordinal) - || output.Contains("MSB3027", StringComparison.Ordinal) - || output.Contains("MSB3061", StringComparison.Ordinal); + || output.Contains("cannot access the file", StringComparison.OrdinalIgnoreCase) + || output.Contains("MSB3021", StringComparison.Ordinal) + || output.Contains("MSB3027", StringComparison.Ordinal) + || output.Contains("MSB3061", StringComparison.Ordinal); } private async Task InitializeDefaultConsumerAsync(string tempRoot, string feedDirectory, string packagesDirectory) @@ -630,7 +630,8 @@ private async Task InitializeLuaFunctionConsumersAsync(string tempRoot, string f feedDirectory, new ThrowawayConsumer.CreateOptions { - ExtraProperties = " true\n", IncludeLuaFunction = true + ExtraProperties = " true\n", + IncludeLuaFunction = true }); ProcessResult optInRestore = await optInConsumer.RestoreAsync(RestoreTimeout, packagesDirectory).ConfigureAwait(false); diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/ProcessRunner.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/ProcessRunner.cs index 81c02f55..7e82eff5 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/ProcessRunner.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/ProcessRunner.cs @@ -24,7 +24,10 @@ public static async Task RunAsync(string fileName, string argumen CreateNoWindow = true }; - using Process process = new() { StartInfo = startInfo }; + using Process process = new() + { + StartInfo = startInfo + }; StringBuilder standardOutput = new(); StringBuilder standardError = new(); process.OutputDataReceived += (_, e) => diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/RepositoryLayout.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/RepositoryLayout.cs index fbb0c418..2ad3cdfc 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/RepositoryLayout.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/RepositoryLayout.cs @@ -20,8 +20,8 @@ public static string PathOf(string relativePath) private static string FindRoot() { for (DirectoryInfo? directory = new(AppContext.BaseDirectory); - directory is not null; - directory = directory.Parent) + directory is not null; + directory = directory.Parent) { if (File.Exists(Path.Combine(directory.FullName, SolutionFileName))) { diff --git a/tests/CheatEngine.SDK.Tests/Infrastructure/UmbrellaPackageSource.cs b/tests/CheatEngine.SDK.Tests/Infrastructure/UmbrellaPackageSource.cs index 0c2d6341..7d9d82ae 100644 --- a/tests/CheatEngine.SDK.Tests/Infrastructure/UmbrellaPackageSource.cs +++ b/tests/CheatEngine.SDK.Tests/Infrastructure/UmbrellaPackageSource.cs @@ -75,9 +75,9 @@ public static bool IsUmbrellaPackageFileName(string fileName) ArgumentNullException.ThrowIfNull(fileName); string prefix = UmbrellaPackage.Id + "."; return fileName.StartsWith(prefix, StringComparison.Ordinal) - && fileName.EndsWith(NupkgExtension, StringComparison.Ordinal) - && fileName.Length > prefix.Length + NupkgExtension.Length - && SemanticVersion().IsMatch(fileName[prefix.Length..^NupkgExtension.Length]); + && fileName.EndsWith(NupkgExtension, StringComparison.Ordinal) + && fileName.Length > prefix.Length + NupkgExtension.Length + && SemanticVersion().IsMatch(fileName[prefix.Length..^NupkgExtension.Length]); } private static InvalidOperationException Rejected(string value, string reason) diff --git a/tests/CheatEngine.SDK.Tests/Packaging/BridgeAuditManifestTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/BridgeAuditManifestTests.cs index c743736d..b1070ba1 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/BridgeAuditManifestTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/BridgeAuditManifestTests.cs @@ -27,7 +27,9 @@ public sealed partial class BridgeAuditManifestTests private static readonly JsonSerializerOptions s_manifestFormat = new() { - WriteIndented = true, IndentSize = 2, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + WriteIndented = true, + IndentSize = 2, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; [Fact] @@ -150,7 +152,7 @@ private static async Task ExpectedManifestJsonAsync() private static async Task StaleMessageAsync() { return $"{ManifestPath} does not describe the committed bridge. Replace it with:{Environment.NewLine}" + - await ExpectedManifestJsonAsync().ConfigureAwait(false); + await ExpectedManifestJsonAsync().ConfigureAwait(false); } private static async Task ReadCommittedBridgeAsync() @@ -215,7 +217,7 @@ private static async Task ReadCommittedBridgeAsync() private static JsonNode ReadManifest() { return JsonNode.Parse(File.ReadAllText(RepositoryLayout.PathOf(ManifestPath))) - ?? throw new InvalidDataException($"{ManifestPath} is empty."); + ?? throw new InvalidDataException($"{ManifestPath} is empty."); } private static string BridgeInput(string fileName) @@ -226,7 +228,7 @@ private static string BridgeInput(string fileName) private static JsonObject Object(JsonNode parent, string name) { return parent[name] as JsonObject - ?? throw new InvalidDataException($"{ManifestPath} has no '{name}' object."); + ?? throw new InvalidDataException($"{ManifestPath} has no '{name}' object."); } private static JsonArray JsonStrings(IReadOnlyList values) @@ -257,7 +259,7 @@ private static List Strings(JsonNode? node) private static bool SetEquals(IReadOnlyList expected, List actual) { return expected.Count == actual.Count - && new HashSet(expected, StringComparer.Ordinal).SetEquals(actual); + && new HashSet(expected, StringComparer.Ordinal).SetEquals(actual); } private static string Sha256(byte[] content) diff --git a/tests/CheatEngine.SDK.Tests/Packaging/CleanConsumerIsolationTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/CleanConsumerIsolationTests.cs index 8d186494..fb9fe1a3 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/CleanConsumerIsolationTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/CleanConsumerIsolationTests.cs @@ -52,7 +52,7 @@ public void Consumer_manifests_contain_no_repository_or_developer_path() string path = Path.Combine(folder, manifest); Assert.True(File.Exists(path), $"'{path}' was not produced."); foreach (string leak in ConsumerManifestRules.WorkspaceLeaks(File.ReadAllText(path), - RepositoryLayout.Root)) + RepositoryLayout.Root)) { offenders.Add($"{path}: {leak}"); } @@ -75,7 +75,7 @@ public void Every_deployed_sdk_assembly_is_byte_identical_to_its_packed_lib_entr foreach (string entry in fixture.PackageEntries) { if (!entry.StartsWith(LibraryPrefix, StringComparison.Ordinal) - || !entry.EndsWith(".dll", StringComparison.Ordinal)) + || !entry.EndsWith(".dll", StringComparison.Ordinal)) { continue; } diff --git a/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRules.cs b/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRules.cs index 021ebd00..196d82d6 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRules.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/ConsumerManifestRules.cs @@ -25,7 +25,7 @@ public static List SdkLibraryProblems(string depsJson, string packageVer string key = $"{UmbrellaPackage.Id}/{packageVersion}"; using JsonDocument document = JsonDocument.Parse(depsJson); if (!document.RootElement.TryGetProperty("libraries", out JsonElement libraries) - || !libraries.TryGetProperty(key, out JsonElement library)) + || !libraries.TryGetProperty(key, out JsonElement library)) { problems.Add($"library '{key}' is absent"); return problems; @@ -68,7 +68,7 @@ public static List ProjectTypedSdkLibraries(string depsJson) foreach (JsonProperty library in libraries.EnumerateObject()) { if (library.Name.StartsWith(UmbrellaPackage.Id, StringComparison.OrdinalIgnoreCase) - && string.Equals(StringProperty(library.Value, "type"), "project", StringComparison.Ordinal)) + && string.Equals(StringProperty(library.Value, "type"), "project", StringComparison.Ordinal)) { offenders.Add($"library '{library.Name}' is project-typed"); } @@ -115,14 +115,14 @@ public static List WorkspaceLeaks(string manifestText, string repository public static bool IsLuaRuntimeFileName(string fileName) { return fileName.StartsWith("lua", StringComparison.OrdinalIgnoreCase) - && fileName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase); + && fileName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase); } private static string StringProperty(JsonElement element, string name) { return element.ValueKind == JsonValueKind.Object - && element.TryGetProperty(name, out JsonElement value) - && value.ValueKind == JsonValueKind.String + && element.TryGetProperty(name, out JsonElement value) + && value.ValueKind == JsonValueKind.String ? value.GetString()! : ""; } diff --git a/tests/CheatEngine.SDK.Tests/Packaging/LivePluginClosureTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/LivePluginClosureTests.cs index 9e51e227..e26e281a 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/LivePluginClosureTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/LivePluginClosureTests.cs @@ -61,7 +61,7 @@ public void Live_plugin_output_closure_matches_the_workspace_bridge(string proje { string name = library.Name[..library.Name.IndexOf('/', StringComparison.Ordinal)]; if (name.StartsWith("CheatEngine.SDK.", StringComparison.Ordinal) && - !string.Equals(name, project, StringComparison.Ordinal)) + !string.Equals(name, project, StringComparison.Ordinal)) { sdkLibraries.Add(name); } @@ -153,7 +153,7 @@ private static string BundleFolder(string project) { TypeDefinition type = reader.GetTypeDefinition(typeHandle); if (!string.Equals(reader.GetString(type.Namespace), "CESDK", StringComparison.Ordinal) - || !string.Equals(reader.GetString(type.Name), "CESDK", StringComparison.Ordinal)) + || !string.Equals(reader.GetString(type.Name), "CESDK", StringComparison.Ordinal)) { continue; } diff --git a/tests/CheatEngine.SDK.Tests/Packaging/PackagedUmbrellaTraitTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/PackagedUmbrellaTraitTests.cs index 6e6f0d14..6677f1fa 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/PackagedUmbrellaTraitTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/PackagedUmbrellaTraitTests.cs @@ -30,13 +30,13 @@ public void Every_packaged_umbrella_collection_class_carries_the_packaging_trait if (!HasPackagingTrait(type)) { offenders.Add($"{type.FullName} joins '{PackagedUmbrellaSuite.Name}' without " + - $"[Trait(\"{CategoryTrait}\", UmbrellaPackage.PackagingCategory)]."); + $"[Trait(\"{CategoryTrait}\", UmbrellaPackage.PackagingCategory)]."); } } else if (ReceivesTheFixture(type)) { offenders.Add($"{type.FullName} receives {nameof(PackagedUmbrellaFixture)} outside collection " + - $"'{PackagedUmbrellaSuite.Name}', so it would get its own pack."); + $"'{PackagedUmbrellaSuite.Name}', so it would get its own pack."); } } @@ -89,8 +89,8 @@ private static List TestTypes() private static bool HasTestMethod(Type type) { foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | - BindingFlags.Static | - BindingFlags.DeclaredOnly)) + BindingFlags.Static | + BindingFlags.DeclaredOnly)) { foreach (CustomAttributeData attribute in method.GetCustomAttributesData()) { @@ -144,9 +144,9 @@ private static bool HasPackagingTrait(MemberInfo member) foreach (CustomAttributeData attribute in member.GetCustomAttributesData()) { if (attribute.AttributeType == typeof(TraitAttribute) - && attribute.ConstructorArguments.Count == 2 - && Equals(attribute.ConstructorArguments[0].Value, CategoryTrait) - && Equals(attribute.ConstructorArguments[1].Value, UmbrellaPackage.PackagingCategory)) + && attribute.ConstructorArguments.Count == 2 + && Equals(attribute.ConstructorArguments[0].Value, CategoryTrait) + && Equals(attribute.ConstructorArguments[1].Value, UmbrellaPackage.PackagingCategory)) { return true; } @@ -158,8 +158,8 @@ private static bool HasPackagingTrait(MemberInfo member) private static bool HasPackagingTraitOnAMethod(Type type) { foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | - BindingFlags.Static | - BindingFlags.DeclaredOnly)) + BindingFlags.Static | + BindingFlags.DeclaredOnly)) { if (HasPackagingTrait(method)) { diff --git a/tests/CheatEngine.SDK.Tests/Packaging/SupplyChainPackageTests.cs b/tests/CheatEngine.SDK.Tests/Packaging/SupplyChainPackageTests.cs index 3958249b..6cbffa28 100644 --- a/tests/CheatEngine.SDK.Tests/Packaging/SupplyChainPackageTests.cs +++ b/tests/CheatEngine.SDK.Tests/Packaging/SupplyChainPackageTests.cs @@ -64,8 +64,8 @@ public void Sbom_lists_every_shipped_assembly_and_the_native_bridge_with_its_sha foreach (string entry in fixture.PackageEntries) { if ((entry.StartsWith("lib/net10.0/", StringComparison.Ordinal) - || entry.StartsWith("analyzers/dotnet/cs/", StringComparison.Ordinal)) - && entry.EndsWith(".dll", StringComparison.Ordinal)) + || entry.StartsWith("analyzers/dotnet/cs/", StringComparison.Ordinal)) + && entry.EndsWith(".dll", StringComparison.Ordinal)) { shipped.Add(entry); } @@ -159,7 +159,7 @@ public void Embedded_libraries_carry_source_link_to_the_repository_commit() string? sourceLink = null; foreach (CustomDebugInformationHandle handle in - pdb.GetCustomDebugInformation(EntityHandle.ModuleDefinition)) + pdb.GetCustomDebugInformation(EntityHandle.ModuleDefinition)) { CustomDebugInformation information = pdb.GetCustomDebugInformation(handle); if (pdb.GetGuid(information.Kind) == s_sourceLinkKind) @@ -187,7 +187,7 @@ private List LibraryEntries() foreach (string entry in fixture.PackageEntries) { if (entry.StartsWith("lib/net10.0/CheatEngine.SDK", StringComparison.Ordinal) - && entry.EndsWith(".dll", StringComparison.Ordinal)) + && entry.EndsWith(".dll", StringComparison.Ordinal)) { libraries.Add(entry); } @@ -228,7 +228,7 @@ private static Dictionary SbomFileSha256(ZipArchive archive) private static byte[] ReadEntry(ZipArchive archive, string entryName) { ZipArchiveEntry entry = archive.GetEntry(entryName) - ?? throw new InvalidOperationException($"The package has no '{entryName}' entry."); + ?? throw new InvalidOperationException($"The package has no '{entryName}' entry."); using Stream stream = entry.Open(); using MemoryStream copy = new(); stream.CopyTo(copy); diff --git a/tests/CheatEngine.SDK.Tests/packages.lock.json b/tests/CheatEngine.SDK.Tests/packages.lock.json index fe279b25..b254c5b5 100644 --- a/tests/CheatEngine.SDK.Tests/packages.lock.json +++ b/tests/CheatEngine.SDK.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.Testing.Extensions.CodeCoverage": { "type": "Direct", From fad2b0326aa359b60660afad303333715fafe5e0 Mon Sep 17 00:00:00 2001 From: AriusII Date: Wed, 23 Sep 2026 23:50:49 +0200 Subject: [PATCH 4/4] Refresh the AotProbe lock file for the Meziantou.Analyzer 3.0.290 pin tests/CheatEngine.SDK.AotProbe isn't part of CheatEngine.SDK.slnx, so the solution-wide restore in the previous commit never touched its packages.lock.json. It was still pinned to Meziantou.Analyzer 3.0.283 while every other lock file in the tree had already moved to the 3.0.290 GlobalPackageReference, which failed CI's locked-mode restore (NU1004) in the Lock files, Detect NuGet dependencies, and Native AOT publication probe jobs. --- tests/CheatEngine.SDK.AotProbe/packages.lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/CheatEngine.SDK.AotProbe/packages.lock.json b/tests/CheatEngine.SDK.AotProbe/packages.lock.json index 3b2f244a..43937847 100644 --- a/tests/CheatEngine.SDK.AotProbe/packages.lock.json +++ b/tests/CheatEngine.SDK.AotProbe/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "Meziantou.Analyzer": { "type": "Direct", - "requested": "[3.0.283, )", - "resolved": "3.0.283", - "contentHash": "8UKUK7wiL+DMA/c8mGPK9J24wLKDZ5DHKDv38GlyeJNkza9Q1yQziudEt1Op7/+0CL1vVi41PhACj1e6948f7w==" + "requested": "[3.0.290, )", + "resolved": "3.0.290", + "contentHash": "vdSXgMEPil67EFwkcicjSCMnB7TdhUNiR1Fjw1P8MN+UeX6yP8wTb7cNT20H/ejHuUxkrxQS1Rz4QcJuMLmCkA==" }, "Microsoft.DotNet.ILCompiler": { "type": "Direct",