diff --git a/ArchUnitNET/Core/Type.cs b/ArchUnitNET/Core/Type.cs index 1439341eb..c670a6c47 100644 --- a/ArchUnitNET/Core/Type.cs +++ b/ArchUnitNET/Core/Type.cs @@ -53,7 +53,7 @@ public Type(string fullname, string name, Assembly assembly, Namespace namespc, .OfType() .Select(dependency => dependency.Target); - public bool ImplementsInterface(IType intf) + public bool ImplementsInterface(Interface intf) { return ImplementedInterfaces.Any(implementedInterface => Equals(implementedInterface, intf) || Equals(implementedInterface.GenericType, intf)); @@ -84,7 +84,7 @@ public bool IsAssignableTo(IType assignableToType) return true; } - return assignableToType is Interface && ImplementsInterface(assignableToType); + return assignableToType is Interface && ImplementsInterface((Interface) assignableToType); } public bool IsAssignableTo(string pattern, bool useRegularExpressions = false) diff --git a/ArchUnitNET/Domain/Class.cs b/ArchUnitNET/Domain/Class.cs index 58d288d3a..6542f02bb 100644 --- a/ArchUnitNET/Domain/Class.cs +++ b/ArchUnitNET/Domain/Class.cs @@ -83,7 +83,7 @@ public bool? IsStruct public IType GenericType => Type.GenericType; public List GenericTypeArguments => Type.GenericTypeArguments; - public bool ImplementsInterface(IType intf) + public bool ImplementsInterface(Interface intf) { return Type.ImplementsInterface(intf); } diff --git a/ArchUnitNET/Domain/IType.cs b/ArchUnitNET/Domain/IType.cs index a2758d3b1..378488014 100644 --- a/ArchUnitNET/Domain/IType.cs +++ b/ArchUnitNET/Domain/IType.cs @@ -19,7 +19,7 @@ public interface IType : ICanBeAnalyzed [CanBeNull] IType GenericType { get; } bool IsNested { get; } IEnumerable ImplementedInterfaces { get; } - bool ImplementsInterface(IType intf); + bool ImplementsInterface(Interface intf); bool ImplementsInterface(string pattern, bool useRegularExpressions = false); bool IsAssignableTo(IType assignableToType); bool IsAssignableTo(string pattern, bool useRegularExpressions = false); diff --git a/ArchUnitNET/Domain/Interface.cs b/ArchUnitNET/Domain/Interface.cs index e3e0a1e15..67f526a3e 100644 --- a/ArchUnitNET/Domain/Interface.cs +++ b/ArchUnitNET/Domain/Interface.cs @@ -38,7 +38,7 @@ public Interface(IType type) public IType GenericType => Type.GenericType; public List GenericTypeArguments => Type.GenericTypeArguments; - public bool ImplementsInterface(IType intf) + public bool ImplementsInterface(Interface intf) { return Type.ImplementsInterface(intf); } diff --git a/ArchUnitNET/Fluent/Extensions/MemberExtensions.cs b/ArchUnitNET/Fluent/Extensions/MemberExtensions.cs index 8fc62f8e2..35bbbade9 100644 --- a/ArchUnitNET/Fluent/Extensions/MemberExtensions.cs +++ b/ArchUnitNET/Fluent/Extensions/MemberExtensions.cs @@ -56,6 +56,12 @@ public static bool IsCalledBy(this MethodMember member, string pattern, bool use dependency.Origin.FullNameMatches(pattern, useRegularExpressions)); } + public static IEnumerable GetCallingTypes(this MethodMember member) + { + return member.MemberBackwardsDependencies.OfType() + .Select(dependency => dependency.Origin).Distinct(); + } + public static bool HasDependencyInMethodBodyTo(this MethodMember member, string pattern, bool useRegularExpressions = false) { diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/GivenMethodMembersThat.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/GivenMethodMembersThat.cs index 96e7a0ee7..757cfc272 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/GivenMethodMembersThat.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/GivenMethodMembersThat.cs @@ -4,6 +4,8 @@ // // SPDX-License-Identifier: Apache-2.0 +using System; +using System.Collections.Generic; using ArchUnitNET.Domain; namespace ArchUnitNET.Fluent.Syntax.Elements.Members.MethodMembers @@ -33,6 +35,43 @@ public GivenMethodMembersConjunction AreCalledBy(string pattern, bool useRegular return new GivenMethodMembersConjunction(_ruleCreator); } + public GivenMethodMembersConjunction AreCalledBy(IEnumerable patterns, + bool useRegularExpressions = false) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreCalledBy(patterns, useRegularExpressions)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction AreCalledBy(IType firstType, params IType[] moreTypes) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreCalledBy(firstType, moreTypes)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction AreCalledBy(Type type, params Type[] moreTypes) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreCalledBy(type, moreTypes)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction AreCalledBy(IObjectProvider types) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreCalledBy(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction AreCalledBy(IEnumerable types) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreCalledBy(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction AreCalledBy(IEnumerable types) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreCalledBy(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + public GivenMethodMembersConjunction HaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false) { @@ -41,6 +80,49 @@ public GivenMethodMembersConjunction HaveDependencyInMethodBodyTo(string pattern return new GivenMethodMembersConjunction(_ruleCreator); } + public GivenMethodMembersConjunction HaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(patterns, useRegularExpressions)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction HaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(firstType, moreTypes)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction HaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(type, moreTypes)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction HaveDependencyInMethodBodyTo(IObjectProvider types) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction HaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction HaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + //Negations @@ -62,6 +144,43 @@ public GivenMethodMembersConjunction AreNotCalledBy(string pattern, bool useRegu return new GivenMethodMembersConjunction(_ruleCreator); } + public GivenMethodMembersConjunction AreNotCalledBy(IEnumerable patterns, + bool useRegularExpressions = false) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreNotCalledBy(patterns, useRegularExpressions)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction AreNotCalledBy(IType firstType, params IType[] moreTypes) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreNotCalledBy(firstType, moreTypes)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction AreNotCalledBy(Type type, params Type[] moreTypes) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreNotCalledBy(type, moreTypes)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction AreNotCalledBy(IObjectProvider types) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreNotCalledBy(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction AreNotCalledBy(IEnumerable types) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreNotCalledBy(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction AreNotCalledBy(IEnumerable types) + { + _ruleCreator.AddPredicate(MethodMemberPredicatesDefinition.AreNotCalledBy(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + public GivenMethodMembersConjunction DoNotHaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false) { @@ -69,5 +188,49 @@ public GivenMethodMembersConjunction DoNotHaveDependencyInMethodBodyTo(string pa MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(pattern, useRegularExpressions)); return new GivenMethodMembersConjunction(_ruleCreator); } + + public GivenMethodMembersConjunction DoNotHaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(patterns, useRegularExpressions)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction DoNotHaveDependencyInMethodBodyTo(IType firstType, + params IType[] moreTypes) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(firstType, moreTypes)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction DoNotHaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(type, moreTypes)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction DoNotHaveDependencyInMethodBodyTo(IObjectProvider types) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction DoNotHaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } + + public GivenMethodMembersConjunction DoNotHaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.AddPredicate( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(types)); + return new GivenMethodMembersConjunction(_ruleCreator); + } } } \ No newline at end of file diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberConditions.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberConditions.cs index 331561213..08fdf9a66 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberConditions.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberConditions.cs @@ -4,6 +4,10 @@ // // SPDX-License-Identifier: Apache-2.0 +using System; +using System.Collections.Generic; +using ArchUnitNET.Domain; + namespace ArchUnitNET.Fluent.Syntax.Elements.Members.MethodMembers { public interface IMethodMemberConditions : IMemberConditions @@ -11,7 +15,19 @@ public interface IMethodMemberConditions : IMemberConditions patterns, bool useRegularExpressions = false); + TReturnType BeCalledBy(IType firstType, params IType[] moreTypes); + TReturnType BeCalledBy(Type type, params Type[] moreTypes); + TReturnType BeCalledBy(IObjectProvider types); + TReturnType BeCalledBy(IEnumerable types); + TReturnType BeCalledBy(IEnumerable types); TReturnType HaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false); + TReturnType HaveDependencyInMethodBodyTo(IEnumerable patterns, bool useRegularExpressions = false); + TReturnType HaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes); + TReturnType HaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes); + TReturnType HaveDependencyInMethodBodyTo(IObjectProvider types); + TReturnType HaveDependencyInMethodBodyTo(IEnumerable types); + TReturnType HaveDependencyInMethodBodyTo(IEnumerable types); //Negations @@ -20,6 +36,18 @@ public interface IMethodMemberConditions : IMemberConditions patterns, bool useRegularExpressions = false); + TReturnType NotBeCalledBy(IType firstType, params IType[] moreTypes); + TReturnType NotBeCalledBy(Type type, params Type[] moreTypes); + TReturnType NotBeCalledBy(IObjectProvider types); + TReturnType NotBeCalledBy(IEnumerable types); + TReturnType NotBeCalledBy(IEnumerable types); TReturnType NotHaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false); + TReturnType NotHaveDependencyInMethodBodyTo(IEnumerable patterns, bool useRegularExpressions = false); + TReturnType NotHaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes); + TReturnType NotHaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes); + TReturnType NotHaveDependencyInMethodBodyTo(IObjectProvider types); + TReturnType NotHaveDependencyInMethodBodyTo(IEnumerable types); + TReturnType NotHaveDependencyInMethodBodyTo(IEnumerable types); } } \ No newline at end of file diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberPredicates.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberPredicates.cs index 68eb55cc2..31db18098 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberPredicates.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/IMethodMemberPredicates.cs @@ -4,6 +4,10 @@ // // SPDX-License-Identifier: Apache-2.0 +using System; +using System.Collections.Generic; +using ArchUnitNET.Domain; + namespace ArchUnitNET.Fluent.Syntax.Elements.Members.MethodMembers { public interface IMethodMemberPredicates : IMemberPredicates @@ -11,8 +15,23 @@ public interface IMethodMemberPredicates : IMemberPred TRuleTypeConjunction AreConstructors(); TRuleTypeConjunction AreVirtual(); TRuleTypeConjunction AreCalledBy(string pattern, bool useRegularExpressions = false); + TRuleTypeConjunction AreCalledBy(IEnumerable patterns, bool useRegularExpressions = false); + TRuleTypeConjunction AreCalledBy(IType firstType, params IType[] moreTypes); + TRuleTypeConjunction AreCalledBy(Type type, params Type[] moreTypes); + TRuleTypeConjunction AreCalledBy(IObjectProvider types); + TRuleTypeConjunction AreCalledBy(IEnumerable types); + TRuleTypeConjunction AreCalledBy(IEnumerable types); TRuleTypeConjunction HaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false); + TRuleTypeConjunction HaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false); + + TRuleTypeConjunction HaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes); + TRuleTypeConjunction HaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes); + TRuleTypeConjunction HaveDependencyInMethodBodyTo(IObjectProvider types); + TRuleTypeConjunction HaveDependencyInMethodBodyTo(IEnumerable types); + TRuleTypeConjunction HaveDependencyInMethodBodyTo(IEnumerable types); + //Negations @@ -20,6 +39,21 @@ public interface IMethodMemberPredicates : IMemberPred TRuleTypeConjunction AreNoConstructors(); TRuleTypeConjunction AreNotVirtual(); TRuleTypeConjunction AreNotCalledBy(string pattern, bool useRegularExpressions = false); + TRuleTypeConjunction AreNotCalledBy(IEnumerable patterns, bool useRegularExpressions = false); + TRuleTypeConjunction AreNotCalledBy(IType firstType, params IType[] moreTypes); + TRuleTypeConjunction AreNotCalledBy(Type type, params Type[] moreTypes); + TRuleTypeConjunction AreNotCalledBy(IObjectProvider types); + TRuleTypeConjunction AreNotCalledBy(IEnumerable types); + TRuleTypeConjunction AreNotCalledBy(IEnumerable types); TRuleTypeConjunction DoNotHaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false); + + TRuleTypeConjunction DoNotHaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false); + + TRuleTypeConjunction DoNotHaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes); + TRuleTypeConjunction DoNotHaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes); + TRuleTypeConjunction DoNotHaveDependencyInMethodBodyTo(IObjectProvider types); + TRuleTypeConjunction DoNotHaveDependencyInMethodBodyTo(IEnumerable types); + TRuleTypeConjunction DoNotHaveDependencyInMethodBodyTo(IEnumerable types); } } \ No newline at end of file diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs index b5d86453a..e812c918e 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberConditionsDefinition.cs @@ -4,6 +4,8 @@ // // SPDX-License-Identifier: Apache-2.0 +using System; +using System.Collections.Generic; using System.Linq; using ArchUnitNET.Domain; using ArchUnitNET.Fluent.Conditions; @@ -34,6 +36,178 @@ public static ICondition BeCalledBy(string pattern, bool useRegula pattern + "\""); } + public static ICondition BeCalledBy(IEnumerable patterns, + bool useRegularExpressions = false) + { + var patternList = patterns.ToList(); + + bool Condition(MethodMember ruleType) + { + return patternList.Any(pattern => ruleType.IsCalledBy(pattern, useRegularExpressions)); + } + + string description; + string failDescription; + if (patternList.IsNullOrEmpty()) + { + description = "be called by one of no types (always false)"; + failDescription = "is not called by one of no types (always true)"; + } + else + { + var firstPattern = patternList.First(); + description = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "be called by types with full name " + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", + (current, pattern) => current + " or \"" + pattern + "\""); + failDescription = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "is not called by types with full name " + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", + (current, pattern) => current + " or \"" + pattern + "\""); + } + + + return new SimpleCondition(Condition, description, failDescription); + } + + public static ICondition BeCalledBy(IType firstType, params IType[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return BeCalledBy(types); + } + + public static ICondition BeCalledBy(Type firstType, params Type[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return BeCalledBy(types); + } + + public static ICondition BeCalledBy(IObjectProvider objectProvider) + { + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + { + var typeList = objectProvider.GetObjects(architecture).ToList(); + var methodMemberList = methodMembers.ToList(); + var passedObjects = methodMemberList + .Where(methodMember => methodMember.GetCallingTypes().Intersect(typeList).Any()) + .ToList(); + var failDescription = "is not called by " + objectProvider.Description; + foreach (var failedObject in methodMemberList.Except(passedObjects)) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in passedObjects) + { + yield return new ConditionResult(passedObject, true); + } + } + + var description = "be called by " + objectProvider.Description; + return new ArchitectureCondition(Condition, description); + } + + public static ICondition BeCalledBy(IEnumerable types) + { + var typeList = types.ToList(); + var firstType = typeList.First(); + + IEnumerable Condition(IEnumerable methodMembers) + { + var methodMemberList = methodMembers.ToList(); + var passedObjects = methodMemberList + .Where(methodMember => methodMember.GetCallingTypes().Intersect(typeList).Any()) + .ToList(); + string failDescription; + if (typeList.IsNullOrEmpty()) + { + failDescription = "is not called by one of no types (always true)"; + } + else + { + failDescription = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "is not called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + foreach (var failedObject in methodMemberList.Except(passedObjects)) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in passedObjects) + { + yield return new ConditionResult(passedObject, true); + } + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "be called by one of no types (always false)"; + } + else + { + description = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "be called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new EnumerableCondition(Condition, description); + } + + public static ICondition BeCalledBy(IEnumerable types) + { + var typeList = types.ToList(); + var firstType = typeList.First(); + + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + { + var iTypeList = typeList.Select(architecture.GetITypeOfType).ToList(); + var methodMemberList = methodMembers.ToList(); + var passedObjects = methodMemberList + .Where(methodMember => methodMember.GetCallingTypes().Intersect(iTypeList).Any()) + .ToList(); + string failDescription; + if (typeList.IsNullOrEmpty()) + { + failDescription = "is not called by one of no types (always true)"; + } + else + { + failDescription = typeList.Where(type => type != firstType).Distinct().Aggregate( + "is not called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + foreach (var failedObject in methodMemberList.Except(passedObjects)) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in passedObjects) + { + yield return new ConditionResult(passedObject, true); + } + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "be called by one of no types (always false)"; + } + else + { + description = typeList.Where(type => type != firstType).Distinct().Aggregate( + "be called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new ArchitectureCondition(Condition, description); + } + public static ICondition HaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false) { @@ -47,6 +221,183 @@ public static ICondition HaveDependencyInMethodBodyTo(string patte pattern + "\""); } + public static ICondition HaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false) + { + var patternList = patterns.ToList(); + + bool Condition(MethodMember ruleType) + { + return patternList.Any(pattern => ruleType.HasDependencyInMethodBodyTo(pattern, useRegularExpressions)); + } + + string description; + string failDescription; + if (patternList.IsNullOrEmpty()) + { + description = "have dependency in method body to one of no types (always false)"; + failDescription = "does not have dependencies in method body to one of no types (always true)"; + } + else + { + var firstPattern = patternList.First(); + description = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "have dependencies in method body to types with full name " + + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", + (current, pattern) => current + " or \"" + pattern + "\""); + failDescription = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "does not have dependencies in method body to types with full name " + + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", + (current, pattern) => current + " or \"" + pattern + "\""); + } + + + return new SimpleCondition(Condition, description, failDescription); + } + + 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) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return HaveDependencyInMethodBodyTo(types); + } + + public static ICondition HaveDependencyInMethodBodyTo(IObjectProvider objectProvider) + { + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + { + var typeList = objectProvider.GetObjects(architecture).ToList(); + var methodMemberList = methodMembers.ToList(); + var passedObjects = methodMemberList.Where(methodMember => + methodMember.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target) + .Intersect(typeList).Any()) + .ToList(); + 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); + } + + foreach (var passedObject in passedObjects) + { + yield return new ConditionResult(passedObject, true); + } + } + + var description = "have dependencies in method body to " + objectProvider.Description; + return new ArchitectureCondition(Condition, description); + } + + public static ICondition HaveDependencyInMethodBodyTo(IEnumerable types) + { + var typeList = types.ToList(); + var firstType = typeList.First(); + + IEnumerable Condition(IEnumerable methodMembers) + { + var methodMemberList = methodMembers.ToList(); + var passedObjects = methodMemberList.Where(methodMember => + methodMember.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target) + .Intersect(typeList).Any()) + .ToList(); + string failDescription; + if (typeList.IsNullOrEmpty()) + { + failDescription = "does not have dependencies in method body to one of no types (always true)"; + } + else + { + failDescription = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "does not have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + foreach (var failedObject in methodMemberList.Except(passedObjects)) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in passedObjects) + { + yield return new ConditionResult(passedObject, true); + } + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "have dependencies in method body to one of no types (always false)"; + } + else + { + description = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new EnumerableCondition(Condition, description); + } + + public static ICondition HaveDependencyInMethodBodyTo(IEnumerable types) + { + var typeList = types.ToList(); + var firstType = typeList.First(); + + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + { + var iTypeList = typeList.Select(architecture.GetITypeOfType).ToList(); + var methodMemberList = methodMembers.ToList(); + var passedObjects = methodMemberList.Where(methodMember => + methodMember.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target) + .Intersect(iTypeList).Any()) + .ToList(); + string failDescription; + if (typeList.IsNullOrEmpty()) + { + failDescription = "does not have dependencies in method body to one of no types (always true)"; + } + else + { + failDescription = typeList.Where(type => type != firstType).Distinct().Aggregate( + "does not have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + foreach (var failedObject in methodMemberList.Except(passedObjects)) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in passedObjects) + { + yield return new ConditionResult(passedObject, true); + } + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "have dependencies in method body to one of no types (always false)"; + } + else + { + description = typeList.Where(type => type != firstType).Distinct().Aggregate( + "have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new ArchitectureCondition(Condition, description); + } + //Negations @@ -86,6 +437,178 @@ ConditionResult Condition(MethodMember member) pattern + "\""); } + public static ICondition NotBeCalledBy(IEnumerable patterns, + bool useRegularExpressions = false) + { + var patternList = patterns.ToList(); + + bool Condition(MethodMember ruleType) + { + return !patternList.Any(pattern => ruleType.IsCalledBy(pattern, useRegularExpressions)); + } + + string description; + string failDescription; + if (patternList.IsNullOrEmpty()) + { + description = "not be called by one of no types (always true)"; + failDescription = "is called by one of no types (always false)"; + } + else + { + var firstPattern = patternList.First(); + description = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "not be called by types with full name " + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", + (current, pattern) => current + " or \"" + pattern + "\""); + failDescription = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "is called by types with full name " + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", + (current, pattern) => current + " or \"" + pattern + "\""); + } + + + return new SimpleCondition(Condition, description, failDescription); + } + + 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) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return NotBeCalledBy(types); + } + + public static ICondition NotBeCalledBy(IObjectProvider objectProvider) + { + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + { + var typeList = objectProvider.GetObjects(architecture).ToList(); + var methodMemberList = methodMembers.ToList(); + var failedObjects = methodMemberList + .Where(methodMember => methodMember.GetCallingTypes().Intersect(typeList).Any()) + .ToList(); + var failDescription = "is called by " + objectProvider.Description; + foreach (var failedObject in failedObjects) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in methodMemberList.Except(failedObjects)) + { + yield return new ConditionResult(passedObject, true); + } + } + + var description = "not be called by " + objectProvider.Description; + return new ArchitectureCondition(Condition, description); + } + + public static ICondition NotBeCalledBy(IEnumerable types) + { + var typeList = types.ToList(); + var firstType = typeList.First(); + + IEnumerable Condition(IEnumerable methodMembers) + { + var methodMemberList = methodMembers.ToList(); + var failedObjects = methodMemberList + .Where(methodMember => methodMember.GetCallingTypes().Intersect(typeList).Any()) + .ToList(); + string failDescription; + if (typeList.IsNullOrEmpty()) + { + failDescription = "is called by one of no types (always false)"; + } + else + { + failDescription = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "is called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + foreach (var failedObject in failedObjects) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in methodMemberList.Except(failedObjects)) + { + yield return new ConditionResult(passedObject, true); + } + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "not be called by one of no types (always true)"; + } + else + { + description = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "not be called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new EnumerableCondition(Condition, description); + } + + public static ICondition NotBeCalledBy(IEnumerable types) + { + var typeList = types.ToList(); + var firstType = typeList.First(); + + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + { + var iTypeList = typeList.Select(architecture.GetITypeOfType).ToList(); + var methodMemberList = methodMembers.ToList(); + var failedObjects = methodMemberList + .Where(methodMember => methodMember.GetCallingTypes().Intersect(iTypeList).Any()) + .ToList(); + string failDescription; + if (typeList.IsNullOrEmpty()) + { + failDescription = "is called by one of no types (always false)"; + } + else + { + failDescription = typeList.Where(type => type != firstType).Distinct().Aggregate( + "is called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + foreach (var failedObject in failedObjects) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in methodMemberList.Except(failedObjects)) + { + yield return new ConditionResult(passedObject, true); + } + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "not be called by one of no types (always true)"; + } + else + { + description = typeList.Where(type => type != firstType).Distinct().Aggregate( + "not be called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new ArchitectureCondition(Condition, description); + } + public static ICondition NotHaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false) { @@ -110,5 +633,184 @@ ConditionResult Condition(MethodMember member) "not have dependencies in method body to types with full name " + (useRegularExpressions ? "matching" : "containing") + " \"" + pattern + "\""); } + + public static ICondition NotHaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false) + { + var patternList = patterns.ToList(); + + bool Condition(MethodMember ruleType) + { + return !patternList.Any(pattern => + ruleType.HasDependencyInMethodBodyTo(pattern, useRegularExpressions)); + } + + string description; + string failDescription; + if (patternList.IsNullOrEmpty()) + { + description = "not have dependencies in method body to one of no types (always true)"; + failDescription = "does have dependencies in method body to one of no types (always false)"; + } + else + { + var firstPattern = patternList.First(); + description = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "not have dependencies in method body to types with full name " + + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", + (current, pattern) => current + " or \"" + pattern + "\""); + failDescription = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "does have dependencies in method body to types with full name " + + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", + (current, pattern) => current + " or \"" + pattern + "\""); + } + + + return new SimpleCondition(Condition, description, failDescription); + } + + public static ICondition NotHaveDependencyInMethodBodyTo(IType firstType, + params IType[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return NotHaveDependencyInMethodBodyTo(types); + } + + 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) + { + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + { + var typeList = objectProvider.GetObjects(architecture).ToList(); + var methodMemberList = methodMembers.ToList(); + var failedObjects = methodMemberList.Where(methodMember => + methodMember.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target) + .Intersect(typeList).Any()) + .ToList(); + var failDescription = "does have dependencies in method body to " + objectProvider.Description; + foreach (var failedObject in failedObjects) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in methodMemberList.Except(failedObjects)) + { + yield return new ConditionResult(passedObject, true); + } + } + + var description = "not have dependencies in method body to " + objectProvider.Description; + return new ArchitectureCondition(Condition, description); + } + + public static ICondition NotHaveDependencyInMethodBodyTo(IEnumerable types) + { + var typeList = types.ToList(); + var firstType = typeList.First(); + + IEnumerable Condition(IEnumerable methodMembers) + { + var methodMemberList = methodMembers.ToList(); + var passedObjects = methodMemberList.Where(methodMember => + methodMember.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target) + .Intersect(typeList).Any()) + .ToList(); + string failDescription; + if (typeList.IsNullOrEmpty()) + { + failDescription = "does not have dependencies in method body to one of no types (always true)"; + } + else + { + failDescription = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "does not have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + foreach (var failedObject in methodMemberList.Except(passedObjects)) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in passedObjects) + { + yield return new ConditionResult(passedObject, true); + } + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "have dependencies in method body to one of no types (always false)"; + } + else + { + description = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new EnumerableCondition(Condition, description); + } + + public static ICondition NotHaveDependencyInMethodBodyTo(IEnumerable types) + { + var typeList = types.ToList(); + var firstType = typeList.First(); + + IEnumerable Condition(IEnumerable methodMembers, Architecture architecture) + { + var iTypeList = typeList.Select(architecture.GetITypeOfType).ToList(); + var methodMemberList = methodMembers.ToList(); + var failedObjects = methodMemberList.Where(methodMember => + methodMember.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target) + .Intersect(iTypeList).Any()) + .ToList(); + string failDescription; + if (typeList.IsNullOrEmpty()) + { + failDescription = "does have dependencies in method body to one of no types (always false)"; + } + else + { + failDescription = typeList.Where(type => type != firstType).Distinct().Aggregate( + "does have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + foreach (var failedObject in failedObjects) + { + yield return new ConditionResult(failedObject, false, failDescription); + } + + foreach (var passedObject in methodMemberList.Except(failedObjects)) + { + yield return new ConditionResult(passedObject, true); + } + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "not have dependencies in method body to one of no types (always true)"; + } + else + { + description = typeList.Where(type => type != firstType).Distinct().Aggregate( + "not have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new ArchitectureCondition(Condition, description); + } } } \ No newline at end of file diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberPredicatesDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberPredicatesDefinition.cs index 5c1e32e5c..a4c395cc4 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberPredicatesDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMemberPredicatesDefinition.cs @@ -4,6 +4,9 @@ // // SPDX-License-Identifier: Apache-2.0 +using System; +using System.Collections.Generic; +using System.Linq; using ArchUnitNET.Domain; using ArchUnitNET.Fluent.Extensions; using ArchUnitNET.Fluent.Predicates; @@ -30,6 +33,109 @@ public static IPredicate AreCalledBy(string pattern, bool useRegul pattern + "\""); } + public static IPredicate AreCalledBy(IEnumerable patterns, + bool useRegularExpressions = false) + { + var patternList = patterns.ToList(); + + bool Condition(MethodMember ruleType) + { + return patternList.Any(pattern => ruleType.IsCalledBy(pattern, useRegularExpressions)); + } + + string description; + if (patternList.IsNullOrEmpty()) + { + description = "are called by one of no types (always false)"; + } + else + { + var firstPattern = patternList.First(); + description = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "are called by types with full name " + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", (current, pattern) => current + " or \"" + pattern + "\""); + } + + return new SimplePredicate(Condition, description); + } + + public static IPredicate AreCalledBy(IType firstType, params IType[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return AreCalledBy(types); + } + + public static IPredicate AreCalledBy(Type firstType, params Type[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return AreCalledBy(types); + } + + public static IPredicate AreCalledBy(IObjectProvider objectProvider) + { + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var types = objectProvider.GetObjects(architecture); + return ruleTypes.Where(type => type.GetCallingTypes().Intersect(types).Any()); + } + + var description = "are called by " + objectProvider.Description; + return new ArchitecturePredicate(Condition, description); + } + + public static IPredicate AreCalledBy(IEnumerable types) + { + var typeList = types.ToList(); + + IEnumerable Condition(IEnumerable ruleTypes) + { + return ruleTypes.Where(type => type.GetCallingTypes().Intersect(typeList).Any()); + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "are called by one of no types (always false)"; + } + else + { + var firstType = typeList.First(); + description = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "are called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new EnumerablePredicate(Condition, description); + } + + public static IPredicate AreCalledBy(IEnumerable types) + { + var typeList = types.ToList(); + + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var iTypeList = typeList.Select(architecture.GetITypeOfType); + return ruleTypes.Where(type => type.GetCallingTypes().Intersect(iTypeList).Any()); + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "are called by one of no types (always false)"; + } + else + { + var firstType = typeList.First(); + description = typeList.Where(type => type != firstType).Distinct().Aggregate( + "are called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new ArchitecturePredicate(Condition, description); + } + public static IPredicate HaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false) { @@ -39,6 +145,116 @@ public static IPredicate HaveDependencyInMethodBodyTo(string patte (useRegularExpressions ? "matching" : "containing") + " \"" + pattern + "\""); } + public static IPredicate HaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false) + { + var patternList = patterns.ToList(); + + bool Condition(MethodMember ruleType) + { + return patternList.Any(pattern => ruleType.HasDependencyInMethodBodyTo(pattern, useRegularExpressions)); + } + + string description; + if (patternList.IsNullOrEmpty()) + { + description = "have dependencies in method body to one of no types (always false)"; + } + else + { + var firstPattern = patternList.First(); + description = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "have dependencies in method body to types with full name " + + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", (current, pattern) => current + " or \"" + pattern + "\""); + } + + return new SimplePredicate(Condition, description); + } + + public static IPredicate HaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return HaveDependencyInMethodBodyTo(types); + } + + public static IPredicate HaveDependencyInMethodBodyTo(Type firstType, params Type[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return HaveDependencyInMethodBodyTo(types); + } + + public static IPredicate HaveDependencyInMethodBodyTo(IObjectProvider objectProvider) + { + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var types = objectProvider.GetObjects(architecture); + return ruleTypes.Where(type => + type.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target).Intersect(types) + .Any()); + } + + var description = "have dependencies in method body to " + objectProvider.Description; + return new ArchitecturePredicate(Condition, description); + } + + public static IPredicate HaveDependencyInMethodBodyTo(IEnumerable types) + { + var typeList = types.ToList(); + + IEnumerable Condition(IEnumerable ruleTypes) + { + return ruleTypes.Where(type => + type.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target).Intersect(types) + .Any()); + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "have dependencies in method body to one of no types (always false)"; + } + else + { + var firstType = typeList.First(); + description = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new EnumerablePredicate(Condition, description); + } + + public static IPredicate HaveDependencyInMethodBodyTo(IEnumerable types) + { + var typeList = types.ToList(); + + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var iTypeList = typeList.Select(architecture.GetITypeOfType); + return ruleTypes.Where(type => + type.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target).Intersect(iTypeList) + .Any()); + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "have dependencies in method body to one of no types (always false)"; + } + else + { + var firstType = typeList.First(); + description = typeList.Where(type => type != firstType).Distinct().Aggregate( + "have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new ArchitecturePredicate(Condition, description); + } + //Negations @@ -62,6 +278,109 @@ public static IPredicate AreNotCalledBy(string pattern, bool useRe pattern + "\""); } + public static IPredicate AreNotCalledBy(IEnumerable patterns, + bool useRegularExpressions = false) + { + var patternList = patterns.ToList(); + + bool Condition(MethodMember ruleType) + { + return !patternList.Any(pattern => ruleType.IsCalledBy(pattern, useRegularExpressions)); + } + + string description; + if (patternList.IsNullOrEmpty()) + { + description = "are not called by one of no types (always true)"; + } + else + { + var firstPattern = patternList.First(); + description = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "are not called by types with full name " + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", (current, pattern) => current + " or \"" + pattern + "\""); + } + + return new SimplePredicate(Condition, description); + } + + public static IPredicate AreNotCalledBy(IType firstType, params IType[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return AreNotCalledBy(types); + } + + public static IPredicate AreNotCalledBy(Type firstType, params Type[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return AreNotCalledBy(types); + } + + public static IPredicate AreNotCalledBy(IObjectProvider objectProvider) + { + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var types = objectProvider.GetObjects(architecture); + return ruleTypes.Where(type => !type.GetCallingTypes().Intersect(types).Any()); + } + + var description = "are not called by " + objectProvider.Description; + return new ArchitecturePredicate(Condition, description); + } + + public static IPredicate AreNotCalledBy(IEnumerable types) + { + var typeList = types.ToList(); + + IEnumerable Condition(IEnumerable ruleTypes) + { + return ruleTypes.Where(type => !type.GetCallingTypes().Intersect(typeList).Any()); + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "are not called by one of no types (always true)"; + } + else + { + var firstType = typeList.First(); + description = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "are not called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new EnumerablePredicate(Condition, description); + } + + public static IPredicate AreNotCalledBy(IEnumerable types) + { + var typeList = types.ToList(); + + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var iTypeList = typeList.Select(architecture.GetITypeOfType); + return ruleTypes.Where(type => !type.GetCallingTypes().Intersect(iTypeList).Any()); + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "are not called by one of no types (always false)"; + } + else + { + var firstType = typeList.First(); + description = typeList.Where(type => type != firstType).Distinct().Aggregate( + "are not called by \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new ArchitecturePredicate(Condition, description); + } + public static IPredicate DoNotHaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false) { @@ -70,5 +389,118 @@ public static IPredicate DoNotHaveDependencyInMethodBodyTo(string "do not have dependencies in method body to types with full name " + (useRegularExpressions ? "matching" : "containing") + " \"" + pattern + "\""); } + + public static IPredicate DoNotHaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false) + { + var patternList = patterns.ToList(); + + bool Condition(MethodMember ruleType) + { + return !patternList.Any(pattern => + ruleType.HasDependencyInMethodBodyTo(pattern, useRegularExpressions)); + } + + string description; + if (patternList.IsNullOrEmpty()) + { + description = "do not have dependencies in method body to one of no types (always true)"; + } + else + { + var firstPattern = patternList.First(); + description = patternList.Where(type => !type.Equals(firstPattern)).Distinct().Aggregate( + "do not have dependencies in method body to types with full name " + + (useRegularExpressions ? "matching" : "containing") + + " \"" + firstPattern + "\"", (current, pattern) => current + " or \"" + pattern + "\""); + } + + return new SimplePredicate(Condition, description); + } + + public static IPredicate DoNotHaveDependencyInMethodBodyTo(IType firstType, + params IType[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return DoNotHaveDependencyInMethodBodyTo(types); + } + + public static IPredicate DoNotHaveDependencyInMethodBodyTo(Type firstType, + params Type[] moreTypes) + { + var types = new List {firstType}; + types.AddRange(moreTypes); + return DoNotHaveDependencyInMethodBodyTo(types); + } + + public static IPredicate DoNotHaveDependencyInMethodBodyTo(IObjectProvider objectProvider) + { + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var types = objectProvider.GetObjects(architecture); + return ruleTypes.Where(type => + !type.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target).Intersect(types) + .Any()); + } + + var description = "do not have dependencies in method body to " + objectProvider.Description; + return new ArchitecturePredicate(Condition, description); + } + + public static IPredicate DoNotHaveDependencyInMethodBodyTo(IEnumerable types) + { + var typeList = types.ToList(); + + IEnumerable Condition(IEnumerable ruleTypes) + { + return ruleTypes.Where(type => + !type.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target).Intersect(types) + .Any()); + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "do not have dependencies in method body to one of no types (always true)"; + } + else + { + var firstType = typeList.First(); + description = typeList.Where(type => !type.Equals(firstType)).Distinct().Aggregate( + "do not have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new EnumerablePredicate(Condition, description); + } + + public static IPredicate DoNotHaveDependencyInMethodBodyTo(IEnumerable types) + { + var typeList = types.ToList(); + + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var iTypeList = typeList.Select(architecture.GetITypeOfType); + return ruleTypes.Where(type => + !type.GetBodyTypeMemberDependencies().Select(dependency => dependency.Target).Intersect(iTypeList) + .Any()); + } + + string description; + if (typeList.IsNullOrEmpty()) + { + description = "do not have dependencies in method body to one of no types (always true)"; + } + else + { + var firstType = typeList.First(); + description = typeList.Where(type => type != firstType).Distinct().Aggregate( + "do not have dependencies in method body to \"" + firstType.FullName + "\"", + (current, type) => current + " or \"" + type.FullName + "\""); + } + + return new ArchitecturePredicate(Condition, description); + } } } \ No newline at end of file diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs index 1e5bcb123..6e176ab0b 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/MethodMembersShould.cs @@ -4,6 +4,8 @@ // // SPDX-License-Identifier: Apache-2.0 +using System; +using System.Collections.Generic; using ArchUnitNET.Domain; namespace ArchUnitNET.Fluent.Syntax.Elements.Members.MethodMembers @@ -33,6 +35,43 @@ public MethodMembersShouldConjunction BeCalledBy(string pattern, bool useRegular return new MethodMembersShouldConjunction(_ruleCreator); } + public MethodMembersShouldConjunction BeCalledBy(IEnumerable patterns, + bool useRegularExpressions = false) + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.BeCalledBy(patterns, useRegularExpressions)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction BeCalledBy(IType firstType, params IType[] moreTypes) + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.BeCalledBy(firstType, moreTypes)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction BeCalledBy(Type type, params Type[] moreTypes) + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.BeCalledBy(type, moreTypes)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction BeCalledBy(IObjectProvider types) + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.BeCalledBy(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction BeCalledBy(IEnumerable types) + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.BeCalledBy(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction BeCalledBy(IEnumerable types) + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.BeCalledBy(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false) { @@ -41,6 +80,48 @@ public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(string patter return new MethodMembersShouldConjunction(_ruleCreator); } + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(patterns, useRegularExpressions)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(firstType, moreTypes)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(type, moreTypes)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IObjectProvider types) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction HaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.HaveDependencyInMethodBodyTo(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } //Negations @@ -63,6 +144,43 @@ public MethodMembersShouldConjunction NotBeCalledBy(string pattern, bool useRegu return new MethodMembersShouldConjunction(_ruleCreator); } + public MethodMembersShouldConjunction NotBeCalledBy(IEnumerable patterns, + bool useRegularExpressions = false) + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotBeCalledBy(patterns, useRegularExpressions)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction NotBeCalledBy(IType firstType, params IType[] 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)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction NotBeCalledBy(IObjectProvider types) + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotBeCalledBy(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction NotBeCalledBy(IEnumerable types) + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotBeCalledBy(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction NotBeCalledBy(IEnumerable types) + { + _ruleCreator.AddCondition(MethodMemberConditionsDefinition.NotBeCalledBy(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false) { @@ -70,5 +188,48 @@ public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(string pat MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(pattern, useRegularExpressions)); return new MethodMembersShouldConjunction(_ruleCreator); } + + public MethodMembersShouldConjunction + NotHaveDependencyInMethodBodyTo(IEnumerable patterns, bool useRegularExpressions = false) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(patterns, useRegularExpressions)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(firstType, moreTypes)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(type, moreTypes)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IObjectProvider types) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } + + public MethodMembersShouldConjunction NotHaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.AddCondition( + MethodMemberConditionsDefinition.NotHaveDependencyInMethodBodyTo(types)); + return new MethodMembersShouldConjunction(_ruleCreator); + } } } \ No newline at end of file diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/ShouldRelateToMethodMembersThat.cs b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/ShouldRelateToMethodMembersThat.cs index b12da15d6..25ff1dbd0 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/ShouldRelateToMethodMembersThat.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Members/MethodMembers/ShouldRelateToMethodMembersThat.cs @@ -4,6 +4,8 @@ // // SPDX-License-Identifier: Apache-2.0 +using System; +using System.Collections.Generic; using ArchUnitNET.Domain; using static ArchUnitNET.Fluent.Syntax.ConjunctionFactory; @@ -38,6 +40,48 @@ public TRuleTypeShouldConjunction AreCalledBy(string pattern, bool useRegularExp return Create(_ruleCreator); } + public TRuleTypeShouldConjunction AreCalledBy(IEnumerable patterns, bool useRegularExpressions = false) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreCalledBy(patterns, useRegularExpressions)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction AreCalledBy(IType firstType, params IType[] moreTypes) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreCalledBy(firstType, moreTypes)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction AreCalledBy(Type type, params Type[] moreTypes) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreCalledBy(type, moreTypes)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction AreCalledBy(IObjectProvider types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreCalledBy(types)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction AreCalledBy(IEnumerable types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreCalledBy(types)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction AreCalledBy(IEnumerable types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreCalledBy(types)); + return Create(_ruleCreator); + } + public TRuleTypeShouldConjunction HaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false) { @@ -46,6 +90,49 @@ public TRuleTypeShouldConjunction HaveDependencyInMethodBodyTo(string pattern, return Create(_ruleCreator); } + public TRuleTypeShouldConjunction HaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(patterns, useRegularExpressions)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(firstType, moreTypes)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(type, moreTypes)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveDependencyInMethodBodyTo(IObjectProvider types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(types)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(types)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.HaveDependencyInMethodBodyTo(types)); + return Create(_ruleCreator); + } + //Negations @@ -69,6 +156,49 @@ public TRuleTypeShouldConjunction AreNotCalledBy(string pattern, bool useRegular return Create(_ruleCreator); } + public TRuleTypeShouldConjunction AreNotCalledBy(IEnumerable patterns, + bool useRegularExpressions = false) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreNotCalledBy(patterns, useRegularExpressions)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction AreNotCalledBy(IType firstType, params IType[] moreTypes) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreNotCalledBy(firstType, moreTypes)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction AreNotCalledBy(Type type, params Type[] moreTypes) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreNotCalledBy(type, moreTypes)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction AreNotCalledBy(IObjectProvider types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreNotCalledBy(types)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction AreNotCalledBy(IEnumerable types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreNotCalledBy(types)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction AreNotCalledBy(IEnumerable types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.AreNotCalledBy(types)); + return Create(_ruleCreator); + } + public TRuleTypeShouldConjunction DoNotHaveDependencyInMethodBodyTo(string pattern, bool useRegularExpressions = false) { @@ -76,5 +206,48 @@ public TRuleTypeShouldConjunction DoNotHaveDependencyInMethodBodyTo(string patte MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(pattern, useRegularExpressions)); return Create(_ruleCreator); } + + public TRuleTypeShouldConjunction DoNotHaveDependencyInMethodBodyTo(IEnumerable patterns, + bool useRegularExpressions = false) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(patterns, useRegularExpressions)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveDependencyInMethodBodyTo(IType firstType, params IType[] moreTypes) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(firstType, moreTypes)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveDependencyInMethodBodyTo(Type type, params Type[] moreTypes) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(type, moreTypes)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveDependencyInMethodBodyTo(IObjectProvider types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(types)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(types)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveDependencyInMethodBodyTo(IEnumerable types) + { + _ruleCreator.ContinueComplexCondition( + MethodMemberPredicatesDefinition.DoNotHaveDependencyInMethodBodyTo(types)); + return Create(_ruleCreator); + } } } \ No newline at end of file diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/GivenTypesThat.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/GivenTypesThat.cs index 0919e135a..24edea097 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/GivenTypesThat.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/GivenTypesThat.cs @@ -86,6 +86,20 @@ public TGivenRuleTypeConjunction ImplementInterface(string pattern, bool useRegu return Create(_ruleCreator); } + public TGivenRuleTypeConjunction ImplementInterface(Interface intf) + { + _ruleCreator.AddPredicate( + TypePredicatesDefinition.ImplementInterface(intf)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction ImplementInterface(Type intf) + { + _ruleCreator.AddPredicate( + TypePredicatesDefinition.ImplementInterface(intf)); + return Create(_ruleCreator); + } + public TGivenRuleTypeConjunction ResideInNamespace(string pattern, bool useRegularExpressions = false) { _ruleCreator.AddPredicate( @@ -205,6 +219,20 @@ public TGivenRuleTypeConjunction DoNotImplementInterface(string pattern, bool us return Create(_ruleCreator); } + public TGivenRuleTypeConjunction DoNotImplementInterface(Interface intf) + { + _ruleCreator.AddPredicate( + TypePredicatesDefinition.DoNotImplementInterface(intf)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotImplementInterface(Type intf) + { + _ruleCreator.AddPredicate( + TypePredicatesDefinition.DoNotImplementInterface(intf)); + return Create(_ruleCreator); + } + public TGivenRuleTypeConjunction DoNotResideInNamespace(string pattern, bool useRegularExpressions = false) { _ruleCreator.AddPredicate( diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/ITypeConditions.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/ITypeConditions.cs index 3bda490ad..3a205a7e4 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/ITypeConditions.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/ITypeConditions.cs @@ -23,6 +23,8 @@ public interface ITypeConditions : IObjectConditions types); TReturnType BeAssignableTo(IEnumerable types); TReturnType ImplementInterface(string pattern, bool useRegularExpressions = false); + TReturnType ImplementInterface(Interface intf); + TReturnType ImplementInterface(Type intf); TReturnType ResideInNamespace(string pattern, bool useRegularExpressions = false); TReturnType ResideInAssembly(string pattern, bool useRegularExpressions = false); TReturnType ResideInAssembly(Assembly assembly, params Assembly[] moreAssemblies); @@ -46,6 +48,8 @@ public interface ITypeConditions : IObjectConditions types); TReturnType NotBeAssignableTo(IEnumerable types); TReturnType NotImplementInterface(string pattern, bool useRegularExpressions = false); + TReturnType NotImplementInterface(Interface intf); + TReturnType NotImplementInterface(Type intf); TReturnType NotResideInNamespace(string pattern, bool useRegularExpressions = false); TReturnType NotResideInAssembly(string pattern, bool useRegularExpressions = false); TReturnType NotResideInAssembly(Assembly assembly, params Assembly[] moreAssemblies); diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/ITypePredicates.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/ITypePredicates.cs index 68715182f..eaa783313 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/ITypePredicates.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/ITypePredicates.cs @@ -23,6 +23,8 @@ public interface ITypePredicates : IObjectPredicates types); TReturnType AreAssignableTo(IEnumerable types); TReturnType ImplementInterface(string pattern, bool useRegularExpressions = false); + TReturnType ImplementInterface(Interface intf); + TReturnType ImplementInterface(Type intf); TReturnType ResideInNamespace(string pattern, bool useRegularExpressions = false); TReturnType ResideInAssembly(string pattern, bool useRegularExpressions = false); TReturnType ResideInAssembly(Assembly assembly, params Assembly[] moreAssemblies); @@ -46,6 +48,8 @@ public interface ITypePredicates : IObjectPredicates types); TReturnType AreNotAssignableTo(IEnumerable types); TReturnType DoNotImplementInterface(string pattern, bool useRegularExpressions = false); + TReturnType DoNotImplementInterface(Interface intf); + TReturnType DoNotImplementInterface(Type intf); TReturnType DoNotResideInNamespace(string pattern, bool useRegularExpressions = false); TReturnType DoNotResideInAssembly(string pattern, bool useRegularExpressions = false); TReturnType DoNotResideInAssembly(Assembly assembly, params Assembly[] moreAssemblies); diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/ShouldRelateToTypesThat.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/ShouldRelateToTypesThat.cs index 98908d64f..5fc496146 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/ShouldRelateToTypesThat.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/ShouldRelateToTypesThat.cs @@ -89,6 +89,20 @@ public TRuleTypeShouldConjunction ImplementInterface(string pattern, bool useReg return Create(_ruleCreator); } + public TRuleTypeShouldConjunction ImplementInterface(Interface intf) + { + _ruleCreator.ContinueComplexCondition( + TypePredicatesDefinition.ImplementInterface(intf)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction ImplementInterface(Type intf) + { + _ruleCreator.ContinueComplexCondition( + TypePredicatesDefinition.ImplementInterface(intf)); + return Create(_ruleCreator); + } + public TRuleTypeShouldConjunction ResideInNamespace(string pattern, bool useRegularExpressions = false) { @@ -215,6 +229,20 @@ public TRuleTypeShouldConjunction DoNotImplementInterface(string pattern, bool u return Create(_ruleCreator); } + public TRuleTypeShouldConjunction DoNotImplementInterface(Interface intf) + { + _ruleCreator.ContinueComplexCondition( + TypePredicatesDefinition.DoNotImplementInterface(intf)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotImplementInterface(Type intf) + { + _ruleCreator.ContinueComplexCondition( + TypePredicatesDefinition.DoNotImplementInterface(intf)); + return Create(_ruleCreator); + } + public TRuleTypeShouldConjunction DoNotResideInNamespace(string pattern, bool useRegularExpressions = false) { _ruleCreator.ContinueComplexCondition( diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs index 0290305e0..ef2766b9a 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs @@ -247,6 +247,37 @@ public static ICondition ImplementInterface(string pattern, bool useR " \"" + pattern + "\""); } + public static ICondition ImplementInterface(Interface intf) + { + return new SimpleCondition( + type => type.ImplementsInterface(intf), + "implement interface \"" + intf.FullName + "\"", + "does not implement interface \"" + intf.FullName + "\""); + } + + public static ICondition ImplementInterface(Type intf) + { + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var ruleTypeList = ruleTypes.ToList(); + var interf = architecture.GetInterfaceOfType(intf); + var passedObjects = ruleTypeList.Where(type => type.ImplementsInterface(interf)).ToList(); + + foreach (var failedObject in ruleTypeList.Except(passedObjects)) + { + yield return new ConditionResult(failedObject, false, + "does not implement interface \"" + intf.FullName + "\""); + } + + foreach (var passedObject in passedObjects) + { + yield return new ConditionResult(passedObject, true); + } + } + + return new ArchitectureCondition(Condition, "implement interface \"" + intf.FullName + "\""); + } + public static ICondition ResideInNamespace(string pattern, bool useRegularExpressions = false) { return new SimpleCondition( @@ -590,6 +621,37 @@ public static ICondition NotImplementInterface(string pattern, bool u " \"" + pattern + "\""); } + public static ICondition NotImplementInterface(Interface intf) + { + return new SimpleCondition( + type => !type.ImplementsInterface(intf), + "not implement interface \"" + intf.FullName + "\"", + "does implement interface \"" + intf.FullName + "\""); + } + + public static ICondition NotImplementInterface(Type intf) + { + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var ruleTypeList = ruleTypes.ToList(); + var interf = architecture.GetInterfaceOfType(intf); + var passedObjects = ruleTypeList.Where(type => !type.ImplementsInterface(interf)).ToList(); + + foreach (var failedObject in ruleTypeList.Except(passedObjects)) + { + yield return new ConditionResult(failedObject, false, + "does implement interface \"" + intf.FullName + "\""); + } + + foreach (var passedObject in passedObjects) + { + yield return new ConditionResult(passedObject, true); + } + } + + return new ArchitectureCondition(Condition, "not implement interface \"" + intf.FullName + "\""); + } + public static ICondition NotResideInNamespace(string pattern, bool useRegularExpressions = false) { return new SimpleCondition( diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/TypePredicatesDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/TypePredicatesDefinition.cs index 7d3eb3414..3f2937146 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/TypePredicatesDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/TypePredicatesDefinition.cs @@ -183,6 +183,24 @@ public static IPredicate ImplementInterface(string pattern, bool useRegularEx pattern + "\""); } + public static IPredicate ImplementInterface(Interface intf) + { + return new SimplePredicate(type => type.ImplementsInterface(intf), + "implement interface \"" + intf.FullName + "\""); + } + + public static IPredicate ImplementInterface(Type intf) + { + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var interf = architecture.GetInterfaceOfType(intf); + return ruleTypes.Where(type => type.ImplementsInterface(interf)); + } + + return new ArchitecturePredicate(Condition, + "implement interface \"" + intf.FullName + "\""); + } + public static IPredicate ResideInNamespace(string pattern, bool useRegularExpressions = false) { return new SimplePredicate(type => type.ResidesInNamespace(pattern, useRegularExpressions), @@ -414,6 +432,24 @@ public static IPredicate DoNotImplementInterface(string pattern, bool useRegu " \"" + pattern + "\""); } + public static IPredicate DoNotImplementInterface(Interface intf) + { + return new SimplePredicate(type => !type.ImplementsInterface(intf), + "do not implement interface \"" + intf.FullName + "\""); + } + + public static IPredicate DoNotImplementInterface(Type intf) + { + IEnumerable Condition(IEnumerable ruleTypes, Architecture architecture) + { + var interf = architecture.GetInterfaceOfType(intf); + return ruleTypes.Where(type => !type.ImplementsInterface(interf)); + } + + return new ArchitecturePredicate(Condition, + "do not implement interface \"" + intf.FullName + "\""); + } + public static IPredicate DoNotResideInNamespace(string pattern, bool useRegularExpressions = false) { return new SimplePredicate(type => !type.ResidesInNamespace(pattern, useRegularExpressions), diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/TypesShould.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/TypesShould.cs index 21254fc55..7db45fe17 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/TypesShould.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/TypesShould.cs @@ -87,6 +87,20 @@ public TRuleTypeShouldConjunction ImplementInterface(string pattern, bool useReg return Create(_ruleCreator); } + public TRuleTypeShouldConjunction ImplementInterface(Interface intf) + { + _ruleCreator.AddCondition( + TypeConditionsDefinition.ImplementInterface(intf)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction ImplementInterface(Type intf) + { + _ruleCreator.AddCondition( + TypeConditionsDefinition.ImplementInterface(intf)); + return Create(_ruleCreator); + } + public TRuleTypeShouldConjunction ResideInNamespace(string pattern, bool useRegularExpressions = false) { _ruleCreator.AddCondition( @@ -217,6 +231,20 @@ public TRuleTypeShouldConjunction NotImplementInterface(string pattern, bool use return Create(_ruleCreator); } + public TRuleTypeShouldConjunction NotImplementInterface(Interface intf) + { + _ruleCreator.AddCondition( + TypeConditionsDefinition.NotImplementInterface(intf)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotImplementInterface(Type intf) + { + _ruleCreator.AddCondition( + TypeConditionsDefinition.NotImplementInterface(intf)); + return Create(_ruleCreator); + } + public TRuleTypeShouldConjunction NotResideInNamespace(string pattern, bool useRegularExpressions = false) { _ruleCreator.AddCondition( diff --git a/README.md b/README.md index 70fb44f99..518919c35 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ To use ArchUnitNET, install the ArchUnitNET package from NuGet: ``` PS> Install-Package ArchUnitNET ``` -If you want to use xUnit or NUnit for your unit tests, you can also install the corresponding ArchUnit extension: +If you want to use xUnit or NUnit for your unit tests, you should instead install the corresponding ArchUnit extension: ``` PS> Install-Package ArchUnitNET.xUnit PS> Install-Package ArchUnitNET.NUnit