Skip to content

Close IDE/CA build-enforcement gaps in the C# 14 style contract - #87

Merged
AriusII merged 4 commits into
mainfrom
chore/csharp14-net10-editorconfig-hardening
Sep 23, 2026
Merged

AriusII merged 4 commits into
mainfrom
chore/csharp14-net10-editorconfig-hardening

Conversation

@AriusII

@AriusII AriusII commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Closes IDE/CA severity gaps left at their non-blocking SDK-default
    (Suggestion/Silent) despite EnforceCodeStyleInBuild, and fills in three
    naming-convention rules that previously matched nothing (async-suffix,
    const/static-readonly fields, non-private fields).
  • Makes the net10.0 assemblies' AOT/trim guarantees explicit in
    eng/Shipping.props (IsTrimmable, EnableTrimAnalyzer, EnableAotAnalyzer,
    EnableSingleFileAnalyzer, VerifyReferenceTrimCompatibility).
  • Repairs a set of regressions from an IDE-wide reformat pass that landed
    on this branch mid-review: five classes silently lost the partial
    modifier their LuaBindings-generated members depend on, the CE 7.7
    bootstrap's CESDK namespace got renamed (breaking CE's hard-coded
    CESDK.CESDK host lookup), two using CheatEngine.SDK.Engine.Generated;
    directives were dropped as apparently-unused, three
    CompatibilitySuppressions.xml <Target> entries got line-wrapped
    (breaking ApiCompat's exact-match lookup), a markdown table drifted past
    a doc-consistency test's exact substring check, and one line in the
    native Lua bridge changed in a way that invalidated its pinned SHA-256
    proof record.
  • Splits a test method that grew past MA0051's 60-line limit.

Test plan

  • dotnet build CheatEngine.SDK.slnx -c Debug — 0 warnings, 0 errors
  • dotnet format CheatEngine.SDK.slnx --verify-no-changes — clean
  • dotnet test --solution CheatEngine.SDK.slnx -c Debug --fail-skips on
    — 4167/4168; the sole failure (PackedConsumerBindingTests Native
    AOT publish) reproduces identically on main and needs the
    MSVC/vswhere.exe linker toolchain this environment lacks
  • Expanded .editorconfig with build-enforced analyzer severities, style preferences, and naming rules. Added SYSLIB1054 as an error and enabled required API analyzer files.
  • Enabled explicit trim, AOT, and single-file analysis settings in eng/Shipping.props, including referenced-assembly trim-compatibility verification.
  • Updated Meziantou.Analyzer to 3.0.290 in central package management and lock files, including the AotProbe lock file.
  • Applied analyzer-driven syntax and code updates across SDK, generator, and test projects. Notable test changes add a synchronize stand-in, refine bridge-export assertions, and extract a dependency snapshot helper.
  • PR objectives report repairs to formatting-pass regressions, including restored partial modifiers and generator imports, a corrected bootstrap namespace, compatibility suppression updates, and a native Lua bridge change. The supplied change details do not describe each repair.
  • Reported validation: Debug build and formatting verification passed; 4167 of 4168 tests passed. The remaining Native AOT publish test reportedly also fails on main and requires an unavailable MSVC/vswhere.exe linker toolchain.

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<Category> 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.
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 `<Target>` 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).
@coderabbitai

coderabbitai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: CheatEngineNet/CheatEngine.SDK/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: ce45862e-888c-451e-b68e-432dabf3fefd

📥 Commits

Reviewing files that changed from the base of the PR and between 9995088 and fad2b03.

📒 Files selected for processing (1)
  • tests/CheatEngine.SDK.AotProbe/packages.lock.json
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • CheatEngineNet/CheatEngine.Client (manual)

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The pull request updates analyzer settings and the Meziantou.Analyzer package across the solution. It explicitly enables trimming and AOT analysis checks in shipping properties. It also changes several code expressions and internal state declarations, adds test support for Lua synchronization, and updates tests and documentation. Most other edits reformat existing code, tables, and comments without changing their described behavior.

Merge Risk: ⚪ Minimal · up to fad2b

The lock-file update matches the repository’s analyzer version pin; no actionable merge risk is identified.

🚥 Pre-merge checks | ✅ 9 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Public Api And Compatibility ⚠️ Warning The PR changes src/CheatEngine.SDK/CompatibilitySuppressions.xml, but the diff only removes unused XML namespace declarations. It introduces no intentional compatibility break, and the PR does not a… Revert the namespace-only change to src/CheatEngine.SDK/CompatibilitySuppressions.xml. If an intentional compatibility break is required, make the API change, record it in the owning PublicAPI.Unshipped.txt, and declare the break in bot…
✅ Passed checks (9 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main changes, starts with an uppercase imperative verb, uses no prefix, has no trailing period, and is 63 characters long.
Native Abi Evidence ✅ Passed PASS. The PR changes files under libs/CheatEngine.SDK.Abi/ and updates ABI tests under tests/CheatEngine.SDK.Abi.Tests/, so the check applies. The changed ABI documentation identifies `cepluginsdk…
Lua Stack Balance Tests ✅ Passed The check applies because the PR changes scoped Lua source. The changed Lua stack operations in LuaRuntime only replace s_stampKey with StampKeyForTests; push, raw-set, raw-get, and pop behavior…
Lua Concurrency Contract ✅ Passed PASS. The PR changes libs/CheatEngine.SDK.Lua/Runtime/**, so the check applies. The worker-thread opt-in remains [Experimental("CESDK5001")]; the default remains `LuaThreadAdmission.MainThreadOnly…
Native Host Emulator Evidence ✅ Passed Applicable because the PR changes tests/CheatEngine.SDK.Hosting.Tests/Coexistence/. The authoritative diff contains only formatting, positional-argument, and discard changes in the emulator tests and …
Public Api Documentation And Changelog ✅ Passed The check is not triggered. The authoritative diff does not modify CHANGELOG.md or any PublicAPI.Shipped.txt/PublicAPI.Unshipped.txt file. The apparent public changes are non-API edits: HostErrorTextM…
Dependency Direction ✅ Passed PASS. The authoritative diff adds no references to CheatEngine.Client, CheatEngine.Mcp, or their namespaces or packages. It adds no client-level policy, dependency-injection registration, fluent API, …
Workflow Hygiene ✅ Passed Pass: the authoritative pull-request diff contains 277 changed files, and none are under .github/. The workflow-hygiene rules therefore do not apply.
Full details: Public Api And Compatibility

Explanation

The PR changes src/CheatEngine.SDK/CompatibilitySuppressions.xml, but the diff only removes unused XML namespace declarations. It introduces no intentional compatibility break, and the PR does not add a corresponding CHANGELOG entry. The PublicAPI baseline files are unchanged, and the lock updates are consistently tied to the Directory.Packages.props Meziantou.Analyzer 3.0.290 change; commit metadata also describes solution-wide and AotProbe lock refreshes.

Resolution

Revert the namespace-only change to src/CheatEngine.SDK/CompatibilitySuppressions.xml. If an intentional compatibility break is required, make the API change, record it in the owning PublicAPI.Unshipped.txt, and declare the break in both the PR description and CHANGELOG.md. Regenerate all changed packages.lock.json files with the required CLI restore command and retain the accompanying package-version change.


Comment @coderabbitai help to get the list of available commands.

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.
@sonarqubecloud

Copy link
Copy Markdown

@AriusII
AriusII merged commit 0f1e0ce into main Sep 23, 2026
20 checks passed
@AriusII
AriusII deleted the chore/csharp14-net10-editorconfig-hardening branch September 23, 2026 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant