Repository navigation
Releases: TNG/ArchUnitNET
Release list
0.13.5
Most of this release fixes cases where ArchUnitNET missed dependencies, crashed while loading or evaluating, or drew a wrong diagram. Dependencies inside async methods are now found in Release builds and in async lambdas, so rules that only passed because those dependencies were missing may start failing. Please read Upgrading before you update. Also in this release: ResideInNamespaceOrBelow and NotBeNestedIn, and much better PlantUML export for slices.
Highlights
- Dependencies in async code are no longer lost. In optimized builds, every dependency inside an
asyncmethod body used to be missing, and so were the dependencies inside async lambdas. Negative rules such asNotDependOnAnycould therefore pass without checking anything. - Combined rules are now consistent.
a.And(b)andb.And(a)now give the same result, andRequirePositiveResultsis respected on both sides. - Slice diagrams are correct for more namespace layouts. Packages with the same name under different parents are no longer merged. Slice names that aren't valid PlantUML ids (like nested or generic type names) no longer produce broken diagrams, and C4 style works for slices without a namespace.
Added
-
ResideInNamespaceOrBelowand its negated forms. These match a namespace and all of its sub-namespaces, so a rule no longer needs to list every sub-namespace or use a regular expression like^Foo\.Bar(\.|$)."Foo.Bar"matchesFoo.BarandFoo.Bar.Baz, but notFoo.BarBaz, and the comparison ignores case likeResideInNamespacedoes. Available asResideInNamespaceOrBelow/NotResideInNamespaceOrBelowon conditions andResideInNamespaceOrBelow/DoNotResideInNamespaceOrBelowon predicates. #511 (@StefanGreve)Types().That().ResideInNamespaceOrBelow("MyProject.Model") .Should().NotBePublic()
-
NotBeNestedIn/AreNotNestedIn. These are the negated forms ofBeNestedIn/AreNestedIn, with the same overloads. #487 (@alexanderlinne)
Fixed
Loading and dependency analysis
- Async methods in Release builds. In optimized builds the compiler creates async state machines as structs, which the loader didn't recognize. It then analyzed only the small method that starts the state machine and lost every call,
newand field access inside the method body. The loader now reads the state machine fromAsyncStateMachineAttribute/IteratorStateMachineAttribute. #500 (@iamAdarshh), fixes #498 - Async lambdas. Dependencies inside async lambdas, e.g.
Register(async () => C3.Bar()), are now added to the method that contains the lambda. #505 (@mkay-sh), fixes #230 - Assemblies that can't be resolved.
ArchLoader.Build()threwAssemblyResolutionException(for example formscorlibin .NET Framework 4.8 SDK-style projects) when a referenced assembly couldn't be found. Types from such assemblies are now treated as unavailable, as intended. #502 (@mak638), fixes #497 - Types without a namespace or assembly. Namespace and assembly predicates and conditions threw a
NullReferenceExceptiononTypes(true)when the architecture contained function pointer types. Such types now simply don't reside in any namespace or assembly. #501 (@iamAdarshh), fixes #492
Rules
And/Orare commutative. A combined rule was built from the first rule's rule creator rather than from the rule itself. As a result, a rule whose predicate matched nothing counted as failing only when it was on the right-hand side ofAnd/Or.HasNoViolations()andEvaluate()now also agree when a predicate matches nothing, and a combined rule now uses the inner rule'sRequirePositiveResultsinstead of its own. #504 (@brandhuf)AreStatic/AreNotStaticon members whose static state is unknown now behave the same asBeStatic/NotBeStatic. #485 (@alexanderlinne)Interfaces().That()...As()/.Because()now returnGivenInterfacesConjunctionWithDescription, like the other rule types. #486 (@alexanderlinne)
Slices and PlantUML export
- Packages with the same name under different parents stay separate. PlantUML identifies a package by its name, so
Orders.DomainandBilling.Domainwere drawn as oneDomainpackage, and an arrow to one of them could end in the other. Each package is now declared with its full path as its alias (package "Domain" as App.Billing.Domain) and keeps its own name as its label. #499 (@alexanderlinne) - Nested slices are written as one package tree. Before, every shared parent package was reopened once per slice. The
.pumloutput is now shorter, indented by nesting level, and reads like a hand-written diagram. Hyperlinks on nested slices, which PlantUML used to reject, now work. #499 (@alexanderlinne) - Slice names that aren't valid PlantUML ids (for example
Outer+InnerorList`1, whichSlicedByproduces from type names) now get an id of their own. The name is still used as the label. #510 (@alexanderlinne) - C4 style works for slices without a namespace.
Slices().Matching(...)withGenerationOptions.C4Stylethrew aNullReferenceException. Patterns that start with a capture group, such asMatchingWithPackages("(**).Service"), crashed the exporter in the same way. #495, #509 (@alexanderlinne) OneToOneIfSameParentNamespacearrows now put component names in brackets like every other arrow type, so names that contain..or*no longer break the diagram. #508 (@alexanderlinne)- Slice equality depends only on the slice's identifier. Two slices with the same identifier used to compare as different when their type lists were separate instances. This affected the deduplication of slices in diagrams and of violations in frozen rules. #507 (@alexanderlinne)
Upgrading
No changes to the fluent API are required. The following fixes can still change the results of existing tests:
- Rules may find new violations. Dependencies inside
asyncmethods (in Release builds) and inside async lambdas are now part of the architecture. A rule that passed because they were missing will now report them. This most likely affects test suites that run in-c Release. Note that it is still recommended to run ArchUnitNET tests with-c Debugin order to have all features available. - Combined rules may fail where they passed before. If one side of an
And/Ormatches no objects, the combined rule now fails, unless that side usesWithoutRequiringPositiveResults(). Before, this depended on the order of the two rules. - The generated PlantUML text for slices has changed. It now uses package aliases, generated ids and indentation, and empty packages are drawn as package boxes. The rendered diagrams are otherwise unchanged. If you compare generated
.pumlfiles with saved copies, update the saved copies. - Removed
HaveAnyAttributesWithArguments(object, params object[])predicate overload. This leftover was missed when the otherparams object[]overloads were removed in 0.13.0. Pass a collection instead:HaveAnyAttributesWithArguments(new object[] { a, b }). #486 PropertyMemberPredicateDefinitionwas renamed toPropertyMemberPredicatesDefinitionto match the other definition classes. This only matters if you use the class directly instead of the fluent API. #489
Testing and CI
- Large expansion and cleanup of the fluent syntax and slice test suites. Snapshot output is now independent of loader order, and the assert helpers can no longer pass without checking anything. #484, #486, #488, #489, #490, #495 (@alexanderlinne)
- NuGet packages are now published with NuGet trusted publishing instead of an API key. #483 (@alexanderlinne)
- Development tools are pinned with mise, and hk runs formatting and lint checks (csharpier, actionlint, gitleaks, zizmor) through
mise run check. Also includes security fixes in the GitHub Actions workflows and removal of the old Travis configuration. #482 (@alexanderlinne) - TUnit tests were updated to TUnit 0.90.45 and now run on Microsoft.Testing.Platform, in parallel with the VSTest-based test projects (
mise run test). #491 (@mak638), #506 (@alexanderlinne)
New Contributors
- @iamAdarshh made their first contribution in #500
- @mkay-sh made their first contribu...
0.13.4
Enhancement
- Allow disabling architecture and rule evaluation cache by @alexanderlinne in #459
- Rewrite Type Syntax Elements Tests and Refactor Type Syntax Elements by @alexanderlinne in #460
- Rewrite Member Syntax Elements Tests and Refactor Member Syntax Elements by @alexanderlinne in #464
- Rewrite Method Member Syntax Elements Tests and Refactor Method Member Syntax Elements by @alexanderlinne in #465
- Rewrite Property Member Syntax Elements Tests and Refactor Property Member Syntax Elements by @alexanderlinne in #472
- Rewrite Class Syntax Elements Tests by @alexanderlinne in #473
- Rewrite Attribute Syntax Elements Tests by @alexanderlinne in #474
- Add issue templates for bugs and feature requests by @mak638 in #466
Fixes
- fix: Refine iterator and async method body scanning by @Optano-Dev in #469
Dependency Updates
- chore(deps): update actions/checkout action to v7 by @renovate[bot] in #470
- chore(deps): update codecov/codecov-action action to v7 by @renovate[bot] in #463
- chore(deps): update dependency dotnet-sdk to v10.0.400 by @renovate[bot] in #436
- chore(deps): update dependency jetbrains.annotations to v2026 by @renovate[bot] in #467
- chore(deps): update all non-major dependencies by @renovate[bot] in #419
New Contributors
- @Optano-Dev made their first contribution in #469
Full Changelog: 0.13.3...0.13.4
0.13.3
What's Changed
- FieldMembersShould should yield a FieldMembersShouldConjunction by @alexanderlinne in #455
- Don't deduplicate Method Parameter Types by @alexanderlinne in #454
- Correct behavior of ImplementAny fluent syntax for empty arguments by @alexanderlinne in #451
Full Changelog: 0.13.2...0.13.3
0.13.2
Enhancements
- Add MSTestV4 Support by @SeMuell in #426
- Enable strong-name signing for all projects and tests by @mak638 in #445
- Only Use IOrderedCondition in Fluent Syntax Implementation by @alexanderlinne in #441
- Refactor Fluent Syntax to have a single implementation of each method by @alexanderlinne in #444
- Remove redundant "Predicates as conditions" test sections by @alexanderlinne in #449
Fixes
- DependOnAny and DoNotDependOnAny should check dependencies on referenced types by @alexanderlinne in #439
Documentation Fixes
- Use absolute Logo URL in README.md by @alexanderlinne in #440
- Fix doxygen generation by @alexanderlinne in #442
- Fix gh-pages update by @alexanderlinne in #443
New Contributors
Full Changelog: 0.13.1...0.13.2
0.13.1
0.13.0
Breaking Changes
Remove Obsolete Fluent Syntax Methods by @alexanderlinne in #412
As announced in version 0.12.0, fluent methods that take strings as an argument for matching the full name are now removed in favour of using fluent methods like .HaveName.
Refactor attribute with arguments fluent syntax methods by @alexanderlinne in #432
For HaveAttributeWithArguments and NotHaveAttributeWithArguments fluent methods, the overloads that take params object[] as arguments have been removed. This was previously ambiguous with the overload that takes an IEnumerable<object> as an argument.
Performance Enhancements
The following refactorings improve performance in our tests by ~15%:
- Refactor Object Syntax Elements by @alexanderlinne in #414
- Improve implementation of AddTypesToNamespaces loader task by @alexanderlinne in #416
- Add IOrderedCondition by @alexanderlinne in #433
CI Enhancements
- Exclude xunit.v3 and TUnit from Updates for released packages by @alexanderlinne in #411
- Run C++/CLI Test only on Windows by @alexanderlinne in #413
Dependency Updates
- Update dependency dotnet-sdk to v9.0.305 by @renovate[bot] in #407
- Update all non-major dependencies by @renovate[bot] in #346
- Update actions/setup-dotnet action to v5 by @renovate[bot] in #401
- Update mstest monorepo to v3 (major) by @renovate[bot] in #310
- chore(config): migrate renovate config by @renovate[bot] in #415
- chore(deps): update dependency xunit.v3 to v3 by @renovate[bot] in #350
- chore(deps): update dependency dotnet-sdk to v9.0.308 by @renovate[bot] in #425
- chore(deps): update github/codeql-action action to v4 by @renovate[bot] in #421
- chore(deps): update actions/checkout action to v6 by @renovate[bot] in #429
- chore(deps): update dotnet version to v10 (major) by @renovate[bot] in #406
Full Changelog: 0.12.3...0.13.0
0.12.3
Fixes
- Fix attribute loading for cases where the base class is not available by @alexanderlinne in #410
- Fix assignment of MemberGenericArguments by @ManuelWalz in #400
New Contributors
- @ManuelWalz made their first contribution in #400
Full Changelog: 0.12.2...0.12.3
0.12.2
Features
- Add TUnit Support by @MeikelLP in #390
- Add ImplementAnyInterfaces Fluent Syntax by @alexanderlinne in #396
- Handle UnavailableType when creating an Attribute by @alexanderlinne in #408
Enhancements
- Add Tests For Object Predicates by @alexanderlinne in #393
Dependency Updates
- chore(deps): update actions/checkout action to v5 by @renovate[bot] in #391
- chore(deps): update dependency dotnet-sdk to v9.0.304 by @renovate[bot] in #354
- chore(deps): update dependency microsoft.net.test.sdk to v17 by @renovate[bot] in #349
- chore(deps): update dependency verify.xunit to v30 by @renovate[bot] in #368
- chore(deps): update dependency jetbrains.annotations to v2025 by @renovate[bot] in #386
New Contributors
Full Changelog: 0.12.1...0.12.2
0.12.1
Fixes
- ResideInNamespaceMatching and ResideInAssemblyMatching incorrectly forward call by @tnotheis in #379
New Contributors
Full Changelog: 0.12.0...0.12.1
0.12.0
Breaking Changes
Marking soon to be removed methods in the fluent api as obsolete by @brandhuf in #362
Until now, ArchUnitNET provided overloads of functions in the fluent syntax that took a string as an argument like Types().That().DependOnAny("ExampleClass") or Types().That().DependOnAny(".*ExampleClass", true). Here, however, it is unclear whether the string would match the Name, FullName or AssemblyQualifiedName. These functions have now been marked as obsolete and will be removed in version 0.13.0.
Besides HaveName, the fluent interface now also provides the functions HaveNameMatching, HaveFullName and HaveFullNameMatching. The above call can therefore be replaced with Types().That().DependOnAny(Types().That().HaveName("ExampleClass")) or Types().That().DependOnAny(Types().That().HaveFullNameMatching(".*ExampleClass")), giving a clear indication of what is matched and how it is matched.
Don't Set Assembly Name To It's Full Name by @alexanderlinne in #372
This is a bug where the Name of an assembly was always set to its FullName. This may be a breaking change for code that currently relies on this behaviour.
Fixes
- Fix Check in AreNotReadOnly Predicate by @alexanderlinne in #373
Enhancements
- Reduce Code Duplication in Fluent Syntax Object Conditions by @alexanderlinne in #367
Dependency Updates
Full Changelog: 0.11.4...0.12.0