From c87381f4fc93601f356d81c3c974cbb0f2fccaf6 Mon Sep 17 00:00:00 2001 From: Ahmed Mohamed El Ahmar Date: Sat, 6 Sep 2025 23:10:58 +0100 Subject: [PATCH 1/3] feat: Add HavePrivateParameterlessConstructor and NotHavePrivateParameterlessConstructor conditions Add support for checking if classes have private parameterless constructors, which is essential for enforcing Domain-Driven Design patterns and ORM requirements. Signed-off-by: Ahmed Mohamed El Ahmar # Conflicts: # ArchUnitNETTests/ArchUnitNETTests.csproj --- .../Classes/ClassConditionsDefinition.cs | 21 ++++++ .../Elements/Types/Classes/ClassesShould.cs | 12 +++ .../ClassPrivateConstructorConditionTests.cs | 73 +++++++++++++++++++ .../Entities/PrivateConstructorTestClasses.cs | 56 ++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 ArchUnitNETTests/Fluent/Syntax/Elements/ClassPrivateConstructorConditionTests.cs create mode 100644 TestAssembly/Domain/Entities/PrivateConstructorTestClasses.cs diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassConditionsDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassConditionsDefinition.cs index 5fd8b88ed..db1bc89fe 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassConditionsDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassConditionsDefinition.cs @@ -1,5 +1,6 @@ using System.Linq; using ArchUnitNET.Domain; +using ArchUnitNET.Domain.Extensions; using ArchUnitNET.Fluent.Conditions; namespace ArchUnitNET.Fluent.Syntax.Elements.Types.Classes @@ -43,6 +44,16 @@ public static ICondition BeImmutable() "is not immutable" ); } + + public static ICondition HavePrivateParameterlessConstructor() + { + return new SimpleCondition( + cls => (cls.IsAbstract.HasValue && cls.IsAbstract.Value) || cls.GetConstructors().Any(c => + c.Visibility == Visibility.Private && !c.Parameters.Any()), + "have private parameterless constructor", + "does not have private parameterless constructor" + ); + } //Negations @@ -81,5 +92,15 @@ public static ICondition NotBeImmutable() "is immutable" ); } + + public static ICondition NotHavePrivateParameterlessConstructor() + { + return new SimpleCondition( + cls => (cls.IsAbstract.HasValue && cls.IsAbstract.Value) || !cls.GetConstructors().Any(c => + c.Visibility == Visibility.Private && !c.Parameters.Any()), + "not have private parameterless constructor", + "has private parameterless constructor" + ); + } } } diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassesShould.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassesShould.cs index 2788f9597..ef89d247f 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassesShould.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassesShould.cs @@ -33,6 +33,12 @@ public ClassesShouldConjunction BeImmutable() return new ClassesShouldConjunction(_ruleCreator); } + public ClassesShouldConjunction HavePrivateParameterlessConstructor() + { + _ruleCreator.AddCondition(ClassConditionsDefinition.HavePrivateParameterlessConstructor()); + return new ClassesShouldConjunction(_ruleCreator); + } + //Negations public ClassesShouldConjunction NotBeAbstract() @@ -58,5 +64,11 @@ public ClassesShouldConjunction NotBeImmutable() _ruleCreator.AddCondition(ClassConditionsDefinition.NotBeImmutable()); return new ClassesShouldConjunction(_ruleCreator); } + + public ClassesShouldConjunction NotHavePrivateParameterlessConstructor() + { + _ruleCreator.AddCondition(ClassConditionsDefinition.NotHavePrivateParameterlessConstructor()); + return new ClassesShouldConjunction(_ruleCreator); + } } } diff --git a/ArchUnitNETTests/Fluent/Syntax/Elements/ClassPrivateConstructorConditionTests.cs b/ArchUnitNETTests/Fluent/Syntax/Elements/ClassPrivateConstructorConditionTests.cs new file mode 100644 index 000000000..7c6986010 --- /dev/null +++ b/ArchUnitNETTests/Fluent/Syntax/Elements/ClassPrivateConstructorConditionTests.cs @@ -0,0 +1,73 @@ +using ArchUnitNET.Domain; +using ArchUnitNET.Loader; +using TestAssembly.Domain.Entities; +using Xunit; +using static ArchUnitNET.Fluent.ArchRuleDefinition; + +namespace ArchUnitNETTests.Fluent.Syntax.Elements; + +public class ClassPrivateConstructorConditionTests +{ + private static readonly Architecture Architecture = + new ArchLoader().LoadAssembly(typeof(ClassWithPrivateParameterlessConstructor).Assembly).Build(); + + [Fact] + public void HavePrivateParameterlessConstructor_ClassWithPrivateParameterlessConstructor_DoesNotViolate() + { + var rule = Classes() + .That().HaveName(nameof(ClassWithPrivateParameterlessConstructor)) + .Should().HavePrivateParameterlessConstructor(); + + Assert.True(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void HavePrivateParameterlessConstructor_ClassWithoutPrivateParameterlessConstructor_Violates() + { + var rule = Classes() + .That().HaveName(nameof(ClassWithoutPrivateParameterlessConstructor)) + .Should().HavePrivateParameterlessConstructor(); + + Assert.False(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void NotHavePrivateParameterlessConstructor_ClassWithoutPrivateParameterlessConstructor_DoesNotViolate() + { + var rule = Classes() + .That().HaveName(nameof(ClassWithoutPrivateParameterlessConstructor)) + .Should().NotHavePrivateParameterlessConstructor(); + + Assert.True(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void NotHavePrivateParameterlessConstructor_ClassWithPrivateParameterlessConstructor_Violates() + { + var rule = Classes() + .That().HaveName(nameof(ClassWithPrivateParameterlessConstructor)) + .Should().NotHavePrivateParameterlessConstructor(); + + Assert.False(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void HavePrivateParameterlessConstructor_AbstractClass_DoesNotViolate() + { + var rule = Classes() + .That().AreAbstract() + .Should().HavePrivateParameterlessConstructor(); + + Assert.True(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void HavePrivateParameterlessConstructor_ClassWithOnlyParameterizedConstructors_Violates() + { + var rule = Classes() + .That().HaveName(nameof(ClassWithOnlyParameterizedConstructors)) + .Should().HavePrivateParameterlessConstructor(); + + Assert.False(rule.HasNoViolations(Architecture)); + } +} \ No newline at end of file diff --git a/TestAssembly/Domain/Entities/PrivateConstructorTestClasses.cs b/TestAssembly/Domain/Entities/PrivateConstructorTestClasses.cs new file mode 100644 index 000000000..983b2a440 --- /dev/null +++ b/TestAssembly/Domain/Entities/PrivateConstructorTestClasses.cs @@ -0,0 +1,56 @@ +namespace TestAssembly.Domain.Entities; + +public class ClassWithPrivateParameterlessConstructor +{ + private ClassWithPrivateParameterlessConstructor() + { + // Private parameterless constructor for ORM + } + + public ClassWithPrivateParameterlessConstructor(string name) + { + Name = name; + } + + public string Name { get; private set; } +} + +public class ClassWithoutPrivateParameterlessConstructor +{ + public ClassWithoutPrivateParameterlessConstructor() + { + // Public parameterless constructor + } + + public ClassWithoutPrivateParameterlessConstructor(string name) + { + Name = name; + } + + public string Name { get; private set; } +} + +public class ClassWithOnlyParameterizedConstructors +{ + public ClassWithOnlyParameterizedConstructors(string name) + { + Name = name; + } + + public ClassWithOnlyParameterizedConstructors(int id, string name) + { + Id = id; + Name = name; + } + + public int Id { get; private set; } + public string Name { get; private set; } +} + +public abstract class AbstractClassBase +{ + protected AbstractClassBase() + { + // Abstract classes should be excluded from checks + } +} \ No newline at end of file From 64473483e2d31ae51f8296c83dc3ea3ab76b5451 Mon Sep 17 00:00:00 2001 From: Ahmed Mohamed El Ahmar Date: Tue, 16 Sep 2025 21:52:08 +0100 Subject: [PATCH 2/3] Add HaveAnyParameters and NotHaveAnyParameters conditions for MethodMembers - Add HaveAnyParameters() condition to check if methods have parameters - Add NotHaveAnyParameters() condition to check if methods have no parameters - Add corresponding methods to IMethodMemberConditions interface - Add comprehensive test coverage for both conditions - Test both regular methods and constructors - Verify failure descriptions in violation cases - Use correct IL method names (.ctor) for constructor tests - Remove redundant test cases that provided no additional value The new conditions enable architectural rules to enforce parameter requirements on methods and constructors, complementing existing method member conditions. Signed-off-by: Ahmed Mohamed El Ahmar --- .../MethodMembers/IMethodMemberConditions.cs | 2 + .../MethodMemberConditionsDefinition.cs | 228 ++++++------------ .../MethodMembers/MethodMembersShould.cs | 134 +++------- .../Classes/ClassConditionsDefinition.cs | 21 -- .../Elements/Types/Classes/ClassesShould.cs | 12 - .../ClassPrivateConstructorConditionTests.cs | 73 ------ .../Elements/MethodParameterConditionTests.cs | 185 ++++++++++++++ .../Entities/PrivateConstructorTestClasses.cs | 56 ----- .../Methods/MethodParameterTestClass.cs | 61 +++++ 9 files changed, 365 insertions(+), 407 deletions(-) delete mode 100644 ArchUnitNETTests/Fluent/Syntax/Elements/ClassPrivateConstructorConditionTests.cs create mode 100644 ArchUnitNETTests/Fluent/Syntax/Elements/MethodParameterConditionTests.cs delete mode 100644 TestAssembly/Domain/Entities/PrivateConstructorTestClasses.cs create mode 100644 TestAssembly/Domain/Methods/MethodParameterTestClass.cs diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberConditions.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberConditions.cs index c95b97342..014626cbe 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberConditions.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberConditions.cs @@ -28,11 +28,13 @@ public interface IMethodMemberConditions TReturnType HaveReturnType(IObjectProvider types); TReturnType HaveReturnType(Type type, params Type[] moreTypes); TReturnType HaveReturnType(IEnumerable types); + TReturnType HaveAnyParameters(); //Negations TReturnType BeNoConstructor(); TReturnType NotBeVirtual(); + TReturnType NotHaveAnyParameters(); TReturnType NotBeCalledBy(IType firstType, params IType[] moreTypes); TReturnType NotBeCalledBy(Type type, params Type[] moreTypes); diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs index 096b92a7a..04d3602a5 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs @@ -30,11 +30,7 @@ public static ICondition BeConstructor() public static ICondition BeVirtual() { - return new SimpleCondition( - member => member.IsVirtual, - "be virtual", - "is not virtual" - ); + return new SimpleCondition(member => member.IsVirtual, "be virtual", "is not virtual"); } public static ICondition BeCalledBy(IType firstType, params IType[] moreTypes) @@ -53,10 +49,7 @@ public static ICondition BeCalledBy(Type firstType, params Type[] public static ICondition BeCalledBy(IObjectProvider objectProvider) { - IEnumerable Condition( - IEnumerable methodMembers, - Architecture architecture - ) + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) { var typeList = objectProvider.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); @@ -141,10 +134,7 @@ public static ICondition BeCalledBy(IEnumerable types) var typeList = types.ToList(); var firstType = typeList.First(); - IEnumerable Condition( - IEnumerable methodMembers, - Architecture architecture - ) + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) { var archUnitTypeList = new List(); foreach (var type in typeList) @@ -159,11 +149,10 @@ Architecture architecture //ignore, can't have a dependency anyways } } + var methodMemberList = methodMembers.ToList(); var passedObjects = methodMemberList - .Where(methodMember => - methodMember.GetCallingTypes().Intersect(archUnitTypeList).Any() - ) + .Where(methodMember => methodMember.GetCallingTypes().Intersect(archUnitTypeList).Any()) .ToList(); string failDescription; if (typeList.IsNullOrEmpty()) @@ -211,34 +200,23 @@ Architecture architecture return new ArchitectureCondition(Condition, description); } - public static ICondition HaveDependencyInMethodBodyTo( - IType firstType, - params IType[] moreTypes - ) + public static ICondition HaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) { var types = new List { firstType }; types.AddRange(moreTypes); return HaveDependencyInMethodBodyTo(types); } - public static ICondition HaveDependencyInMethodBodyTo( - Type firstType, - params Type[] moreTypes - ) + public static ICondition HaveDependencyInMethodBodyTo(Type firstType, params Type[] moreTypes) { var types = new List { firstType }; types.AddRange(moreTypes); return HaveDependencyInMethodBodyTo(types); } - public static ICondition HaveDependencyInMethodBodyTo( - IObjectProvider objectProvider - ) + public static ICondition HaveDependencyInMethodBodyTo(IObjectProvider objectProvider) { - IEnumerable Condition( - IEnumerable methodMembers, - Architecture architecture - ) + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) { var typeList = objectProvider.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); @@ -251,8 +229,7 @@ Architecture architecture .Any() ) .ToList(); - var failDescription = - "does not have dependencies in method body to " + objectProvider.Description; + var failDescription = "does not have dependencies in method body to " + objectProvider.Description; foreach (var failedObject in methodMemberList.Except(passedObjects)) { yield return new ConditionResult(failedObject, false, failDescription); @@ -268,9 +245,7 @@ Architecture architecture return new ArchitectureCondition(Condition, description); } - public static ICondition HaveDependencyInMethodBodyTo( - IEnumerable types - ) + public static ICondition HaveDependencyInMethodBodyTo(IEnumerable types) { var typeList = types.ToList(); var firstType = typeList.First(); @@ -290,8 +265,7 @@ IEnumerable Condition(IEnumerable methodMembers) string failDescription; if (typeList.IsNullOrEmpty()) { - failDescription = - "does not have dependencies in method body to one of no types (always true)"; + failDescription = "does not have dependencies in method body to one of no types (always true)"; } else { @@ -299,9 +273,7 @@ IEnumerable Condition(IEnumerable methodMembers) .Where(type => !type.Equals(firstType)) .Distinct() .Aggregate( - "does not have dependencies in method body to \"" - + firstType.FullName - + "\"", + "does not have dependencies in method body to \"" + firstType.FullName + "\"", (current, type) => current + " or \"" + type.FullName + "\"" ); } @@ -341,10 +313,7 @@ public static ICondition HaveDependencyInMethodBodyTo(IEnumerable< var typeList = types.ToList(); var firstType = typeList.First(); - IEnumerable Condition( - IEnumerable methodMembers, - Architecture architecture - ) + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) { var archUnitTypeList = new List(); foreach (var type in typeList) @@ -359,6 +328,7 @@ Architecture architecture //ignore, can't have a dependency anyways } } + var methodMemberList = methodMembers.ToList(); var passedObjects = methodMemberList .Where(methodMember => @@ -372,8 +342,7 @@ Architecture architecture string failDescription; if (typeList.IsNullOrEmpty()) { - failDescription = - "does not have dependencies in method body to one of no types (always true)"; + failDescription = "does not have dependencies in method body to one of no types (always true)"; } else { @@ -381,9 +350,7 @@ Architecture architecture .Where(type => type != firstType) .Distinct() .Aggregate( - "does not have dependencies in method body to \"" - + firstType.FullName - + "\"", + "does not have dependencies in method body to \"" + firstType.FullName + "\"", (current, type) => current + " or \"" + type.FullName + "\"" ); } @@ -418,10 +385,7 @@ Architecture architecture return new ArchitectureCondition(Condition, description); } - public static ICondition HaveReturnType( - IType firstType, - params IType[] moreTypes - ) + public static ICondition HaveReturnType(IType firstType, params IType[] moreTypes) { var types = new List { firstType }; types.AddRange(moreTypes); @@ -432,8 +396,7 @@ public static ICondition HaveReturnType(IEnumerable types) { var typeList = types.ToList(); var typeStringList = typeList.Select(type => type.FullName).ToList(); - var description = - "have return type \"" + string.Join("\" or \"", typeStringList) + "\""; + var description = "have return type \"" + string.Join("\" or \"", typeStringList) + "\""; bool Condition(MethodMember member) { @@ -449,17 +412,12 @@ bool Condition(MethodMember member) public static ICondition HaveReturnType(IObjectProvider types) { - IEnumerable Condition( - IEnumerable methodMembers, - Architecture architecture - ) + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) { var typeList = types.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); var passedObjects = methodMemberList - .Where(methodMember => - typeList.Any(type => methodMember.ReturnType.FullNameEquals(type.FullName)) - ) + .Where(methodMember => typeList.Any(type => methodMember.ReturnType.FullNameEquals(type.FullName))) .ToList(); foreach (var failedObject in methodMemberList.Except(passedObjects)) { @@ -480,10 +438,7 @@ Architecture architecture return new ArchitectureCondition(Condition, description); } - public static ICondition HaveReturnType( - Type firstType, - params Type[] moreTypes - ) + public static ICondition HaveReturnType(Type firstType, params Type[] moreTypes) { var types = new List { firstType }; types.AddRange(moreTypes); @@ -494,8 +449,7 @@ public static ICondition HaveReturnType(IEnumerable types) { var typeList = types.ToList(); var typeStringList = typeList.Select(type => type.ToString()).ToList(); - var description = - "have return type \"" + string.Join("\" or \"", typeStringList) + "\""; + var description = "have return type \"" + string.Join("\" or \"", typeStringList) + "\""; bool Condition(MethodMember member) { @@ -522,27 +476,17 @@ public static ICondition BeNoConstructor() public static ICondition NotBeVirtual() { - return new SimpleCondition( - member => !member.IsVirtual, - "not be virtual", - "is virtual" - ); + return new SimpleCondition(member => !member.IsVirtual, "not be virtual", "is virtual"); } - public static ICondition NotBeCalledBy( - IType firstType, - params IType[] moreTypes - ) + public static ICondition NotBeCalledBy(IType firstType, params IType[] moreTypes) { var types = new List { firstType }; types.AddRange(moreTypes); return NotBeCalledBy(types); } - public static ICondition NotBeCalledBy( - Type firstType, - params Type[] moreTypes - ) + public static ICondition NotBeCalledBy(Type firstType, params Type[] moreTypes) { var types = new List { firstType }; types.AddRange(moreTypes); @@ -551,10 +495,7 @@ params Type[] moreTypes public static ICondition NotBeCalledBy(IObjectProvider objectProvider) { - IEnumerable Condition( - IEnumerable methodMembers, - Architecture architecture - ) + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) { var typeList = objectProvider.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); @@ -639,10 +580,7 @@ public static ICondition NotBeCalledBy(IEnumerable types) var typeList = types.ToList(); var firstType = typeList.First(); - IEnumerable Condition( - IEnumerable methodMembers, - Architecture architecture - ) + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) { var archUnitTypeList = new List(); foreach (var type in typeList) @@ -657,11 +595,10 @@ Architecture architecture //ignore, can't have a dependency anyways } } + var methodMemberList = methodMembers.ToList(); var failedObjects = methodMemberList - .Where(methodMember => - methodMember.GetCallingTypes().Intersect(archUnitTypeList).Any() - ) + .Where(methodMember => methodMember.GetCallingTypes().Intersect(archUnitTypeList).Any()) .ToList(); string failDescription; if (typeList.IsNullOrEmpty()) @@ -719,24 +656,16 @@ params IType[] moreTypes return NotHaveDependencyInMethodBodyTo(types); } - public static ICondition NotHaveDependencyInMethodBodyTo( - Type firstType, - params Type[] moreTypes - ) + public static ICondition NotHaveDependencyInMethodBodyTo(Type firstType, params Type[] moreTypes) { var types = new List { firstType }; types.AddRange(moreTypes); return NotHaveDependencyInMethodBodyTo(types); } - public static ICondition NotHaveDependencyInMethodBodyTo( - IObjectProvider objectProvider - ) + public static ICondition NotHaveDependencyInMethodBodyTo(IObjectProvider objectProvider) { - IEnumerable Condition( - IEnumerable methodMembers, - Architecture architecture - ) + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) { var typeList = objectProvider.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); @@ -749,8 +678,7 @@ Architecture architecture .Any() ) .ToList(); - var failDescription = - "does have dependencies in method body to " + objectProvider.Description; + var failDescription = "does have dependencies in method body to " + objectProvider.Description; foreach (var failedObject in failedObjects) { yield return new ConditionResult(failedObject, false, failDescription); @@ -762,14 +690,11 @@ Architecture architecture } } - var description = - "not have dependencies in method body to " + objectProvider.Description; + var description = "not have dependencies in method body to " + objectProvider.Description; return new ArchitectureCondition(Condition, description); } - public static ICondition NotHaveDependencyInMethodBodyTo( - IEnumerable types - ) + public static ICondition NotHaveDependencyInMethodBodyTo(IEnumerable types) { var typeList = types.ToList(); var firstType = typeList.First(); @@ -789,8 +714,7 @@ IEnumerable Condition(IEnumerable methodMembers) string failDescription; if (typeList.IsNullOrEmpty()) { - failDescription = - "does have dependencies in method body to one of no types (always false)"; + failDescription = "does have dependencies in method body to one of no types (always false)"; } else { @@ -798,9 +722,7 @@ IEnumerable Condition(IEnumerable methodMembers) .Where(type => !Equals(type, firstType)) .Distinct() .Aggregate( - "does have dependencies in method body to \"" - + firstType.FullName - + "\"", + "does have dependencies in method body to \"" + firstType.FullName + "\"", (current, type) => current + " or \"" + type.FullName + "\"" ); } @@ -819,8 +741,7 @@ IEnumerable Condition(IEnumerable methodMembers) string description; if (typeList.IsNullOrEmpty()) { - description = - "not have dependencies in method body to one of no types (always true)"; + description = "not have dependencies in method body to one of no types (always true)"; } else { @@ -836,17 +757,12 @@ IEnumerable Condition(IEnumerable methodMembers) return new EnumerableCondition(Condition, description); } - public static ICondition NotHaveDependencyInMethodBodyTo( - IEnumerable types - ) + public static ICondition NotHaveDependencyInMethodBodyTo(IEnumerable types) { var typeList = types.ToList(); var firstType = typeList.First(); - IEnumerable Condition( - IEnumerable methodMembers, - Architecture architecture - ) + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) { var archUnitTypeList = new List(); foreach (var type in typeList) @@ -861,6 +777,7 @@ Architecture architecture //ignore, can't have a dependency anyways } } + var methodMemberList = methodMembers.ToList(); var failedObjects = methodMemberList .Where(methodMember => @@ -874,8 +791,7 @@ Architecture architecture string failDescription; if (typeList.IsNullOrEmpty()) { - failDescription = - "does have dependencies in method body to one of no types (always false)"; + failDescription = "does have dependencies in method body to one of no types (always false)"; } else { @@ -883,9 +799,7 @@ Architecture architecture .Where(type => type != firstType) .Distinct() .Aggregate( - "does have dependencies in method body to \"" - + firstType.FullName - + "\"", + "does have dependencies in method body to \"" + firstType.FullName + "\"", (current, type) => current + " or \"" + type.FullName + "\"" ); } @@ -904,8 +818,7 @@ Architecture architecture string description; if (typeList.IsNullOrEmpty()) { - description = - "not have dependencies in method body to one of no types (always true)"; + description = "not have dependencies in method body to one of no types (always true)"; } else { @@ -921,10 +834,7 @@ Architecture architecture return new ArchitectureCondition(Condition, description); } - public static ICondition NotHaveReturnType( - IType firstType, - params IType[] moreTypes - ) + public static ICondition NotHaveReturnType(IType firstType, params IType[] moreTypes) { var types = new List { firstType }; types.AddRange(moreTypes); @@ -935,8 +845,7 @@ public static ICondition NotHaveReturnType(IEnumerable type { var typeList = types.ToList(); var typeStringList = typeList.Select(type => type.FullName).ToList(); - var description = - "not have return type \"" + string.Join("\" or \"", typeStringList) + "\""; + var description = "not have return type \"" + string.Join("\" or \"", typeStringList) + "\""; bool Condition(MethodMember member) { @@ -952,17 +861,12 @@ bool Condition(MethodMember member) public static ICondition NotHaveReturnType(IObjectProvider types) { - IEnumerable Condition( - IEnumerable methodMembers, - Architecture architecture - ) + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) { var typeList = types.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); var passedObjects = methodMemberList - .Where(methodMember => - typeList.All(type => !methodMember.ReturnType.FullNameEquals(type.FullName)) - ) + .Where(methodMember => typeList.All(type => !methodMember.ReturnType.FullNameEquals(type.FullName))) .ToList(); foreach (var failedObject in methodMemberList.Except(passedObjects)) { @@ -983,10 +887,7 @@ Architecture architecture return new ArchitectureCondition(Condition, description); } - public static ICondition NotHaveReturnType( - Type firstType, - params Type[] moreTypes - ) + public static ICondition NotHaveReturnType(Type firstType, params Type[] moreTypes) { var types = new List { firstType }; types.AddRange(moreTypes); @@ -997,8 +898,7 @@ public static ICondition NotHaveReturnType(IEnumerable types { var typeList = types.ToList(); var typeStringList = typeList.Select(type => type.ToString()).ToList(); - var description = - "not have return type \"" + string.Join("\" or \"", typeStringList) + "\""; + var description = "not have return type \"" + string.Join("\" or \"", typeStringList) + "\""; bool Condition(MethodMember member) { @@ -1011,5 +911,31 @@ bool Condition(MethodMember member) description ); } + + /// + /// Selects method members that have any parameters + /// + /// A condition that can be applied to method members + public static ICondition HaveAnyParameters() + { + return new SimpleCondition( + method => method.Parameters.Any(), + "have any parameters", + "does not have any parameters" + ); + } + + /// + /// Selects method members that do not have any parameters (parameterless) + /// + /// A condition that can be applied to method members + public static ICondition NotHaveAnyParameters() + { + return new SimpleCondition( + method => !method.Parameters.Any(), + "not have any parameters", + "has parameters" + ); + } } } diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs index 30e0b3ef0..2ead07fa9 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs @@ -11,19 +11,13 @@ public class MethodMembersShould public MethodMembersShould(IArchRuleCreator ruleCreator) : base(ruleCreator) { } - public ShouldRelateToMethodMembersThat< - MethodMembersShouldConjunction, - MethodMember - > BeMethodMembersThat() + public ShouldRelateToMethodMembersThat BeMethodMembersThat() { _ruleCreator.BeginComplexCondition( ArchRuleDefinition.MethodMembers(), MethodMemberConditionsDefinition.BeMethodMembersThat() ); - return new ShouldRelateToMethodMembersThat< - MethodMembersShouldConjunction, - MethodMember - >(_ruleCreator); + return new ShouldRelateToMethodMembersThat(_ruleCreator); } public MethodMembersShouldConjunction BeConstructor() @@ -40,9 +34,7 @@ public MethodMembersShouldConjunction BeVirtual() public MethodMembersShouldConjunction BeCalledBy(IType firstType, params IType[] moreTypes) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.BeCalledBy(firstType, moreTypes) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.BeCalledBy(firstType, moreTypes)); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -70,10 +62,7 @@ public MethodMembersShouldConjunction BeCalledBy(IEnumerable types) return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo( - IType firstType, - params IType[] moreTypes - ) + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) { _ruleCreator.AddCondition( MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(firstType, moreTypes) @@ -81,51 +70,33 @@ params IType[] moreTypes return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo( - Type type, - params Type[] moreTypes - ) + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(type, moreTypes) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(type, moreTypes)); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo( - IObjectProvider types - ) + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IObjectProvider types) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types)); return new MethodMembersShouldConjunction(_ruleCreator); } public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IEnumerable types) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types)); return new MethodMembersShouldConjunction(_ruleCreator); } public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IEnumerable types) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types)); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction HaveReturnType( - IType firstType, - params IType[] moreTypes - ) + public MethodMembersShouldConjunction HaveReturnType(IType firstType, params IType[] moreTypes) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.HaveReturnType(firstType, moreTypes) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveReturnType(firstType, moreTypes)); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -143,9 +114,7 @@ public MethodMembersShouldConjunction HaveReturnType(IObjectProvider type public MethodMembersShouldConjunction HaveReturnType(Type type, params Type[] moreTypes) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.HaveReturnType(type, moreTypes) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveReturnType(type, moreTypes)); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -169,22 +138,15 @@ public MethodMembersShouldConjunction NotBeVirtual() return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotBeCalledBy( - IType firstType, - params IType[] moreTypes - ) + public MethodMembersShouldConjunction NotBeCalledBy(IType firstType, params IType[] moreTypes) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.NotBeCalledBy(firstType, moreTypes) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotBeCalledBy(firstType, moreTypes)); return new MethodMembersShouldConjunction(_ruleCreator); } public MethodMembersShouldConjunction NotBeCalledBy(Type type, params Type[] moreTypes) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.NotBeCalledBy(type, moreTypes) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotBeCalledBy(type, moreTypes)); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -206,24 +168,15 @@ public MethodMembersShouldConjunction NotBeCalledBy(IEnumerable types) return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo( - IType firstType, - params IType[] moreTypes - ) + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) { _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo( - firstType, - moreTypes - ) + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(firstType, moreTypes) ); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo( - Type type, - params Type[] moreTypes - ) + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes) { _ruleCreator.AddCondition( MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(type, moreTypes) @@ -231,44 +184,27 @@ params Type[] moreTypes return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo( - IObjectProvider types - ) + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IObjectProvider types) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types)); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo( - IEnumerable types - ) + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IEnumerable types) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types)); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo( - IEnumerable types - ) + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IEnumerable types) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types)); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveReturnType( - IType firstType, - params IType[] moreTypes - ) + public MethodMembersShouldConjunction NotHaveReturnType(IType firstType, params IType[] moreTypes) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.NotHaveReturnType(firstType, moreTypes) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveReturnType(firstType, moreTypes)); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -286,9 +222,7 @@ public MethodMembersShouldConjunction NotHaveReturnType(IObjectProvider t public MethodMembersShouldConjunction NotHaveReturnType(Type type, params Type[] moreTypes) { - _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.NotHaveReturnType(type, moreTypes) - ); + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveReturnType(type, moreTypes)); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -297,5 +231,17 @@ public MethodMembersShouldConjunction NotHaveReturnType(IEnumerable types) _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveReturnType(types)); return new MethodMembersShouldConjunction(_ruleCreator); } + + public MethodMembersShouldConjunction HaveAnyParameters() + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveAnyParameters()); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction NotHaveAnyParameters() + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveAnyParameters()); + return new MethodMembersShouldConjunction(_ruleCreator); + } } } diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassConditionsDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassConditionsDefinition.cs index db1bc89fe..5fd8b88ed 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassConditionsDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassConditionsDefinition.cs @@ -1,6 +1,5 @@ using System.Linq; using ArchUnitNET.Domain; -using ArchUnitNET.Domain.Extensions; using ArchUnitNET.Fluent.Conditions; namespace ArchUnitNET.Fluent.Syntax.Elements.Types.Classes @@ -44,16 +43,6 @@ public static ICondition BeImmutable() "is not immutable" ); } - - public static ICondition HavePrivateParameterlessConstructor() - { - return new SimpleCondition( - cls => (cls.IsAbstract.HasValue && cls.IsAbstract.Value) || cls.GetConstructors().Any(c => - c.Visibility == Visibility.Private && !c.Parameters.Any()), - "have private parameterless constructor", - "does not have private parameterless constructor" - ); - } //Negations @@ -92,15 +81,5 @@ public static ICondition NotBeImmutable() "is immutable" ); } - - public static ICondition NotHavePrivateParameterlessConstructor() - { - return new SimpleCondition( - cls => (cls.IsAbstract.HasValue && cls.IsAbstract.Value) || !cls.GetConstructors().Any(c => - c.Visibility == Visibility.Private && !c.Parameters.Any()), - "not have private parameterless constructor", - "has private parameterless constructor" - ); - } } } diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassesShould.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassesShould.cs index ef89d247f..2788f9597 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassesShould.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassesShould.cs @@ -33,12 +33,6 @@ public ClassesShouldConjunction BeImmutable() return new ClassesShouldConjunction(_ruleCreator); } - public ClassesShouldConjunction HavePrivateParameterlessConstructor() - { - _ruleCreator.AddCondition(ClassConditionsDefinition.HavePrivateParameterlessConstructor()); - return new ClassesShouldConjunction(_ruleCreator); - } - //Negations public ClassesShouldConjunction NotBeAbstract() @@ -64,11 +58,5 @@ public ClassesShouldConjunction NotBeImmutable() _ruleCreator.AddCondition(ClassConditionsDefinition.NotBeImmutable()); return new ClassesShouldConjunction(_ruleCreator); } - - public ClassesShouldConjunction NotHavePrivateParameterlessConstructor() - { - _ruleCreator.AddCondition(ClassConditionsDefinition.NotHavePrivateParameterlessConstructor()); - return new ClassesShouldConjunction(_ruleCreator); - } } } diff --git a/ArchUnitNETTests/Fluent/Syntax/Elements/ClassPrivateConstructorConditionTests.cs b/ArchUnitNETTests/Fluent/Syntax/Elements/ClassPrivateConstructorConditionTests.cs deleted file mode 100644 index 7c6986010..000000000 --- a/ArchUnitNETTests/Fluent/Syntax/Elements/ClassPrivateConstructorConditionTests.cs +++ /dev/null @@ -1,73 +0,0 @@ -using ArchUnitNET.Domain; -using ArchUnitNET.Loader; -using TestAssembly.Domain.Entities; -using Xunit; -using static ArchUnitNET.Fluent.ArchRuleDefinition; - -namespace ArchUnitNETTests.Fluent.Syntax.Elements; - -public class ClassPrivateConstructorConditionTests -{ - private static readonly Architecture Architecture = - new ArchLoader().LoadAssembly(typeof(ClassWithPrivateParameterlessConstructor).Assembly).Build(); - - [Fact] - public void HavePrivateParameterlessConstructor_ClassWithPrivateParameterlessConstructor_DoesNotViolate() - { - var rule = Classes() - .That().HaveName(nameof(ClassWithPrivateParameterlessConstructor)) - .Should().HavePrivateParameterlessConstructor(); - - Assert.True(rule.HasNoViolations(Architecture)); - } - - [Fact] - public void HavePrivateParameterlessConstructor_ClassWithoutPrivateParameterlessConstructor_Violates() - { - var rule = Classes() - .That().HaveName(nameof(ClassWithoutPrivateParameterlessConstructor)) - .Should().HavePrivateParameterlessConstructor(); - - Assert.False(rule.HasNoViolations(Architecture)); - } - - [Fact] - public void NotHavePrivateParameterlessConstructor_ClassWithoutPrivateParameterlessConstructor_DoesNotViolate() - { - var rule = Classes() - .That().HaveName(nameof(ClassWithoutPrivateParameterlessConstructor)) - .Should().NotHavePrivateParameterlessConstructor(); - - Assert.True(rule.HasNoViolations(Architecture)); - } - - [Fact] - public void NotHavePrivateParameterlessConstructor_ClassWithPrivateParameterlessConstructor_Violates() - { - var rule = Classes() - .That().HaveName(nameof(ClassWithPrivateParameterlessConstructor)) - .Should().NotHavePrivateParameterlessConstructor(); - - Assert.False(rule.HasNoViolations(Architecture)); - } - - [Fact] - public void HavePrivateParameterlessConstructor_AbstractClass_DoesNotViolate() - { - var rule = Classes() - .That().AreAbstract() - .Should().HavePrivateParameterlessConstructor(); - - Assert.True(rule.HasNoViolations(Architecture)); - } - - [Fact] - public void HavePrivateParameterlessConstructor_ClassWithOnlyParameterizedConstructors_Violates() - { - var rule = Classes() - .That().HaveName(nameof(ClassWithOnlyParameterizedConstructors)) - .Should().HavePrivateParameterlessConstructor(); - - Assert.False(rule.HasNoViolations(Architecture)); - } -} \ No newline at end of file diff --git a/ArchUnitNETTests/Fluent/Syntax/Elements/MethodParameterConditionTests.cs b/ArchUnitNETTests/Fluent/Syntax/Elements/MethodParameterConditionTests.cs new file mode 100644 index 000000000..b47996944 --- /dev/null +++ b/ArchUnitNETTests/Fluent/Syntax/Elements/MethodParameterConditionTests.cs @@ -0,0 +1,185 @@ +using System.Linq; +using ArchUnitNET.Domain; +using ArchUnitNET.Loader; +using TestAssembly.Domain.Methods; +using Xunit; +using static ArchUnitNET.Fluent.ArchRuleDefinition; + +namespace ArchUnitNETTests.Fluent.Syntax.Elements; + +public class MethodParameterConditionTests +{ + private static readonly Architecture Architecture = new ArchLoader() + .LoadAssembly(typeof(ClassWithPrivateParameterlessConstructor).Assembly) + .Build(); + + [Fact] + public void HaveAnyParameters_MethodWithParameters_DoesNotViolate() + { + var rule = MethodMembers() + .That() + .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithMethods))) + .And() + .HaveName("MethodWithParameters(System.String,System.Int32)") + .Should() + .HaveAnyParameters(); + + Assert.True(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void HaveAnyParameters_MethodWithoutParameters_Violates() + { + var rule = MethodMembers() + .That() + .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithMethods))) + .And() + .HaveName("MethodWithoutParameters()") + .Should() + .HaveAnyParameters(); + + Assert.False(rule.HasNoViolations(Architecture)); + + var evaluation = rule.Evaluate(Architecture); + var violations = evaluation.ToList(); + Assert.Single(violations); + Assert.Contains("does not have any parameters", violations.First().Description); + } + + [Fact] + public void NotHaveAnyParameters_MethodWithoutParameters_DoesNotViolate() + { + var rule = MethodMembers() + .That() + .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithMethods))) + .And() + .HaveName("PrivateMethodWithoutParameters()") + .Should() + .NotHaveAnyParameters(); + + Assert.True(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void NotHaveAnyParameters_MethodWithParameters_Violates() + { + var rule = MethodMembers() + .That() + .HaveName("MethodWithParameters(System.String,System.Int32)") + .Should() + .NotHaveAnyParameters(); + + Assert.False(rule.HasNoViolations(Architecture)); + + var evaluation = rule.Evaluate(Architecture); + var violations = evaluation.ToList(); + Assert.Single(violations); + Assert.Contains("has parameters", violations.First().Description); + } + + [Fact] + public void HaveAnyParameters_ConstructorWithParameters_DoesNotViolate() + { + var rule = MethodMembers() + .That() + .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithOnlyParameterizedConstructors))) + .And() + .AreConstructors() + .Should() + .HaveAnyParameters(); + + Assert.True(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void HaveAnyParameters_ParameterlessConstructor_Violates() + { + var rule = MethodMembers() + .That() + .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithPublicParameterlessConstructor))) + .And() + .AreConstructors() + .And() + .HaveName(".ctor()") + .Should() + .HaveAnyParameters(); + + Assert.False(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void PrivateConstructorWithoutParameters_CompositeRule_DoesNotViolate() + { + var rule = MethodMembers() + .That() + .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithPrivateParameterlessConstructor))) + .And() + .AreConstructors() + .And() + .ArePrivate() + .Should() + .NotHaveAnyParameters(); + + Assert.True(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void PublicConstructorWithParameters_CompositeRule_DoesNotViolate() + { + var rule = MethodMembers() + .That() + .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithPrivateParameterlessConstructor))) + .And() + .AreConstructors() + .And() + .ArePublic() + .Should() + .HaveAnyParameters(); + + Assert.True(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void PrivateMethodWithoutParameters_DoesNotViolate() + { + var rule = MethodMembers() + .That() + .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithMethods))) + .And() + .HaveName("PrivateMethodWithoutParameters()") + .And() + .ArePrivate() + .Should() + .NotHaveAnyParameters(); + + Assert.True(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void SpecificClass_AllConstructorsHaveParameters_DoesNotViolate() + { + var rule = MethodMembers() + .That() + .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithOnlyParameterizedConstructors))) + .And() + .AreConstructors() + .Should() + .HaveAnyParameters(); + + Assert.True(rule.HasNoViolations(Architecture)); + } + + [Fact] + public void SpecificClass_HasParameterlessConstructor_Violates() + { + var rule = MethodMembers() + .That() + .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithPublicParameterlessConstructor))) + .And() + .AreConstructors() + .Should() + .HaveAnyParameters(); + + Assert.False(rule.HasNoViolations(Architecture)); + } +} diff --git a/TestAssembly/Domain/Entities/PrivateConstructorTestClasses.cs b/TestAssembly/Domain/Entities/PrivateConstructorTestClasses.cs deleted file mode 100644 index 983b2a440..000000000 --- a/TestAssembly/Domain/Entities/PrivateConstructorTestClasses.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace TestAssembly.Domain.Entities; - -public class ClassWithPrivateParameterlessConstructor -{ - private ClassWithPrivateParameterlessConstructor() - { - // Private parameterless constructor for ORM - } - - public ClassWithPrivateParameterlessConstructor(string name) - { - Name = name; - } - - public string Name { get; private set; } -} - -public class ClassWithoutPrivateParameterlessConstructor -{ - public ClassWithoutPrivateParameterlessConstructor() - { - // Public parameterless constructor - } - - public ClassWithoutPrivateParameterlessConstructor(string name) - { - Name = name; - } - - public string Name { get; private set; } -} - -public class ClassWithOnlyParameterizedConstructors -{ - public ClassWithOnlyParameterizedConstructors(string name) - { - Name = name; - } - - public ClassWithOnlyParameterizedConstructors(int id, string name) - { - Id = id; - Name = name; - } - - public int Id { get; private set; } - public string Name { get; private set; } -} - -public abstract class AbstractClassBase -{ - protected AbstractClassBase() - { - // Abstract classes should be excluded from checks - } -} \ No newline at end of file diff --git a/TestAssembly/Domain/Methods/MethodParameterTestClass.cs b/TestAssembly/Domain/Methods/MethodParameterTestClass.cs new file mode 100644 index 000000000..7697efab0 --- /dev/null +++ b/TestAssembly/Domain/Methods/MethodParameterTestClass.cs @@ -0,0 +1,61 @@ +namespace TestAssembly.Domain.Methods; + +public class ClassWithPrivateParameterlessConstructor +{ + // Private parameterless constructor + private ClassWithPrivateParameterlessConstructor() { } + + // Public constructor with parameters + public ClassWithPrivateParameterlessConstructor(string value) + { + Value = value; + } + + public string Value { get; set; } +} + +public class ClassWithPublicParameterlessConstructor +{ + // Public parameterless constructor + public ClassWithPublicParameterlessConstructor() { } + + // Public constructor with parameters + public ClassWithPublicParameterlessConstructor(int number) + { + Number = number; + } + + public int Number { get; set; } +} + +public class ClassWithOnlyParameterizedConstructors +{ + // Only constructors with parameters + public ClassWithOnlyParameterizedConstructors(string name) + { + Name = name; + } + + public ClassWithOnlyParameterizedConstructors(string name, int id) + { + Name = name; + Id = id; + } + + public string Name { get; set; } + public int Id { get; set; } +} + +public class ClassWithMethods +{ + public ClassWithMethods() { } + + // Method without parameters + public void MethodWithoutParameters() { } + + // Method with parameters + public void MethodWithParameters(string input, int count) { } + + // Private method without parameters + private void PrivateMethodWithoutParameters() { } +} From 888e371a0a39efcfe9fb19c9f3e76fc17f279d21 Mon Sep 17 00:00:00 2001 From: Ahmed Mohamed El Ahmar Date: Fri, 28 Nov 2025 18:01:07 +0100 Subject: [PATCH 3/3] chore: code formating. Signed-off-by: Ahmed Mohamed El Ahmar --- .../MethodMemberConditionsDefinition.cs | 198 +++++++++++++----- .../MethodMembers/MethodMembersShould.cs | 142 +++++++++---- .../Elements/MethodParameterConditionTests.cs | 24 ++- 3 files changed, 275 insertions(+), 89 deletions(-) diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs index 04d3602a5..7a98b4cf7 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs @@ -30,7 +30,11 @@ public static ICondition BeConstructor() public static ICondition BeVirtual() { - return new SimpleCondition(member => member.IsVirtual, "be virtual", "is not virtual"); + return new SimpleCondition( + member => member.IsVirtual, + "be virtual", + "is not virtual" + ); } public static ICondition BeCalledBy(IType firstType, params IType[] moreTypes) @@ -49,7 +53,10 @@ public static ICondition BeCalledBy(Type firstType, params Type[] public static ICondition BeCalledBy(IObjectProvider objectProvider) { - IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + IEnumerable Condition( + IEnumerable methodMembers, + Architecture architecture + ) { var typeList = objectProvider.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); @@ -134,7 +141,10 @@ public static ICondition BeCalledBy(IEnumerable types) var typeList = types.ToList(); var firstType = typeList.First(); - IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + IEnumerable Condition( + IEnumerable methodMembers, + Architecture architecture + ) { var archUnitTypeList = new List(); foreach (var type in typeList) @@ -152,7 +162,9 @@ IEnumerable Condition(IEnumerable methodMembers, var methodMemberList = methodMembers.ToList(); var passedObjects = methodMemberList - .Where(methodMember => methodMember.GetCallingTypes().Intersect(archUnitTypeList).Any()) + .Where(methodMember => + methodMember.GetCallingTypes().Intersect(archUnitTypeList).Any() + ) .ToList(); string failDescription; if (typeList.IsNullOrEmpty()) @@ -200,23 +212,34 @@ IEnumerable Condition(IEnumerable methodMembers, return new ArchitectureCondition(Condition, description); } - public static ICondition HaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) + public static ICondition HaveDependencyInMethodBodyTo( + IType firstType, + params IType[] moreTypes + ) { var types = new List { firstType }; types.AddRange(moreTypes); return HaveDependencyInMethodBodyTo(types); } - public static ICondition HaveDependencyInMethodBodyTo(Type firstType, params Type[] moreTypes) + public static ICondition HaveDependencyInMethodBodyTo( + Type firstType, + params Type[] moreTypes + ) { var types = new List { firstType }; types.AddRange(moreTypes); return HaveDependencyInMethodBodyTo(types); } - public static ICondition HaveDependencyInMethodBodyTo(IObjectProvider objectProvider) + public static ICondition HaveDependencyInMethodBodyTo( + IObjectProvider objectProvider + ) { - IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + IEnumerable Condition( + IEnumerable methodMembers, + Architecture architecture + ) { var typeList = objectProvider.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); @@ -229,7 +252,8 @@ IEnumerable Condition(IEnumerable methodMembers, .Any() ) .ToList(); - var failDescription = "does not have dependencies in method body to " + objectProvider.Description; + var failDescription = + "does not have dependencies in method body to " + objectProvider.Description; foreach (var failedObject in methodMemberList.Except(passedObjects)) { yield return new ConditionResult(failedObject, false, failDescription); @@ -245,7 +269,9 @@ IEnumerable Condition(IEnumerable methodMembers, return new ArchitectureCondition(Condition, description); } - public static ICondition HaveDependencyInMethodBodyTo(IEnumerable types) + public static ICondition HaveDependencyInMethodBodyTo( + IEnumerable types + ) { var typeList = types.ToList(); var firstType = typeList.First(); @@ -265,7 +291,8 @@ IEnumerable Condition(IEnumerable methodMembers) string failDescription; if (typeList.IsNullOrEmpty()) { - failDescription = "does not have dependencies in method body to one of no types (always true)"; + failDescription = + "does not have dependencies in method body to one of no types (always true)"; } else { @@ -273,7 +300,9 @@ IEnumerable Condition(IEnumerable methodMembers) .Where(type => !type.Equals(firstType)) .Distinct() .Aggregate( - "does not have dependencies in method body to \"" + firstType.FullName + "\"", + "does not have dependencies in method body to \"" + + firstType.FullName + + "\"", (current, type) => current + " or \"" + type.FullName + "\"" ); } @@ -313,7 +342,10 @@ public static ICondition HaveDependencyInMethodBodyTo(IEnumerable< var typeList = types.ToList(); var firstType = typeList.First(); - IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + IEnumerable Condition( + IEnumerable methodMembers, + Architecture architecture + ) { var archUnitTypeList = new List(); foreach (var type in typeList) @@ -342,7 +374,8 @@ IEnumerable Condition(IEnumerable methodMembers, string failDescription; if (typeList.IsNullOrEmpty()) { - failDescription = "does not have dependencies in method body to one of no types (always true)"; + failDescription = + "does not have dependencies in method body to one of no types (always true)"; } else { @@ -350,7 +383,9 @@ IEnumerable Condition(IEnumerable methodMembers, .Where(type => type != firstType) .Distinct() .Aggregate( - "does not have dependencies in method body to \"" + firstType.FullName + "\"", + "does not have dependencies in method body to \"" + + firstType.FullName + + "\"", (current, type) => current + " or \"" + type.FullName + "\"" ); } @@ -385,7 +420,10 @@ IEnumerable Condition(IEnumerable methodMembers, return new ArchitectureCondition(Condition, description); } - public static ICondition HaveReturnType(IType firstType, params IType[] moreTypes) + public static ICondition HaveReturnType( + IType firstType, + params IType[] moreTypes + ) { var types = new List { firstType }; types.AddRange(moreTypes); @@ -396,7 +434,8 @@ public static ICondition HaveReturnType(IEnumerable types) { var typeList = types.ToList(); var typeStringList = typeList.Select(type => type.FullName).ToList(); - var description = "have return type \"" + string.Join("\" or \"", typeStringList) + "\""; + var description = + "have return type \"" + string.Join("\" or \"", typeStringList) + "\""; bool Condition(MethodMember member) { @@ -412,12 +451,17 @@ bool Condition(MethodMember member) public static ICondition HaveReturnType(IObjectProvider types) { - IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + IEnumerable Condition( + IEnumerable methodMembers, + Architecture architecture + ) { var typeList = types.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); var passedObjects = methodMemberList - .Where(methodMember => typeList.Any(type => methodMember.ReturnType.FullNameEquals(type.FullName))) + .Where(methodMember => + typeList.Any(type => methodMember.ReturnType.FullNameEquals(type.FullName)) + ) .ToList(); foreach (var failedObject in methodMemberList.Except(passedObjects)) { @@ -438,7 +482,10 @@ IEnumerable Condition(IEnumerable methodMembers, return new ArchitectureCondition(Condition, description); } - public static ICondition HaveReturnType(Type firstType, params Type[] moreTypes) + public static ICondition HaveReturnType( + Type firstType, + params Type[] moreTypes + ) { var types = new List { firstType }; types.AddRange(moreTypes); @@ -449,7 +496,8 @@ public static ICondition HaveReturnType(IEnumerable types) { var typeList = types.ToList(); var typeStringList = typeList.Select(type => type.ToString()).ToList(); - var description = "have return type \"" + string.Join("\" or \"", typeStringList) + "\""; + var description = + "have return type \"" + string.Join("\" or \"", typeStringList) + "\""; bool Condition(MethodMember member) { @@ -476,17 +524,27 @@ public static ICondition BeNoConstructor() public static ICondition NotBeVirtual() { - return new SimpleCondition(member => !member.IsVirtual, "not be virtual", "is virtual"); + return new SimpleCondition( + member => !member.IsVirtual, + "not be virtual", + "is virtual" + ); } - public static ICondition NotBeCalledBy(IType firstType, params IType[] moreTypes) + public static ICondition NotBeCalledBy( + IType firstType, + params IType[] moreTypes + ) { var types = new List { firstType }; types.AddRange(moreTypes); return NotBeCalledBy(types); } - public static ICondition NotBeCalledBy(Type firstType, params Type[] moreTypes) + public static ICondition NotBeCalledBy( + Type firstType, + params Type[] moreTypes + ) { var types = new List { firstType }; types.AddRange(moreTypes); @@ -495,7 +553,10 @@ public static ICondition NotBeCalledBy(Type firstType, params Type public static ICondition NotBeCalledBy(IObjectProvider objectProvider) { - IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + IEnumerable Condition( + IEnumerable methodMembers, + Architecture architecture + ) { var typeList = objectProvider.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); @@ -580,7 +641,10 @@ public static ICondition NotBeCalledBy(IEnumerable types) var typeList = types.ToList(); var firstType = typeList.First(); - IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + IEnumerable Condition( + IEnumerable methodMembers, + Architecture architecture + ) { var archUnitTypeList = new List(); foreach (var type in typeList) @@ -598,7 +662,9 @@ IEnumerable Condition(IEnumerable methodMembers, var methodMemberList = methodMembers.ToList(); var failedObjects = methodMemberList - .Where(methodMember => methodMember.GetCallingTypes().Intersect(archUnitTypeList).Any()) + .Where(methodMember => + methodMember.GetCallingTypes().Intersect(archUnitTypeList).Any() + ) .ToList(); string failDescription; if (typeList.IsNullOrEmpty()) @@ -656,16 +722,24 @@ params IType[] moreTypes return NotHaveDependencyInMethodBodyTo(types); } - public static ICondition NotHaveDependencyInMethodBodyTo(Type firstType, params Type[] moreTypes) + public static ICondition NotHaveDependencyInMethodBodyTo( + Type firstType, + params Type[] moreTypes + ) { var types = new List { firstType }; types.AddRange(moreTypes); return NotHaveDependencyInMethodBodyTo(types); } - public static ICondition NotHaveDependencyInMethodBodyTo(IObjectProvider objectProvider) + public static ICondition NotHaveDependencyInMethodBodyTo( + IObjectProvider objectProvider + ) { - IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + IEnumerable Condition( + IEnumerable methodMembers, + Architecture architecture + ) { var typeList = objectProvider.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); @@ -678,7 +752,8 @@ IEnumerable Condition(IEnumerable methodMembers, .Any() ) .ToList(); - var failDescription = "does have dependencies in method body to " + objectProvider.Description; + var failDescription = + "does have dependencies in method body to " + objectProvider.Description; foreach (var failedObject in failedObjects) { yield return new ConditionResult(failedObject, false, failDescription); @@ -690,11 +765,14 @@ IEnumerable Condition(IEnumerable methodMembers, } } - var description = "not have dependencies in method body to " + objectProvider.Description; + var description = + "not have dependencies in method body to " + objectProvider.Description; return new ArchitectureCondition(Condition, description); } - public static ICondition NotHaveDependencyInMethodBodyTo(IEnumerable types) + public static ICondition NotHaveDependencyInMethodBodyTo( + IEnumerable types + ) { var typeList = types.ToList(); var firstType = typeList.First(); @@ -714,7 +792,8 @@ IEnumerable Condition(IEnumerable methodMembers) string failDescription; if (typeList.IsNullOrEmpty()) { - failDescription = "does have dependencies in method body to one of no types (always false)"; + failDescription = + "does have dependencies in method body to one of no types (always false)"; } else { @@ -722,7 +801,9 @@ IEnumerable Condition(IEnumerable methodMembers) .Where(type => !Equals(type, firstType)) .Distinct() .Aggregate( - "does have dependencies in method body to \"" + firstType.FullName + "\"", + "does have dependencies in method body to \"" + + firstType.FullName + + "\"", (current, type) => current + " or \"" + type.FullName + "\"" ); } @@ -741,7 +822,8 @@ IEnumerable Condition(IEnumerable methodMembers) string description; if (typeList.IsNullOrEmpty()) { - description = "not have dependencies in method body to one of no types (always true)"; + description = + "not have dependencies in method body to one of no types (always true)"; } else { @@ -757,12 +839,17 @@ IEnumerable Condition(IEnumerable methodMembers) return new EnumerableCondition(Condition, description); } - public static ICondition NotHaveDependencyInMethodBodyTo(IEnumerable types) + public static ICondition NotHaveDependencyInMethodBodyTo( + IEnumerable types + ) { var typeList = types.ToList(); var firstType = typeList.First(); - IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + IEnumerable Condition( + IEnumerable methodMembers, + Architecture architecture + ) { var archUnitTypeList = new List(); foreach (var type in typeList) @@ -791,7 +878,8 @@ IEnumerable Condition(IEnumerable methodMembers, string failDescription; if (typeList.IsNullOrEmpty()) { - failDescription = "does have dependencies in method body to one of no types (always false)"; + failDescription = + "does have dependencies in method body to one of no types (always false)"; } else { @@ -799,7 +887,9 @@ IEnumerable Condition(IEnumerable methodMembers, .Where(type => type != firstType) .Distinct() .Aggregate( - "does have dependencies in method body to \"" + firstType.FullName + "\"", + "does have dependencies in method body to \"" + + firstType.FullName + + "\"", (current, type) => current + " or \"" + type.FullName + "\"" ); } @@ -818,7 +908,8 @@ IEnumerable Condition(IEnumerable methodMembers, string description; if (typeList.IsNullOrEmpty()) { - description = "not have dependencies in method body to one of no types (always true)"; + description = + "not have dependencies in method body to one of no types (always true)"; } else { @@ -834,7 +925,10 @@ IEnumerable Condition(IEnumerable methodMembers, return new ArchitectureCondition(Condition, description); } - public static ICondition NotHaveReturnType(IType firstType, params IType[] moreTypes) + public static ICondition NotHaveReturnType( + IType firstType, + params IType[] moreTypes + ) { var types = new List { firstType }; types.AddRange(moreTypes); @@ -845,7 +939,8 @@ public static ICondition NotHaveReturnType(IEnumerable type { var typeList = types.ToList(); var typeStringList = typeList.Select(type => type.FullName).ToList(); - var description = "not have return type \"" + string.Join("\" or \"", typeStringList) + "\""; + var description = + "not have return type \"" + string.Join("\" or \"", typeStringList) + "\""; bool Condition(MethodMember member) { @@ -861,12 +956,17 @@ bool Condition(MethodMember member) public static ICondition NotHaveReturnType(IObjectProvider types) { - IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + IEnumerable Condition( + IEnumerable methodMembers, + Architecture architecture + ) { var typeList = types.GetObjects(architecture).ToList(); var methodMemberList = methodMembers.ToList(); var passedObjects = methodMemberList - .Where(methodMember => typeList.All(type => !methodMember.ReturnType.FullNameEquals(type.FullName))) + .Where(methodMember => + typeList.All(type => !methodMember.ReturnType.FullNameEquals(type.FullName)) + ) .ToList(); foreach (var failedObject in methodMemberList.Except(passedObjects)) { @@ -887,7 +987,10 @@ IEnumerable Condition(IEnumerable methodMembers, return new ArchitectureCondition(Condition, description); } - public static ICondition NotHaveReturnType(Type firstType, params Type[] moreTypes) + public static ICondition NotHaveReturnType( + Type firstType, + params Type[] moreTypes + ) { var types = new List { firstType }; types.AddRange(moreTypes); @@ -898,7 +1001,8 @@ public static ICondition NotHaveReturnType(IEnumerable types { var typeList = types.ToList(); var typeStringList = typeList.Select(type => type.ToString()).ToList(); - var description = "not have return type \"" + string.Join("\" or \"", typeStringList) + "\""; + var description = + "not have return type \"" + string.Join("\" or \"", typeStringList) + "\""; bool Condition(MethodMember member) { diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs index 2ead07fa9..06f92feeb 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs @@ -1,7 +1,11 @@ -using System; +#region + +using System; using System.Collections.Generic; using ArchUnitNET.Domain; +#endregion + namespace ArchUnitNET.Fluent.Syntax.Elements.Members.MethodMembers { public class MethodMembersShould @@ -11,15 +15,6 @@ public class MethodMembersShould public MethodMembersShould(IArchRuleCreator ruleCreator) : base(ruleCreator) { } - public ShouldRelateToMethodMembersThat BeMethodMembersThat() - { - _ruleCreator.BeginComplexCondition( - ArchRuleDefinition.MethodMembers(), - MethodMemberConditionsDefinition.BeMethodMembersThat() - ); - return new ShouldRelateToMethodMembersThat(_ruleCreator); - } - public MethodMembersShouldConjunction BeConstructor() { _ruleCreator.AddCondition(MethodMemberConditionsDefinition.BeConstructor()); @@ -34,7 +29,9 @@ public MethodMembersShouldConjunction BeVirtual() public MethodMembersShouldConjunction BeCalledBy(IType firstType, params IType[] moreTypes) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.BeCalledBy(firstType, moreTypes)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.BeCalledBy(firstType, moreTypes) + ); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -62,7 +59,10 @@ public MethodMembersShouldConjunction BeCalledBy(IEnumerable types) return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo( + IType firstType, + params IType[] moreTypes + ) { _ruleCreator.AddCondition( MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(firstType, moreTypes) @@ -70,33 +70,51 @@ public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IType firstTy return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes) + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo( + Type type, + params Type[] moreTypes + ) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(type, moreTypes)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(type, moreTypes) + ); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IObjectProvider types) + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo( + IObjectProvider types + ) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types) + ); return new MethodMembersShouldConjunction(_ruleCreator); } public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IEnumerable types) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types) + ); return new MethodMembersShouldConjunction(_ruleCreator); } public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IEnumerable types) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types) + ); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction HaveReturnType(IType firstType, params IType[] moreTypes) + public MethodMembersShouldConjunction HaveReturnType( + IType firstType, + params IType[] moreTypes + ) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveReturnType(firstType, moreTypes)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveReturnType(firstType, moreTypes) + ); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -114,7 +132,9 @@ public MethodMembersShouldConjunction HaveReturnType(IObjectProvider type public MethodMembersShouldConjunction HaveReturnType(Type type, params Type[] moreTypes) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.HaveReturnType(type, moreTypes)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveReturnType(type, moreTypes) + ); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -138,15 +158,22 @@ public MethodMembersShouldConjunction NotBeVirtual() return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotBeCalledBy(IType firstType, params IType[] moreTypes) + public MethodMembersShouldConjunction NotBeCalledBy( + IType firstType, + params IType[] moreTypes + ) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotBeCalledBy(firstType, moreTypes)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotBeCalledBy(firstType, moreTypes) + ); return new MethodMembersShouldConjunction(_ruleCreator); } public MethodMembersShouldConjunction NotBeCalledBy(Type type, params Type[] moreTypes) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotBeCalledBy(type, moreTypes)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotBeCalledBy(type, moreTypes) + ); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -168,15 +195,24 @@ public MethodMembersShouldConjunction NotBeCalledBy(IEnumerable types) return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo( + IType firstType, + params IType[] moreTypes + ) { _ruleCreator.AddCondition( - MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(firstType, moreTypes) + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo( + firstType, + moreTypes + ) ); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes) + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo( + Type type, + params Type[] moreTypes + ) { _ruleCreator.AddCondition( MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(type, moreTypes) @@ -184,27 +220,44 @@ public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(Type type, return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IObjectProvider types) + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo( + IObjectProvider types + ) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types) + ); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IEnumerable types) + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo( + IEnumerable types + ) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types) + ); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IEnumerable types) + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo( + IEnumerable types + ) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types) + ); return new MethodMembersShouldConjunction(_ruleCreator); } - public MethodMembersShouldConjunction NotHaveReturnType(IType firstType, params IType[] moreTypes) + public MethodMembersShouldConjunction NotHaveReturnType( + IType firstType, + params IType[] moreTypes + ) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveReturnType(firstType, moreTypes)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveReturnType(firstType, moreTypes) + ); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -222,7 +275,9 @@ public MethodMembersShouldConjunction NotHaveReturnType(IObjectProvider t public MethodMembersShouldConjunction NotHaveReturnType(Type type, params Type[] moreTypes) { - _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveReturnType(type, moreTypes)); + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveReturnType(type, moreTypes) + ); return new MethodMembersShouldConjunction(_ruleCreator); } @@ -243,5 +298,20 @@ public MethodMembersShouldConjunction NotHaveAnyParameters() _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotHaveAnyParameters()); return new MethodMembersShouldConjunction(_ruleCreator); } + + public ShouldRelateToMethodMembersThat< + MethodMembersShouldConjunction, + MethodMember + > BeMethodMembersThat() + { + _ruleCreator.BeginComplexCondition( + ArchRuleDefinition.MethodMembers(), + MethodMemberConditionsDefinition.BeMethodMembersThat() + ); + return new ShouldRelateToMethodMembersThat< + MethodMembersShouldConjunction, + MethodMember + >(_ruleCreator); + } } } diff --git a/ArchUnitNETTests/Fluent/Syntax/Elements/MethodParameterConditionTests.cs b/ArchUnitNETTests/Fluent/Syntax/Elements/MethodParameterConditionTests.cs index b47996944..804b7a2c9 100644 --- a/ArchUnitNETTests/Fluent/Syntax/Elements/MethodParameterConditionTests.cs +++ b/ArchUnitNETTests/Fluent/Syntax/Elements/MethodParameterConditionTests.cs @@ -82,7 +82,9 @@ public void HaveAnyParameters_ConstructorWithParameters_DoesNotViolate() { var rule = MethodMembers() .That() - .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithOnlyParameterizedConstructors))) + .AreDeclaredIn( + Classes().That().HaveName(nameof(ClassWithOnlyParameterizedConstructors)) + ) .And() .AreConstructors() .Should() @@ -96,7 +98,9 @@ public void HaveAnyParameters_ParameterlessConstructor_Violates() { var rule = MethodMembers() .That() - .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithPublicParameterlessConstructor))) + .AreDeclaredIn( + Classes().That().HaveName(nameof(ClassWithPublicParameterlessConstructor)) + ) .And() .AreConstructors() .And() @@ -112,7 +116,9 @@ public void PrivateConstructorWithoutParameters_CompositeRule_DoesNotViolate() { var rule = MethodMembers() .That() - .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithPrivateParameterlessConstructor))) + .AreDeclaredIn( + Classes().That().HaveName(nameof(ClassWithPrivateParameterlessConstructor)) + ) .And() .AreConstructors() .And() @@ -128,7 +134,9 @@ public void PublicConstructorWithParameters_CompositeRule_DoesNotViolate() { var rule = MethodMembers() .That() - .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithPrivateParameterlessConstructor))) + .AreDeclaredIn( + Classes().That().HaveName(nameof(ClassWithPrivateParameterlessConstructor)) + ) .And() .AreConstructors() .And() @@ -160,7 +168,9 @@ public void SpecificClass_AllConstructorsHaveParameters_DoesNotViolate() { var rule = MethodMembers() .That() - .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithOnlyParameterizedConstructors))) + .AreDeclaredIn( + Classes().That().HaveName(nameof(ClassWithOnlyParameterizedConstructors)) + ) .And() .AreConstructors() .Should() @@ -174,7 +184,9 @@ public void SpecificClass_HasParameterlessConstructor_Violates() { var rule = MethodMembers() .That() - .AreDeclaredIn(Classes().That().HaveName(nameof(ClassWithPublicParameterlessConstructor))) + .AreDeclaredIn( + Classes().That().HaveName(nameof(ClassWithPublicParameterlessConstructor)) + ) .And() .AreConstructors() .Should()