Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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 <auto-generated/> 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.
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
Loading
Loading