Skip to content

feat: add immutability assertions and filters for types#334

Merged
vbreuss merged 2 commits into
mainfrom
feature/immutability-assertions
Jun 6, 2026
Merged

feat: add immutability assertions and filters for types#334
vbreuss merged 2 commits into
mainfrom
feature/immutability-assertions

Conversation

@vbreuss
Copy link
Copy Markdown
Member

@vbreuss vbreuss commented Jun 6, 2026

IsImmutable / IsNotImmutable for single types, AreImmutable / AreNotImmutable for type collections (including IAsyncEnumerable overloads) and WhichAreImmutable / WhichAreNotImmutable filters.

A type is considered immutable when all instance fields (including inherited ones) are readonly and all instance properties (including inherited ones) have no setter or an init-only setter; init-only setters count as immutable, static members are ignored. Failure messages list the offending mutable members for actionable feedback.


Implements #329: IsImmutable / IsNotImmutable for single types,
AreImmutable / AreNotImmutable for type collections (including
IAsyncEnumerable overloads) and WhichAreImmutable / WhichAreNotImmutable
filters.

A type is considered immutable when all instance fields (including
inherited ones) are readonly and all instance properties (including
inherited ones) have no setter or an init-only setter; init-only
setters count as immutable, static members are ignored. Failure
messages list the offending mutable members for actionable feedback.
@vbreuss vbreuss self-assigned this Jun 6, 2026
@vbreuss vbreuss added the enhancement New feature or request label Jun 6, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

Test Results

    13 files  ±  0      13 suites  ±0   9m 55s ⏱️ + 2m 34s
 6 454 tests + 54   6 451 ✅ + 54   3 💤 ±0  0 ❌ ±0 
38 569 runs  +324  38 556 ✅ +324  13 💤 ±0  0 ❌ ±0 

Results for commit ba61c36. ± Comparison against base commit 9a8f4d6.

♻️ This comment has been updated with latest results.

Pin behavior for structs (mutable and readonly), record structs
(positional with set vs readonly with init), positional records, enums,
interfaces (settable vs get-only properties), static classes, indexers
with setters, properties with private setters, inherited non-private
mutable fields and open generic type definitions.

Fix Sonar findings: make the static fixture field private (S2223) and
replace the TheoryData collection expressions with object initializers
to avoid zero-length array allocations (CA1825).
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 6, 2026

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

🚀 Benchmark Results

Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Intel Xeon Platinum 8370C CPU 2.80GHz (Max: 2.79GHz), 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.300
[Host] : .NET 10.0.8 (10.0.8, 10.0.826.23019), X64 RyuJIT x86-64-v4
DefaultJob : .NET 10.0.8 (10.0.8, 10.0.826.23019), X64 RyuJIT x86-64-v4

Method Mean Error StdDev Gen0 Allocated
TypeIsNotStatic_aweXpect 228.4 ns 1.24 ns 1.10 ns 0.0257 648 B

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

👽 Mutation Results

Mutation testing badge

aweXpect.Reflection

Details
File Score Killed Survived Timeout No Coverage Ignored Compile Errors Total Detected Total Undetected Total Mutants
Filters/TypeFilters.WhichAreImmutable.cs 100.00% 3 0 0 0 0 0 3 0 3
Helpers/TypeHelpers.cs 82.21% 447 69 6 29 182 64 453 98 797
ThatType.IsImmutable.cs 100.00% 13 0 0 0 3 7 13 0 23
ThatTypes.AreImmutable.cs 100.00% 18 0 0 0 4 12 18 0 34

The final mutation score is 83.25%

Coverage Thresholds: high:80 low:60 break:0

@vbreuss vbreuss merged commit 7bddf2d into main Jun 6, 2026
12 checks passed
@vbreuss vbreuss deleted the feature/immutability-assertions branch June 6, 2026 07:47
@vbreuss vbreuss linked an issue Jun 6, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add immutability assertions and filters for types

1 participant