From 40a7fca9418c4d59ff99c5aab0d27486cd3b4b45 Mon Sep 17 00:00:00 2001 From: Fritz Brandhuber Date: Wed, 28 Apr 2021 16:15:13 +0200 Subject: [PATCH 1/4] add AttributeInstance to store names and values of attribute arguments Signed-off-by: Fritz Brandhuber --- ArchUnitNET/Domain/AttributeArgument.cs | 59 +++++++ ArchUnitNET/Domain/AttributeInstance.cs | 32 ++++ ArchUnitNET/Domain/AttributeNamedArgument.cs | 50 ++++++ ArchUnitNET/Domain/Class.cs | 3 +- .../Dependencies/AttributeMemberDependency.cs | 2 +- .../Dependencies/AttributeTypeDependency.cs | 2 +- .../Domain/Extensions/AttributeExtensions.cs | 4 +- .../Domain/Extensions/MemberExtensions.cs | 2 +- .../Domain/Extensions/TypeExtensions.cs | 2 +- ArchUnitNET/Domain/FieldMember.cs | 3 +- ArchUnitNET/Domain/GenericParameter.cs | 3 +- ArchUnitNET/Domain/IHasAttributes.cs | 3 +- ArchUnitNET/Domain/Interface.cs | 4 +- ArchUnitNET/Domain/MethodMember.cs | 3 +- ArchUnitNET/Domain/PropertyMember.cs | 3 +- .../AddAttributesAndAttributeDependencies.cs | 79 ++++++--- ArchUnitNET/Loader/Type.cs | 3 +- .../Domain/AttributeArgumentTests.cs | 156 ++++++++++++++++++ .../AttributeAssertionRepository.cs | 5 +- ArchUnitNETTests/Loader/TypeTests.cs | 3 +- 20 files changed, 382 insertions(+), 39 deletions(-) create mode 100644 ArchUnitNET/Domain/AttributeArgument.cs create mode 100644 ArchUnitNET/Domain/AttributeInstance.cs create mode 100644 ArchUnitNET/Domain/AttributeNamedArgument.cs create mode 100644 ArchUnitNETTests/Domain/AttributeArgumentTests.cs diff --git a/ArchUnitNET/Domain/AttributeArgument.cs b/ArchUnitNET/Domain/AttributeArgument.cs new file mode 100644 index 000000000..6e9708dfa --- /dev/null +++ b/ArchUnitNET/Domain/AttributeArgument.cs @@ -0,0 +1,59 @@ +// Copyright 2019 Florian Gather +// Copyright 2019 Fritz Brandhuber +// Copyright 2020 Pavel Fischer +// +// SPDX-License-Identifier: Apache-2.0 +// + +using System.Collections.Generic; + +namespace ArchUnitNET.Domain +{ + public class AttributeArgument : ITypeInstance + { + private readonly ITypeInstance _typeInstance; + + public AttributeArgument(object value, ITypeInstance typeInstance) + { + Value = value; + _typeInstance = typeInstance; + } + + public readonly object Value; + + public IType Type => _typeInstance.Type; + public IEnumerable GenericArguments => _typeInstance.GenericArguments; + public bool IsArray => _typeInstance.IsArray; + public IEnumerable ArrayDimensions => _typeInstance.ArrayDimensions; + + private bool Equals(AttributeArgument other) + { + return Equals(_typeInstance, other._typeInstance) && Equals(Value, other.Value); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + return obj.GetType() == GetType() && Equals((AttributeArgument) obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = _typeInstance != null ? Type.GetHashCode() : 0; + hashCode = (hashCode * 397) ^ (Value != null ? Value.GetHashCode() : 0); + return hashCode; + } + } + } +} \ No newline at end of file diff --git a/ArchUnitNET/Domain/AttributeInstance.cs b/ArchUnitNET/Domain/AttributeInstance.cs new file mode 100644 index 000000000..46cc80c8c --- /dev/null +++ b/ArchUnitNET/Domain/AttributeInstance.cs @@ -0,0 +1,32 @@ +// Copyright 2019 Florian Gather +// Copyright 2019 Fritz Brandhuber +// Copyright 2020 Pavel Fischer +// +// SPDX-License-Identifier: Apache-2.0 +// + +using System.Collections.Generic; +using System.Linq; +using ArchUnitNET.Loader; + +namespace ArchUnitNET.Domain +{ + public class AttributeInstance : TypeInstance + { + // ReSharper disable SuggestBaseTypeForParameter + public AttributeInstance(Attribute attribute, IEnumerable attributeArguments) : + base(attribute) + { + AttributeArguments = attributeArguments; + } + + public AttributeInstance(Attribute attribute) : base(attribute) + { + AttributeArguments = Enumerable.Empty(); + } + + public IEnumerable AttributeArguments { get; } + + public bool HasAttributeArguments => AttributeArguments.Any(); + } +} \ No newline at end of file diff --git a/ArchUnitNET/Domain/AttributeNamedArgument.cs b/ArchUnitNET/Domain/AttributeNamedArgument.cs new file mode 100644 index 000000000..f87deeaec --- /dev/null +++ b/ArchUnitNET/Domain/AttributeNamedArgument.cs @@ -0,0 +1,50 @@ +// Copyright 2019 Florian Gather +// Copyright 2019 Fritz Brandhuber +// Copyright 2020 Pavel Fischer +// +// SPDX-License-Identifier: Apache-2.0 +// + +namespace ArchUnitNET.Domain +{ + public class AttributeNamedArgument : AttributeArgument + { + public AttributeNamedArgument(string name, object value, ITypeInstance typeInstance) : base(value, + typeInstance) + { + Name = name; + } + + public readonly string Name; + + private bool Equals(AttributeNamedArgument other) + { + return base.Equals(other) && Equals(Name, other.Name); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + return obj.GetType() == GetType() && Equals((AttributeNamedArgument) obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = base.GetHashCode(); + hashCode = (hashCode * 397) ^ (Name != null ? Name.GetHashCode() : 0); + return hashCode; + } + } + } +} \ No newline at end of file diff --git a/ArchUnitNET/Domain/Class.cs b/ArchUnitNET/Domain/Class.cs index 7ef4e08eb..2810b4474 100644 --- a/ArchUnitNET/Domain/Class.cs +++ b/ArchUnitNET/Domain/Class.cs @@ -77,7 +77,8 @@ public bool? IsStruct public List Dependencies => Type.Dependencies; public List BackwardsDependencies => Type.BackwardsDependencies; - public List Attributes { get; } = new List(); + public IEnumerable Attributes => AttributeInstances.Select(instance => instance.Type); + public List AttributeInstances => Type.AttributeInstances; public IEnumerable ImplementedInterfaces => Type.ImplementedInterfaces; public MemberList Members => Type.Members; diff --git a/ArchUnitNET/Domain/Dependencies/AttributeMemberDependency.cs b/ArchUnitNET/Domain/Dependencies/AttributeMemberDependency.cs index 7bcc9dcd5..587dabf45 100644 --- a/ArchUnitNET/Domain/Dependencies/AttributeMemberDependency.cs +++ b/ArchUnitNET/Domain/Dependencies/AttributeMemberDependency.cs @@ -8,7 +8,7 @@ namespace ArchUnitNET.Domain.Dependencies { public class AttributeMemberDependency : MemberTypeInstanceDependency { - public AttributeMemberDependency(IMember member, ITypeInstance attributeInstance) + public AttributeMemberDependency(IMember member, AttributeInstance attributeInstance) : base(member, attributeInstance) { } diff --git a/ArchUnitNET/Domain/Dependencies/AttributeTypeDependency.cs b/ArchUnitNET/Domain/Dependencies/AttributeTypeDependency.cs index 216abad67..718ab3b6b 100644 --- a/ArchUnitNET/Domain/Dependencies/AttributeTypeDependency.cs +++ b/ArchUnitNET/Domain/Dependencies/AttributeTypeDependency.cs @@ -8,7 +8,7 @@ namespace ArchUnitNET.Domain.Dependencies { public class AttributeTypeDependency : TypeInstanceDependency { - public AttributeTypeDependency(IType origin, ITypeInstance attributeInstance) + public AttributeTypeDependency(IType origin, AttributeInstance attributeInstance) : base(origin, attributeInstance) { } diff --git a/ArchUnitNET/Domain/Extensions/AttributeExtensions.cs b/ArchUnitNET/Domain/Extensions/AttributeExtensions.cs index cde988ae3..4091c7676 100644 --- a/ArchUnitNET/Domain/Extensions/AttributeExtensions.cs +++ b/ArchUnitNET/Domain/Extensions/AttributeExtensions.cs @@ -13,13 +13,13 @@ public static class AttributeExtensions { public static bool HasAttribute(this IHasAttributes a, string pattern, bool useRegularExpressions = false) { - return a.Attributes.Any(attribute => attribute.FullNameMatches(pattern, useRegularExpressions)); + return a.Attributes.Any(attribute => attribute.Type.FullNameMatches(pattern, useRegularExpressions)); } public static bool OnlyHasAttributes(this IHasAttributes a, string pattern, bool useRegularExpressions = false) { return a.Attributes.IsNullOrEmpty() || - a.Attributes.All(attribute => attribute.FullNameMatches(pattern, useRegularExpressions)); + a.Attributes.All(attribute => attribute.Type.FullNameMatches(pattern, useRegularExpressions)); } } } \ No newline at end of file diff --git a/ArchUnitNET/Domain/Extensions/MemberExtensions.cs b/ArchUnitNET/Domain/Extensions/MemberExtensions.cs index ceebd354c..7376e799e 100644 --- a/ArchUnitNET/Domain/Extensions/MemberExtensions.cs +++ b/ArchUnitNET/Domain/Extensions/MemberExtensions.cs @@ -74,7 +74,7 @@ public static bool HasFieldTypeDependencies(this IMember member, bool getBackwar public static Attribute GetAttributeFromMember(this IMember member, Class attributeClass) { - return member.Attributes.Find(attribute => attribute.FullName.Equals(attributeClass.FullName)); + return member.Attributes.FirstOrDefault(attribute => attribute.FullName.Equals(attributeClass.FullName)); } public static bool HasMethodSignatureDependency(this IMember member, diff --git a/ArchUnitNET/Domain/Extensions/TypeExtensions.cs b/ArchUnitNET/Domain/Extensions/TypeExtensions.cs index 3455b437d..d439c611f 100644 --- a/ArchUnitNET/Domain/Extensions/TypeExtensions.cs +++ b/ArchUnitNET/Domain/Extensions/TypeExtensions.cs @@ -118,7 +118,7 @@ public static bool HasMemberWithFullName(this IType type, string fullname) public static Attribute GetAttributeOfType(this IType type, Class attributeClass) { - return type.Attributes.Find(attribute => attribute.FullName.Equals(attributeClass.FullName)); + return type.Attributes.FirstOrDefault(attribute => attribute.FullName.Equals(attributeClass.FullName)); } public static bool ResidesInNamespace(this IType e, string pattern, bool useRegularExpressions = false) diff --git a/ArchUnitNET/Domain/FieldMember.cs b/ArchUnitNET/Domain/FieldMember.cs index ad32d9a77..14ce7306b 100644 --- a/ArchUnitNET/Domain/FieldMember.cs +++ b/ArchUnitNET/Domain/FieldMember.cs @@ -34,7 +34,8 @@ public FieldMember(IType declaringType, string name, string fullName, Visibility public bool IsCompilerGenerated { get; } public bool IsGeneric => false; public List GenericParameters => new List(); - public List Attributes { get; } = new List(); + public IEnumerable Attributes => AttributeInstances.Select(instance => instance.Type); + public List AttributeInstances { get; } = new List(); public List MemberDependencies { get; } = new List(); public List MemberBackwardsDependencies { get; } = new List(); public List Dependencies => MemberDependencies.Cast().ToList(); diff --git a/ArchUnitNET/Domain/GenericParameter.cs b/ArchUnitNET/Domain/GenericParameter.cs index 5e00f8964..3876b602d 100644 --- a/ArchUnitNET/Domain/GenericParameter.cs +++ b/ArchUnitNET/Domain/GenericParameter.cs @@ -48,7 +48,8 @@ public GenericParameter(string declarerFullName, string name, GenericParameterVa public string Name { get; } public string FullName => _declarerFullName + "+<" + Name + ">"; public bool IsCompilerGenerated { get; } - public List Attributes { get; } = new List(); + public IEnumerable Attributes => AttributeInstances.Select(instance => instance.Type); + public List AttributeInstances { get; } = new List(); public List Dependencies { get; } = new List(); public List BackwardsDependencies { get; } = new List(); diff --git a/ArchUnitNET/Domain/IHasAttributes.cs b/ArchUnitNET/Domain/IHasAttributes.cs index dee2cfc7c..0e0f4dfa2 100644 --- a/ArchUnitNET/Domain/IHasAttributes.cs +++ b/ArchUnitNET/Domain/IHasAttributes.cs @@ -10,6 +10,7 @@ namespace ArchUnitNET.Domain { public interface IHasAttributes { - List Attributes { get; } + IEnumerable Attributes { get; } + List AttributeInstances { get; } } } \ No newline at end of file diff --git a/ArchUnitNET/Domain/Interface.cs b/ArchUnitNET/Domain/Interface.cs index 3c68114f6..5e4dab49d 100644 --- a/ArchUnitNET/Domain/Interface.cs +++ b/ArchUnitNET/Domain/Interface.cs @@ -5,6 +5,7 @@ // SPDX-License-Identifier: Apache-2.0 using System.Collections.Generic; +using System.Linq; using ArchUnitNET.Domain.Dependencies; using ArchUnitNET.Domain.Extensions; @@ -31,7 +32,8 @@ public Interface(IType type) public Namespace Namespace => Type.Namespace; public Assembly Assembly => Type.Assembly; - public List Attributes { get; } = new List(); + public IEnumerable Attributes => AttributeInstances.Select(instance => instance.Type); + public List AttributeInstances => Type.AttributeInstances; public List Dependencies => Type.Dependencies; public List BackwardsDependencies => Type.BackwardsDependencies; diff --git a/ArchUnitNET/Domain/MethodMember.cs b/ArchUnitNET/Domain/MethodMember.cs index be9edc473..be8c883d4 100644 --- a/ArchUnitNET/Domain/MethodMember.cs +++ b/ArchUnitNET/Domain/MethodMember.cs @@ -43,7 +43,8 @@ public MethodMember(string name, string fullName, IType declaringType, Visibilit public bool IsGeneric { get; } public List GenericParameters { get; } = new List(); public Visibility Visibility { get; } - public List Attributes { get; } = new List(); + public IEnumerable Attributes => AttributeInstances.Select(instance => instance.Type); + public List AttributeInstances { get; } = new List(); public List MemberDependencies { get; } = new List(); public List MemberBackwardsDependencies { get; } = new List(); public List Dependencies => MemberDependencies.Cast().ToList(); diff --git a/ArchUnitNET/Domain/PropertyMember.cs b/ArchUnitNET/Domain/PropertyMember.cs index 1457da003..b4bee0b62 100644 --- a/ArchUnitNET/Domain/PropertyMember.cs +++ b/ArchUnitNET/Domain/PropertyMember.cs @@ -48,7 +48,8 @@ public PropertyMember(IType declaringType, string name, string fullName, ITypeIn public string Name { get; } public string FullName { get; } public IType DeclaringType { get; } - public List Attributes { get; } = new List(); + public IEnumerable Attributes => AttributeInstances.Select(instance => instance.Type); + public List AttributeInstances { get; } = new List(); public List MemberDependencies { diff --git a/ArchUnitNET/Loader/LoadTasks/AddAttributesAndAttributeDependencies.cs b/ArchUnitNET/Loader/LoadTasks/AddAttributesAndAttributeDependencies.cs index 6ca95ffec..db949b6a1 100644 --- a/ArchUnitNET/Loader/LoadTasks/AddAttributesAndAttributeDependencies.cs +++ b/ArchUnitNET/Loader/LoadTasks/AddAttributesAndAttributeDependencies.cs @@ -32,9 +32,10 @@ public void Execute() _typeDefinition.CustomAttributes.ForEach(AddAttributeArgumentReferenceDependenciesToOriginType); var typeAttributeInstances = CreateAttributesFromCustomAttributes(_typeDefinition.CustomAttributes).ToList(); - _type.Attributes.AddRange(typeAttributeInstances.Select(instance => instance.Type)); + _type.AttributeInstances.AddRange(typeAttributeInstances); var typeAttributeDependencies = - typeAttributeInstances.Select(attribute => new AttributeTypeDependency(_type, attribute)); + typeAttributeInstances.Select( + attributeInstance => new AttributeTypeDependency(_type, attributeInstance)); _type.Dependencies.AddRange(typeAttributeDependencies); SetUpAttributesForTypeGenericParameters(); CollectAttributesForMembers(); @@ -47,11 +48,10 @@ private void SetUpAttributesForTypeGenericParameters() var param = _type.GenericParameters.First(parameter => parameter.Name == genericParameter.Name); var attributeInstances = CreateAttributesFromCustomAttributes(genericParameter.CustomAttributes).ToList(); - var attributes = attributeInstances.Select(instance => instance.Type).ToList(); - _type.Attributes.AddRange(attributes); - param.Attributes.AddRange(attributes); - var genericParameterAttributeDependencies = attributeInstances.Select(attribute => - new AttributeTypeDependency(_type, attribute)); + _type.AttributeInstances.AddRange(attributeInstances); + param.AttributeInstances.AddRange(attributeInstances); + var genericParameterAttributeDependencies = attributeInstances.Select(attributeInstance => + new AttributeTypeDependency(_type, attributeInstance)); _type.Dependencies.AddRange(genericParameterAttributeDependencies); } } @@ -101,11 +101,10 @@ private void SetUpAttributesForMethodGenericParameters(MethodDefinition methodDe var customAttributes = genericParameter.CustomAttributes; customAttributes.ForEach(AddAttributeArgumentReferenceDependenciesToOriginType); var attributeInstances = CreateAttributesFromCustomAttributes(customAttributes).ToList(); - var attributes = attributeInstances.Select(instance => instance.Type).ToList(); - methodMember.Attributes.AddRange(attributes); - param.Attributes.AddRange(attributes); - var genericParameterAttributeDependencies = attributeInstances.Select(attribute => - new AttributeMemberDependency(methodMember, attribute)); + methodMember.AttributeInstances.AddRange(attributeInstances); + param.AttributeInstances.AddRange(attributeInstances); + var genericParameterAttributeDependencies = attributeInstances.Select(attributeInstance => + new AttributeMemberDependency(methodMember, attributeInstance)); methodMember.MemberDependencies.AddRange(genericParameterAttributeDependencies); } } @@ -115,35 +114,73 @@ private void CollectMemberAttributesAndDependencies(IMember methodMember, { memberCustomAttributes.ForEach(AddAttributeArgumentReferenceDependenciesToOriginType); var memberAttributeInstances = CreateAttributesFromCustomAttributes(memberCustomAttributes).ToList(); - methodMember.Attributes.AddRange(memberAttributeInstances.Select(instance => instance.Type)); + methodMember.AttributeInstances.AddRange(memberAttributeInstances); var methodAttributeDependencies = CreateMemberAttributeDependencies(methodMember, memberAttributeInstances); attributeDependencies.AddRange(methodAttributeDependencies); } [NotNull] - private IEnumerable> CreateAttributesFromCustomAttributes( + private IEnumerable CreateAttributesFromCustomAttributes( IEnumerable customAttributes) { return customAttributes.Select(customAttribute => { var attributeTypeReference = customAttribute.AttributeType; var attributeType = _typeFactory.GetOrCreateStubTypeInstanceFromTypeReference(attributeTypeReference); - if (attributeType.Type is Class cls) + var attribute = attributeType.Type is Class cls + ? new Attribute(cls) + : new Attribute(attributeType.Type, null, null); + + var attributeArguments = new List(); + + foreach (var constructorArgument in customAttribute.ConstructorArguments) + { + HandleAttributeArgument(constructorArgument, out var value, out var type); + attributeArguments.Add(new AttributeArgument(value, type)); + } + + foreach (var namedArgument in customAttribute.Fields.Concat(customAttribute.Properties)) { - return new TypeInstance(new Attribute(cls), - attributeType.GenericArguments, attributeType.ArrayDimensions); + var name = namedArgument.Name; + HandleAttributeArgument(namedArgument.Argument, out var value, out var type); + attributeArguments.Add(new AttributeNamedArgument(name, value, type)); } - return new TypeInstance(new Attribute(attributeType.Type, null, null), - attributeType.GenericArguments, attributeType.ArrayDimensions); + return new AttributeInstance(attribute, attributeArguments); }); } + private void HandleAttributeArgument(CustomAttributeArgument argument, out object value, + out ITypeInstance type) + { + while (argument.Value is CustomAttributeArgument arg) //if would work too + { + argument = arg; + } + + type = _typeFactory.GetOrCreateStubTypeInstanceFromTypeReference(argument.Type); + + if (type.IsArray) + { + value = (from arrayMember in (CustomAttributeArgument[]) argument.Value + select arrayMember.Value is TypeReference tr + ? _typeFactory.GetOrCreateStubTypeInstanceFromTypeReference(tr) + : arrayMember.Value) + .ToArray(); + } + else + { + value = argument.Value is TypeReference tr + ? _typeFactory.GetOrCreateStubTypeInstanceFromTypeReference(tr) + : argument.Value; + } + } + [NotNull] private static IEnumerable CreateMemberAttributeDependencies(IMember member, - IEnumerable> attributes) + IEnumerable attributes) { - return attributes.Select(attribute => new AttributeMemberDependency(member, attribute)); + return attributes.Select(attributeInstance => new AttributeMemberDependency(member, attributeInstance)); } private void AddAttributeArgumentReferenceDependenciesToOriginType(ICustomAttribute customAttribute) diff --git a/ArchUnitNET/Loader/Type.cs b/ArchUnitNET/Loader/Type.cs index 9a4f8e4f5..f54ce83fa 100644 --- a/ArchUnitNET/Loader/Type.cs +++ b/ArchUnitNET/Loader/Type.cs @@ -49,7 +49,8 @@ public Type(string fullname, string name, Assembly assembly, Namespace namespc, public bool IsStub { get; } public MemberList Members { get; } = new MemberList(); - public List Attributes { get; } = new List(); + public IEnumerable Attributes => AttributeInstances.Select(instance => instance.Type); + public List AttributeInstances { get; } = new List(); public List Dependencies { get; } = new List(); diff --git a/ArchUnitNETTests/Domain/AttributeArgumentTests.cs b/ArchUnitNETTests/Domain/AttributeArgumentTests.cs new file mode 100644 index 000000000..79f5c310f --- /dev/null +++ b/ArchUnitNETTests/Domain/AttributeArgumentTests.cs @@ -0,0 +1,156 @@ +// Copyright 2019 Florian Gather +// Copyright 2019 Fritz Brandhuber +// Copyright 2020 Pavel Fischer +// +// SPDX-License-Identifier: Apache-2.0 +// + +using System; +using System.Linq; +using ArchUnitNET.Domain; +using ArchUnitNET.Domain.Extensions; +using ArchUnitNET.Loader; +using Xunit; +using Attribute = System.Attribute; + +namespace ArchUnitNETTests.Domain +{ + public class AttributeArgumentTests + { + private static readonly Architecture Architecture = + new ArchLoader().LoadAssembly(typeof(AttributeArgumentTests).Assembly).Build(); + + private readonly Class _classWithMultipleAttributesWithParameters; + private readonly Class _classWithTypeParameterAttribute; + private readonly Class _classWithArrayParameterAttribute; + private readonly Class _classWithMixedParameterAttribute; + + private readonly ArchUnitNET.Domain.Attribute _attributeWithStringParameters; + private readonly ArchUnitNET.Domain.Attribute _attributeWithObjectParameter; + + public AttributeArgumentTests() + { + _classWithMultipleAttributesWithParameters = + Architecture.GetClassOfType(typeof(ClassWithMultipleAttributesWithParameters)); + _classWithTypeParameterAttribute = + Architecture.GetClassOfType(typeof(ClassWithTypeParameterAttribute)); + _classWithArrayParameterAttribute = + Architecture.GetClassOfType(typeof(ClassWithArrayParameterAttribute)); + _classWithMixedParameterAttribute = + Architecture.GetClassOfType(typeof(ClassWithMixedParameterAttribute)); + _attributeWithStringParameters = Architecture + .GetAttributeOfType(typeof(AttributeWithStringParameters)); + _attributeWithObjectParameter = Architecture + .GetAttributeOfType(typeof(AttributeWithObjectParameter)); + } + + [Fact] + public void AssignArrayParametersToAttributeInstance() + { + var argumentValues = _classWithArrayParameterAttribute.AttributeInstances.First().AttributeArguments + .Select(arg => (object[]) arg.Value).ToList(); + Assert.Contains(new object[] {1, 2, 3}, argumentValues); + Assert.Contains(new object[] {"a", "b", "c", "d"}, argumentValues); + Assert.Contains(new object[] { }, argumentValues); + } + + [Fact] + public void AssignTypeParametersToAttributeInstance() + { + var argumentValues = _classWithTypeParameterAttribute.AttributeInstances.First().AttributeArguments + .Select(arg => (ITypeInstance) arg.Value).Select(instance => instance.Type).ToList(); + Assert.Contains(_classWithTypeParameterAttribute, argumentValues); + Assert.Contains(_classWithArrayParameterAttribute, argumentValues); + Assert.Contains(_classWithMixedParameterAttribute, argumentValues); + } + + [Fact] + public void AssignMixedParametersToAttributeInstance() + { + var argumentValues = _classWithMixedParameterAttribute.AttributeInstances.First().AttributeArguments + .Select(arg => arg.Value).ToList(); + Assert.Contains((uint) 10, argumentValues); + Assert.Contains(true, argumentValues); + Assert.Contains("test", argumentValues); + } + + [Fact] + public void FindMultipleAttributesOfTheSameType() + { + Assert.Equal(3, + _classWithMultipleAttributesWithParameters.Attributes.Count(att => + Equals(att, _attributeWithStringParameters))); + Assert.Equal(1, + _classWithMultipleAttributesWithParameters.Attributes.Count(att => + Equals(att, _attributeWithObjectParameter))); + } + + [Fact] + public void AssignNamesToAttributeParameters() + { + var namedArguments = _classWithMultipleAttributesWithParameters.AttributeInstances + .SelectMany(instance => instance.AttributeArguments).OfType().ToList(); + Assert.Contains(namedArguments, arg => arg.Name == "Parameter2" && (string) arg.Value == "param2_1"); + Assert.Contains(namedArguments, arg => arg.Name == "Parameter3" && (string) arg.Value == "param3_2"); + } + } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + internal class AttributeWithStringParameters : Attribute + { + public AttributeWithStringParameters(string parameter1) + { + Parameter1 = parameter1; + } + + public AttributeWithStringParameters(string parameter1, string parameter2) + { + Parameter1 = parameter1; + Parameter2 = parameter2; + } + + public string Parameter1 { get; } + public string Parameter2; + public string Parameter3 { get; set; } + } + + internal class AttributeWithObjectParameter : Attribute + { + public AttributeWithObjectParameter(object type) + { + Type = type; + } + + public object Type { get; } + public object Type2; + public object Type3 { get; set; } + } + + [AttributeWithStringParameters("param1_0")] + [AttributeWithStringParameters("param1_1", Parameter2 = "param2_1")] + [AttributeWithStringParameters("param1_2", "param2_2", Parameter3 = "param3_2")] + [AttributeWithObjectParameter(1)] + internal class ClassWithMultipleAttributesWithParameters + { + } + + [AttributeWithObjectParameter(typeof(ClassWithTypeParameterAttribute), + Type2 = typeof(ClassWithArrayParameterAttribute), Type3 = typeof(ClassWithMixedParameterAttribute))] + internal class ClassWithTypeParameterAttribute + { + public ClassWithTypeParameterAttribute() + { + var a = new[] {new[] {"a", "b"}, new[] {"c", "d"}}; + } + } + + [AttributeWithObjectParameter(new[] {1, 2, 3}, Type2 = new[] {"a", "b", "c", "d"}, Type3 = new bool[] { })] + internal class ClassWithArrayParameterAttribute + { + } + + [AttributeWithObjectParameter((uint) 10, Type2 = true, Type3 = "test")] + internal class ClassWithMixedParameterAttribute + { + } +} \ No newline at end of file diff --git a/ArchUnitNETTests/Domain/Dependencies/Attributes/AttributeAssertionRepository.cs b/ArchUnitNETTests/Domain/Dependencies/Attributes/AttributeAssertionRepository.cs index bc82279fd..f680dffc1 100644 --- a/ArchUnitNETTests/Domain/Dependencies/Attributes/AttributeAssertionRepository.cs +++ b/ArchUnitNETTests/Domain/Dependencies/Attributes/AttributeAssertionRepository.cs @@ -8,7 +8,6 @@ using ArchUnitNET.Domain; using ArchUnitNET.Domain.Dependencies; using ArchUnitNET.Domain.Extensions; -using ArchUnitNET.Loader; using Xunit; using Attribute = ArchUnitNET.Domain.Attribute; @@ -83,7 +82,7 @@ public static void AttributeDependencyAsExpected(IMember targetMember, Class exp var expectedAttribute = new Attribute(expectedAttributeClass); var expectedAttributeDependency = - new AttributeMemberDependency(targetMember, new TypeInstance(expectedAttribute)); + new AttributeMemberDependency(targetMember, new AttributeInstance(expectedAttribute)); //Assert Assert.Contains(expectedAttributeDependency, targetMember.Dependencies); @@ -106,7 +105,7 @@ public static void AttributeDependencyAsExpected(IType targetType, Class expecte var expectedAttribute = new Attribute(expectedAttributeClass); var expectedAttributeDependency = - new AttributeTypeDependency(targetType, new TypeInstance(expectedAttribute)); + new AttributeTypeDependency(targetType, new AttributeInstance(expectedAttribute)); //Assert Assert.True(targetType.HasDependency(expectedAttributeDependency)); diff --git a/ArchUnitNETTests/Loader/TypeTests.cs b/ArchUnitNETTests/Loader/TypeTests.cs index 81dfeb28c..309f7749b 100644 --- a/ArchUnitNETTests/Loader/TypeTests.cs +++ b/ArchUnitNETTests/Loader/TypeTests.cs @@ -107,7 +107,8 @@ public void AccessAttributes() { //Setup, Act var attribute = new Attribute(_expectedAttributeClass); - _type.Attributes.Add(attribute); + var instance = new AttributeInstance(attribute); + _type.AttributeInstances.Add(instance); //Assert Assert.Contains(attribute, _type.Attributes); From 3af9c31a0aa870b0ced7ac9579e1f46376997301 Mon Sep 17 00:00:00 2001 From: Fritz Brandhuber Date: Mon, 12 Jul 2021 16:38:24 +0200 Subject: [PATCH 2/4] implement fluent methods for attribute arguments Signed-off-by: Fritz Brandhuber --- .../Syntax/Elements/GivenObjectsThat.cs | 207 +++ .../Syntax/Elements/IObjectConditions.cs | 28 + .../Syntax/Elements/IObjectPredicates.cs | 32 + .../Elements/ObjectConditionsDefinition.cs | 1144 ++++++++++++++++- .../Elements/ObjectPredicatesDefinition.cs | 1008 +++++++++++++++ .../Fluent/Syntax/Elements/ObjectsShould.cs | 284 +++- .../Elements/ShouldRelateToObjectsThat.cs | 240 ++++ 7 files changed, 2941 insertions(+), 2 deletions(-) diff --git a/ArchUnitNET/Fluent/Syntax/Elements/GivenObjectsThat.cs b/ArchUnitNET/Fluent/Syntax/Elements/GivenObjectsThat.cs index 130d119e6..abcc8f86c 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/GivenObjectsThat.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/GivenObjectsThat.cs @@ -279,6 +279,109 @@ public TGivenRuleTypeConjunction OnlyHaveAttributes(IEnumerable attributes return Create(_ruleCreator); } + public TGivenRuleTypeConjunction HaveAnyAttributesWithArguments(IEnumerable argumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAnyAttributesWithArguments(argumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAnyAttributesWithArguments(object firstArgumentValue, params object[] moreArgumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAnyAttributesWithArguments(firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithArguments(string attribute, IEnumerable argumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithArguments(string attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithArguments(Attribute attribute, IEnumerable argumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithArguments(Type attribute, IEnumerable argumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithArguments(Type attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAnyAttributesWithNamedArguments(IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAnyAttributesWithNamedArguments(attributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAnyAttributesWithNamedArguments((string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAnyAttributesWithNamedArguments(firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithNamedArguments(string attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithNamedArguments(string attribute, (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithNamedArguments(Attribute attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithNamedArguments(Attribute attribute, (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithNamedArguments(Type attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction HaveAttributeWithNamedArguments(Type attribute, (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + public TGivenRuleTypeConjunction HaveName(string name) { _ruleCreator.AddPredicate(ObjectPredicatesDefinition.HaveName(name)); @@ -525,6 +628,110 @@ public TGivenRuleTypeConjunction DoNotHaveAnyAttributes(IEnumerable attrib return Create(_ruleCreator); } + public TGivenRuleTypeConjunction DoNotHaveAnyAttributesWithArguments(IEnumerable argumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAnyAttributesWithArguments(argumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAnyAttributesWithArguments(object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAnyAttributesWithArguments(firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithArguments(string attribute, IEnumerable argumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithArguments(string attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithNamedArguments(string attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithNamedArguments(string attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithArguments(Attribute attribute, IEnumerable argumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithArguments(Type attribute, IEnumerable argumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithArguments(Type attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAnyAttributesWithNamedArguments(IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAnyAttributesWithNamedArguments(attributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAnyAttributesWithNamedArguments((string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAnyAttributesWithNamedArguments(firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithNamedArguments(Attribute attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithNamedArguments(Attribute attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithNamedArguments(Type attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TGivenRuleTypeConjunction DoNotHaveAttributeWithNamedArguments(Type attribute, (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + public TGivenRuleTypeConjunction DoNotHaveName(string name) { _ruleCreator.AddPredicate(ObjectPredicatesDefinition.DoNotHaveName(name)); diff --git a/ArchUnitNET/Fluent/Syntax/Elements/IObjectConditions.cs b/ArchUnitNET/Fluent/Syntax/Elements/IObjectConditions.cs index 1ba5d0a9c..36b0d3c8b 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/IObjectConditions.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/IObjectConditions.cs @@ -56,6 +56,22 @@ public interface IObjectConditions where TRuleTy TReturnType OnlyHaveAttributes(IObjectProvider attributes); TReturnType OnlyHaveAttributes(IEnumerable attributes); TReturnType OnlyHaveAttributes(IEnumerable attributes); + TReturnType HaveAnyAttributesWithArguments(IEnumerable argumentValues); + TReturnType HaveAnyAttributesWithArguments(object firstArgumentValue, params object[] moreArgumentValues); + TReturnType HaveAttributeWithArguments(string attribute, IEnumerable argumentValues); + TReturnType HaveAttributeWithArguments(string attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType HaveAttributeWithArguments(Attribute attribute, IEnumerable argumentValues); + TReturnType HaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType HaveAttributeWithArguments(Type attribute, IEnumerable argumentValues); + TReturnType HaveAttributeWithArguments(Type attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType HaveAnyAttributesWithNamedArguments(IEnumerable<(string,object)> attributeArguments); + TReturnType HaveAnyAttributesWithNamedArguments((string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType HaveAttributeWithNamedArguments(string attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType HaveAttributeWithNamedArguments(string attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType HaveAttributeWithNamedArguments(Attribute attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType HaveAttributeWithNamedArguments(Attribute attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType HaveAttributeWithNamedArguments(Type attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType HaveAttributeWithNamedArguments(Type attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); TReturnType HaveName(string name); TReturnType HaveNameMatching(string pattern); TReturnType HaveFullName(string fullname); @@ -100,6 +116,18 @@ public interface IObjectConditions where TRuleTy TReturnType NotHaveAnyAttributes(IObjectProvider attributes); TReturnType NotHaveAnyAttributes(IEnumerable attributes); TReturnType NotHaveAnyAttributes(IEnumerable attributes); + TReturnType NotHaveAnyAttributesWithArguments(IEnumerable argumentValues); + TReturnType NotHaveAnyAttributesWithArguments(object firstArgumentValue, params object[] moreArgumentValues); + TReturnType NotHaveAttributeWithArguments(Attribute attribute, IEnumerable argumentValues); + TReturnType NotHaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType NotHaveAttributeWithArguments(Type attribute, IEnumerable argumentValues); + TReturnType NotHaveAttributeWithArguments(Type attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType NotHaveAnyAttributesWithNamedArguments(IEnumerable<(string,object)> attributeArguments); + TReturnType NotHaveAnyAttributesWithNamedArguments((string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType NotHaveAttributeWithNamedArguments(Attribute attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType NotHaveAttributeWithNamedArguments(Attribute attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType NotHaveAttributeWithNamedArguments(Type attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType NotHaveAttributeWithNamedArguments(Type attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); TReturnType NotHaveName(string name); TReturnType NotHaveNameMatching(string pattern); TReturnType NotHaveFullName(string fullname); diff --git a/ArchUnitNET/Fluent/Syntax/Elements/IObjectPredicates.cs b/ArchUnitNET/Fluent/Syntax/Elements/IObjectPredicates.cs index 02e437388..a305ee81e 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/IObjectPredicates.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/IObjectPredicates.cs @@ -54,6 +54,22 @@ public interface IObjectPredicates where TRuleType : TReturnType OnlyHaveAttributes(IObjectProvider attributes); TReturnType OnlyHaveAttributes(IEnumerable attributes); TReturnType OnlyHaveAttributes(IEnumerable attributes); + TReturnType HaveAnyAttributesWithArguments(IEnumerable argumentValues); + TReturnType HaveAnyAttributesWithArguments(object firstArgumentValue, params object[] moreArgumentValues); + TReturnType HaveAttributeWithArguments(string attribute, IEnumerable argumentValues); + TReturnType HaveAttributeWithArguments(string attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType HaveAttributeWithArguments(Attribute attribute, IEnumerable argumentValues); + TReturnType HaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType HaveAttributeWithArguments(Type attribute, IEnumerable argumentValues); + TReturnType HaveAttributeWithArguments(Type attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType HaveAnyAttributesWithNamedArguments(IEnumerable<(string,object)> attributeArguments); + TReturnType HaveAnyAttributesWithNamedArguments((string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType HaveAttributeWithNamedArguments(string attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType HaveAttributeWithNamedArguments(string attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType HaveAttributeWithNamedArguments(Attribute attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType HaveAttributeWithNamedArguments(Attribute attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType HaveAttributeWithNamedArguments(Type attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType HaveAttributeWithNamedArguments(Type attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); TReturnType HaveName(string name); TReturnType HaveNameMatching(string pattern); TReturnType HaveFullName(string fullname); @@ -97,6 +113,22 @@ public interface IObjectPredicates where TRuleType : TReturnType DoNotHaveAnyAttributes(IObjectProvider attributes); TReturnType DoNotHaveAnyAttributes(IEnumerable attributes); TReturnType DoNotHaveAnyAttributes(IEnumerable attributes); + TReturnType DoNotHaveAnyAttributesWithArguments(IEnumerable argumentValues); + TReturnType DoNotHaveAnyAttributesWithArguments(object firstArgumentValue, params object[] moreArgumentValues); + TReturnType DoNotHaveAttributeWithArguments(string attribute, IEnumerable argumentValues); + TReturnType DoNotHaveAttributeWithArguments(string attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType DoNotHaveAttributeWithArguments(Attribute attribute, IEnumerable argumentValues); + TReturnType DoNotHaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType DoNotHaveAttributeWithArguments(Type attribute, IEnumerable argumentValues); + TReturnType DoNotHaveAttributeWithArguments(Type attribute, object firstArgumentValue, params object[] moreArgumentValues); + TReturnType DoNotHaveAnyAttributesWithNamedArguments(IEnumerable<(string,object)> attributeArguments); + TReturnType DoNotHaveAnyAttributesWithNamedArguments((string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType DoNotHaveAttributeWithNamedArguments(string attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType DoNotHaveAttributeWithNamedArguments(string attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType DoNotHaveAttributeWithNamedArguments(Attribute attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType DoNotHaveAttributeWithNamedArguments(Attribute attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); + TReturnType DoNotHaveAttributeWithNamedArguments(Type attribute, IEnumerable<(string,object)> attributeArguments); + TReturnType DoNotHaveAttributeWithNamedArguments(Type attribute, (string,object) firstAttributeArgument, params (string,object)[] moreAttributeArguments); TReturnType DoNotHaveName(string name); TReturnType DoNotHaveNameMatching(string pattern); TReturnType DoNotHaveFullName(string fullname); diff --git a/ArchUnitNET/Fluent/Syntax/Elements/ObjectConditionsDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/ObjectConditionsDefinition.cs index 1d1bf2b88..f2c148c50 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/ObjectConditionsDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/ObjectConditionsDefinition.cs @@ -10,6 +10,7 @@ using ArchUnitNET.Domain; using ArchUnitNET.Domain.Extensions; using ArchUnitNET.Fluent.Conditions; +using JetBrains.Annotations; using static ArchUnitNET.Domain.Visibility; using Attribute = ArchUnitNET.Domain.Attribute; @@ -992,6 +993,575 @@ IEnumerable Condition(IEnumerable ruleTypes, Archite return new ArchitectureCondition(Condition, description); } + public static ICondition HaveAnyAttributesWithArguments(object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return HaveAnyAttributesWithArguments(argumentValues); + } + + public static ICondition HaveAttributeWithArguments(string attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return HaveAttributeWithArguments(attribute, argumentValues); + } + + public static ICondition HaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return HaveAttributeWithArguments(attribute, argumentValues); + } + + public static ICondition HaveAttributeWithArguments(Type attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return HaveAttributeWithArguments(attribute, argumentValues); + } + + public static ICondition HaveAnyAttributesWithNamedArguments((string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return HaveAnyAttributesWithNamedArguments(attributeArguments); + } + + public static ICondition HaveAttributeWithNamedArguments(string attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return HaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static ICondition HaveAttributeWithNamedArguments(Attribute attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return HaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static ICondition HaveAttributeWithNamedArguments(Type attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return HaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static ICondition HaveAnyAttributesWithArguments(IEnumerable argumentValues) + { + var argumentValueList = argumentValues.ToList(); + string description; + Func failDescription; + if (argumentValueList.IsNullOrEmpty()) + { + description = "have no or any attributes with arguments (always true)"; + failDescription = (ruleType, architecture) => + "not have no or any attributes with arguments (impossible)"; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(attribute => attribute != firstArgument).Aggregate( + "have any attributes with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + + + failDescription = (ruleType, architecture) => + { + var actualArgumentValues = ruleType.AttributeInstances + .SelectMany(instance => + instance.AttributeArguments.Select(argument => argument.Value)).ToList(); + if (!actualArgumentValues.Any()) + { + return "does have no attribute with an argument"; + } + + var firstActualArgumentValue = actualArgumentValues.First(); + return actualArgumentValues.Aggregate( + "does have attributes with argument values \"" + firstActualArgumentValue + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + }; + } + + bool Condition(TRuleType obj, Architecture architecture) + { + var attributeArguments = obj.AttributeInstances + .SelectMany(instance => instance.AttributeArguments.Select(arg => arg.Value)).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + return false; + } + } + else if (!attributeArguments.Contains(arg)) + { + return false; + } + } + + return true; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition HaveAttributeWithArguments([NotNull] string attribute, + IEnumerable argumentValues) + { + string description, failDescription; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute + "\""; + failDescription = "does not have attribute \"" + attribute + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + failDescription = argumentValueList.Where(att => att != firstArgument).Aggregate( + "does not have attribute \"" + attribute + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.FullNameMatches(attribute)) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition HaveAttributeWithArguments([NotNull] Attribute attribute, + IEnumerable argumentValues) + { + string description, failDescription; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute.FullName + "\""; + failDescription = "does not have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + failDescription = argumentValueList.Where(att => att != firstArgument).Aggregate( + "does not have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(attribute)) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition HaveAttributeWithArguments([NotNull] Type attribute, + IEnumerable argumentValues) + { + string description, failDescription; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute.FullName + "\""; + failDescription = "does not have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + failDescription = argumentValueList.Where(att => att != firstArgument).Aggregate( + "does not have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(architecture.GetAttributeOfType(attribute))) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition HaveAnyAttributesWithNamedArguments( + IEnumerable<(string, object)> attributeArguments) + { + var argumentList = attributeArguments.ToList(); + string description; + Func failDescription; + if (argumentList.IsNullOrEmpty()) + { + description = "have no or any attributes with named arguments (always true)"; + failDescription = (ruleType, architecture) => + "not have no or any attributes with named arguments (impossible)"; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(attribute => attribute != firstArgument).Aggregate( + "have any attributes with named arguments \"" + firstArgument.Item1 + "=" + firstArgument.Item2 + + "\"", + (current, arg) => + current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + + + failDescription = (ruleType, architecture) => + { + var actualNamedArguments = ruleType.AttributeInstances + .SelectMany(instance => + instance.AttributeArguments.OfType()).ToList(); + if (!actualNamedArguments.Any()) + { + return "does have no attribute with a named argument"; + } + + var firstActualNamedArgument = actualNamedArguments.First(); + return actualNamedArguments.Aggregate( + "does have attributes with named arguments \"" + firstActualNamedArgument.Name + "=" + + firstActualNamedArgument.Value + "\"", + (current, arg) => + current + " and \"" + arg.Name + "=" + arg.Value + "\""); + }; + } + + bool Condition(TRuleType obj, Architecture architecture) + { + var attArguments = obj.AttributeInstances.SelectMany(instance => + instance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value))) + .ToList(); + var typeAttributeArguments = attArguments + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => + t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && type.FullName != argType.FullName)) + { + return false; + } + } + else if (!attArguments.Contains(arg)) + { + return false; + } + } + + return true; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition HaveAttributeWithNamedArguments([NotNull] string attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description, failDescription; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute + "\""; + failDescription = "does not have attribute \"" + attribute + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute + "\" with named arguments \"" + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + failDescription = argumentList.Where(att => att != firstArgument).Aggregate( + "does not have attribute \"" + attribute + "\" with named arguments \"" + + firstArgument.Item1 + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.FullNameMatches(attribute)) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => + t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition HaveAttributeWithNamedArguments([NotNull] Attribute attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description, failDescription; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute.FullName + "\""; + failDescription = "does not have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute.FullName + "\" with named arguments \"" + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + failDescription = argumentList.Where(att => att != firstArgument).Aggregate( + "does not have attribute \"" + attribute.FullName + "\" with named arguments \"" + + firstArgument.Item1 + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(attribute)) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => + t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition HaveAttributeWithNamedArguments([NotNull] Type attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description, failDescription; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute.FullName + "\""; + failDescription = "does not have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute.FullName + "\" with named arguments \"" + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + failDescription = argumentList.Where(att => att != firstArgument).Aggregate( + "does not have attribute \"" + attribute.FullName + "\" with named arguments \"" + + firstArgument.Item1 + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(architecture.GetAttributeOfType(attribute))) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => + t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } public static ICondition HaveName(string name) { @@ -1089,7 +1659,7 @@ public static ICondition BePrivateProtected() //Relation Conditions - + public static RelationCondition DependOnAnyTypesThat() { @@ -1733,6 +2303,578 @@ IEnumerable Condition(IEnumerable ruleTypes, Archite return new ArchitectureCondition(Condition, description); } + public static ICondition NotHaveAnyAttributesWithArguments(object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return NotHaveAnyAttributesWithArguments(argumentValues); + } + + public static ICondition NotHaveAttributeWithArguments(string attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return NotHaveAttributeWithArguments(attribute, argumentValues); + } + + public static ICondition NotHaveAttributeWithArguments(Attribute attribute, + object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return NotHaveAttributeWithArguments(attribute, argumentValues); + } + + public static ICondition NotHaveAttributeWithArguments(Type attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return NotHaveAttributeWithArguments(attribute, argumentValues); + } + + public static ICondition NotHaveAnyAttributesWithNamedArguments( + (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return NotHaveAnyAttributesWithNamedArguments(attributeArguments); + } + + public static ICondition NotHaveAttributeWithNamedArguments(string attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return NotHaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static ICondition NotHaveAttributeWithNamedArguments(Attribute attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return NotHaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static ICondition NotHaveAttributeWithNamedArguments(Type attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return NotHaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static ICondition NotHaveAnyAttributesWithArguments(IEnumerable argumentValues) + { + var argumentValueList = argumentValues.ToList(); + string description; + Func failDescription; + if (argumentValueList.IsNullOrEmpty()) + { + description = "not have no or any attributes with arguments (impossible)"; + failDescription = (ruleType, architecture) => "have no or any attributes with arguments (always)"; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(attribute => attribute != firstArgument).Aggregate( + "not have any attributes with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + + + failDescription = (ruleType, architecture) => + { + var actualArgumentValues = ruleType.AttributeInstances + .SelectMany(instance => + instance.AttributeArguments.Select(argument => argument.Value)).ToList(); + if (!actualArgumentValues.Any()) + { + return "does have no attribute with an argument"; + } + + var firstActualArgumentValue = actualArgumentValues.First(); + return actualArgumentValues.Aggregate( + "does have attributes with argument values \"" + firstActualArgumentValue + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + }; + } + + bool Condition(TRuleType obj, Architecture architecture) + { + var attributeArguments = obj.AttributeInstances + .SelectMany(instance => instance.AttributeArguments.Select(arg => arg.Value)).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.Any(t => t.FullName == argType.FullName)) + { + return false; + } + } + else if (attributeArguments.Contains(arg)) + { + return false; + } + } + + return true; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition NotHaveAttributeWithArguments([NotNull] string attribute, + IEnumerable argumentValues) + { + string description, failDescription; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "not have attribute \"" + attribute + "\""; + failDescription = "does have attribute \"" + attribute + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "not have attribute \"" + attribute + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + failDescription = argumentValueList.Where(att => att != firstArgument).Aggregate( + "does have attribute \"" + attribute + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.FullNameMatches(attribute)) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition NotHaveAttributeWithArguments([NotNull] Attribute attribute, + IEnumerable argumentValues) + { + string description, failDescription; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "not have attribute \"" + attribute.FullName + "\""; + failDescription = "does have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "not have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + failDescription = argumentValueList.Where(att => att != firstArgument).Aggregate( + "does have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(attribute)) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition NotHaveAttributeWithArguments([NotNull] Type attribute, + IEnumerable argumentValues) + { + string description, failDescription; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "not have attribute \"" + attribute.FullName + "\""; + failDescription = "does have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "not have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + failDescription = argumentValueList.Where(att => att != firstArgument).Aggregate( + "does have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(architecture.GetAttributeOfType(attribute))) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition NotHaveAnyAttributesWithNamedArguments( + IEnumerable<(string, object)> attributeArguments) + { + var argumentList = attributeArguments.ToList(); + string description; + Func failDescription; + if (argumentList.IsNullOrEmpty()) + { + description = "not have no or any attributes with named arguments (impossible)"; + failDescription = (ruleType, architecture) => + "have no or any attributes with named arguments (always true)"; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(attribute => attribute != firstArgument).Aggregate( + "not have any attributes with named arguments \"" + firstArgument.Item1 + "=" + + firstArgument.Item2 + + "\"", + (current, arg) => + current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + + + failDescription = (ruleType, architecture) => + { + var actualNamedArguments = ruleType.AttributeInstances + .SelectMany(instance => + instance.AttributeArguments.OfType()).ToList(); + if (!actualNamedArguments.Any()) + { + return "does have no attribute with a named argument"; + } + + var firstActualNamedArgument = actualNamedArguments.First(); + return actualNamedArguments.Aggregate( + "does have attributes with named arguments \"" + firstActualNamedArgument.Name + "=" + + firstActualNamedArgument.Value + "\"", + (current, arg) => + current + " and \"" + arg.Name + "=" + arg.Value + "\""); + }; + } + + bool Condition(TRuleType obj, Architecture architecture) + { + var attArguments = obj.AttributeInstances.SelectMany(instance => + instance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value))) + .ToList(); + var typeAttributeArguments = attArguments + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.Any(t => + t.Name == arg.Item1 && + (t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName == argType.FullName || + t.Value is IType type && type.FullName == argType.FullName))) + { + return false; + } + } + else if (attArguments.Contains(arg)) + { + return false; + } + } + + return true; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition NotHaveAttributeWithNamedArguments([NotNull] string attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description, failDescription; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "not have attribute \"" + attribute + "\""; + failDescription = "does have attribute \"" + attribute + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "not have attribute \"" + attribute + "\" with named arguments \"" + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + failDescription = argumentList.Where(att => att != firstArgument).Aggregate( + "does have attribute \"" + attribute + "\" with named arguments \"" + + firstArgument.Item1 + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.FullNameMatches(attribute)) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && + type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition NotHaveAttributeWithNamedArguments([NotNull] Attribute attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description, failDescription; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "not have attribute \"" + attribute.FullName + "\""; + failDescription = "does have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "not have attribute \"" + attribute.FullName + "\" with named arguments \"" + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + failDescription = argumentList.Where(att => att != firstArgument).Aggregate( + "does have attribute \"" + attribute.FullName + "\" with named arguments \"" + + firstArgument.Item1 + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(attribute)) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && + type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + + public static ICondition NotHaveAttributeWithNamedArguments([NotNull] Type attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description, failDescription; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "not have attribute \"" + attribute.FullName + "\""; + failDescription = "does have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "not have attribute \"" + attribute.FullName + "\" with named arguments \"" + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + failDescription = argumentList.Where(att => att != firstArgument).Aggregate( + "does have attribute \"" + attribute.FullName + "\" with named arguments \"" + + firstArgument.Item1 + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Condition(TRuleType obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(architecture.GetAttributeOfType(attribute))) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && + type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitectureCondition(Condition, failDescription, description); + } + public static ICondition NotHaveName(string name) { return new SimpleCondition(obj => !obj.Name.Equals(name), obj => "does have name " + obj.Name, diff --git a/ArchUnitNET/Fluent/Syntax/Elements/ObjectPredicatesDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/ObjectPredicatesDefinition.cs index 6b5899a20..a38ff407c 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/ObjectPredicatesDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/ObjectPredicatesDefinition.cs @@ -10,6 +10,7 @@ using ArchUnitNET.Domain; using ArchUnitNET.Domain.Extensions; using ArchUnitNET.Fluent.Predicates; +using JetBrains.Annotations; using static ArchUnitNET.Domain.Visibility; using Attribute = ArchUnitNET.Domain.Attribute; @@ -606,6 +607,507 @@ IEnumerable Filter(IEnumerable objects, Architecture architecture) return new ArchitecturePredicate(Filter, description); } + public static IPredicate HaveAnyAttributesWithArguments(object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return HaveAnyAttributesWithArguments(argumentValues); + } + + public static IPredicate HaveAttributeWithArguments(string attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return HaveAttributeWithArguments(attribute, argumentValues); + } + + public static IPredicate HaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return HaveAttributeWithArguments(attribute, argumentValues); + } + + public static IPredicate HaveAttributeWithArguments(Type attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return HaveAttributeWithArguments(attribute, argumentValues); + } + + public static IPredicate HaveAnyAttributesWithNamedArguments((string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return HaveAnyAttributesWithNamedArguments(attributeArguments); + } + + public static IPredicate HaveAttributeWithNamedArguments(string attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return HaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static IPredicate HaveAttributeWithNamedArguments(Attribute attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return HaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static IPredicate HaveAttributeWithNamedArguments(Type attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return HaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static IPredicate HaveAnyAttributesWithArguments(IEnumerable argumentValues) + { + var argumentValueList = argumentValues.ToList(); + string description; + if (argumentValueList.IsNullOrEmpty()) + { + description = "have no or any attributes with arguments (always true)"; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(attribute => attribute != firstArgument).Aggregate( + "have any attributes with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + var attributeArguments = obj.AttributeInstances + .SelectMany(instance => instance.AttributeArguments.Select(arg => arg.Value)).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + return false; + } + } + else if (!attributeArguments.Contains(arg)) + { + return false; + } + } + + return true; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate HaveAttributeWithArguments([NotNull] string attribute, + IEnumerable argumentValues) + { + string description; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.FullNameMatches(attribute)) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate HaveAttributeWithArguments([NotNull] Attribute attribute, + IEnumerable argumentValues) + { + string description; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(attribute)) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate HaveAttributeWithArguments([NotNull] Type attribute, + IEnumerable argumentValues) + { + string description; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(architecture.GetAttributeOfType(attribute))) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate HaveAnyAttributesWithNamedArguments( + IEnumerable<(string, object)> attributeArguments) + { + var argumentList = attributeArguments.ToList(); + string description; + if (argumentList.IsNullOrEmpty()) + { + description = "have no or any attributes with named arguments (always true)"; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(attribute => attribute != firstArgument).Aggregate( + "have any attributes with named arguments \"" + firstArgument.Item1 + "=" + firstArgument.Item2 + + "\"", + (current, arg) => + current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + var attArguments = obj.AttributeInstances.SelectMany(instance => + instance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value))) + .ToList(); + var typeAttributeArguments = attArguments + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => + t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && type.FullName != argType.FullName)) + { + return false; + } + } + else if (!attArguments.Contains(arg)) + { + return false; + } + } + + return true; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate HaveAttributeWithNamedArguments([NotNull] string attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute + "\" with named arguments \"" + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.FullNameMatches(attribute)) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => + t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate HaveAttributeWithNamedArguments([NotNull] Attribute attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute.FullName + "\" with named arguments \"" + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Condition(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(attribute)) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => + t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitecturePredicate(Condition, description); + } + + public static IPredicate HaveAttributeWithNamedArguments([NotNull] Type attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "have attribute \"" + attribute.FullName + "\" with named arguments \"" + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(architecture.GetAttributeOfType(attribute))) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => + t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return true; + NextAttribute: ; + } + + return false; + } + + return new ArchitecturePredicate(Predicate, description); + } + public static IPredicate HaveName(string name) { return new SimplePredicate(obj => obj.Name.Equals(name), "have name \"" + name + "\""); @@ -1049,6 +1551,512 @@ IEnumerable Filter(IEnumerable objects, Architecture architecture) return new ArchitecturePredicate(Filter, description); } + public static IPredicate DoNotHaveAnyAttributesWithArguments(object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return DoNotHaveAnyAttributesWithArguments(argumentValues); + } + + public static IPredicate DoNotHaveAttributeWithArguments(string attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return DoNotHaveAttributeWithArguments(attribute, argumentValues); + } + + public static IPredicate DoNotHaveAttributeWithArguments(Attribute attribute, + object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return DoNotHaveAttributeWithArguments(attribute, argumentValues); + } + + public static IPredicate DoNotHaveAttributeWithArguments(Type attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + var argumentValues = new List {firstArgumentValue}; + argumentValues.AddRange(moreArgumentValues); + return DoNotHaveAttributeWithArguments(attribute, argumentValues); + } + + public static IPredicate DoNotHaveAnyAttributesWithNamedArguments( + (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return DoNotHaveAnyAttributesWithNamedArguments(attributeArguments); + } + + public static IPredicate DoNotHaveAttributeWithNamedArguments(string attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return DoNotHaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static IPredicate DoNotHaveAttributeWithNamedArguments(Attribute attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return DoNotHaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static IPredicate DoNotHaveAttributeWithNamedArguments(Type attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + var attributeArguments = new List<(string, object)> {firstAttributeArgument}; + attributeArguments.AddRange(moreAttributeArguments); + return DoNotHaveAttributeWithNamedArguments(attribute, attributeArguments); + } + + public static IPredicate DoNotHaveAnyAttributesWithArguments(IEnumerable argumentValues) + { + var argumentValueList = argumentValues.ToList(); + string description; + if (argumentValueList.IsNullOrEmpty()) + { + description = "do not have no or any attributes with arguments (impossible)"; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(attribute => attribute != firstArgument).Aggregate( + "do not have any attributes with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + var attributeArguments = obj.AttributeInstances + .SelectMany(instance => instance.AttributeArguments.Select(arg => arg.Value)).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.Any(t => t.FullName == argType.FullName)) + { + return false; + } + } + else if (attributeArguments.Contains(arg)) + { + return false; + } + } + + return true; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate DoNotHaveAttributeWithArguments([NotNull] string attribute, + IEnumerable argumentValues) + { + string description; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "do not have attribute \"" + attribute + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "do not have attribute \"" + attribute + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.FullNameMatches(attribute)) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate DoNotHaveAttributeWithArguments([NotNull] Attribute attribute, + IEnumerable argumentValues) + { + string description; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "do not have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "do not have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(attribute)) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate DoNotHaveAttributeWithArguments([NotNull] Type attribute, + IEnumerable argumentValues) + { + string description; + var argumentValueList = argumentValues.ToList(); + if (argumentValueList.IsNullOrEmpty()) + { + description = "do not have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentValueList.First(); + description = argumentValueList.Where(att => att != firstArgument).Aggregate( + "do not have attribute \"" + attribute.FullName + "\" with arguments \"" + firstArgument + "\"", + (current, argumentValue) => current + " and \"" + argumentValue + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(architecture.GetAttributeOfType(attribute))) + { + goto NextAttribute; + } + + var attributeArguments = attributeInstance.AttributeArguments.Select(arg => arg.Value).ToList(); + var typeAttributeArguments = attributeArguments.OfType>().Select(t => t.Type) + .Union(attributeArguments.OfType()).ToList(); + foreach (var arg in argumentValueList) + { + if (arg is Type argType) + { + if (typeAttributeArguments.All(t => t.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!attributeArguments.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate DoNotHaveAnyAttributesWithNamedArguments( + IEnumerable<(string, object)> attributeArguments) + { + var argumentList = attributeArguments.ToList(); + string description; + if (argumentList.IsNullOrEmpty()) + { + description = "do not have no or any attributes with named arguments (impossible)"; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(attribute => attribute != firstArgument).Aggregate( + "do not have any attributes with named arguments \"" + firstArgument.Item1 + "=" + + firstArgument.Item2 + + "\"", + (current, arg) => + current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Condition(T obj, Architecture architecture) + { + var attArguments = obj.AttributeInstances.SelectMany(instance => + instance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value))) + .ToList(); + var typeAttributeArguments = attArguments + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.Any(t => + t.Name == arg.Item1 && + (t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName == argType.FullName || + t.Value is IType type && type.FullName == argType.FullName))) + { + return false; + } + } + else if (attArguments.Contains(arg)) + { + return false; + } + } + + return true; + } + + return new ArchitecturePredicate(Condition, description); + } + + public static IPredicate DoNotHaveAttributeWithNamedArguments([NotNull] string attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "do not have attribute \"" + attribute + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "do not have attribute \"" + attribute + "\" with named arguments \"" + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.FullNameMatches(attribute)) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && + type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate DoNotHaveAttributeWithNamedArguments([NotNull] Attribute attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "do not have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "do not have attribute \"" + attribute.FullName + "\" with named arguments \"" + + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(attribute)) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && + type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitecturePredicate(Predicate, description); + } + + public static IPredicate DoNotHaveAttributeWithNamedArguments([NotNull] Type attribute, + IEnumerable<(string, object)> attributeArguments) + { + string description; + var argumentList = attributeArguments.ToList(); + if (argumentList.IsNullOrEmpty()) + { + description = "do not have attribute \"" + attribute.FullName + "\""; + } + else + { + var firstArgument = argumentList.First(); + description = argumentList.Where(att => att != firstArgument).Aggregate( + "do not have attribute \"" + attribute.FullName + "\" with named arguments \"" + + firstArgument.Item1 + + "=" + firstArgument.Item2 + "\"", + (current, arg) => current + " and \"" + arg.Item1 + "=" + arg.Item2 + "\""); + } + + bool Predicate(T obj, Architecture architecture) + { + foreach (var attributeInstance in obj.AttributeInstances) + { + if (!attributeInstance.Type.Equals(architecture.GetAttributeOfType(attribute))) + { + goto NextAttribute; + } + + var attributeArgs = attributeInstance.AttributeArguments.OfType() + .Select(arg => (arg.Name, arg.Value)).ToList(); + var typeAttributeArguments = attributeArgs + .Where(arg => arg.Value is ITypeInstance || arg.Value is IType).ToList(); + foreach (var arg in argumentList) + { + if (arg.Item2 is Type argType) + { + if (typeAttributeArguments.All(t => t.Name != arg.Item1 || + t.Value is ITypeInstance typeInstance && + typeInstance.Type.FullName != argType.FullName || + t.Value is IType type && + type.FullName != argType.FullName)) + { + goto NextAttribute; + } + } + else if (!argumentList.Contains(arg)) + { + goto NextAttribute; + } + } + + return false; + NextAttribute: ; + } + + return true; + } + + return new ArchitecturePredicate(Predicate, description); + } + public static IPredicate DoNotHaveName(string name) { return new SimplePredicate(obj => !obj.Name.Equals(name), "do not have name \"" + name + "\""); diff --git a/ArchUnitNET/Fluent/Syntax/Elements/ObjectsShould.cs b/ArchUnitNET/Fluent/Syntax/Elements/ObjectsShould.cs index 28904580e..535b6a797 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/ObjectsShould.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/ObjectsShould.cs @@ -301,6 +301,143 @@ public TRuleTypeShouldConjunction OnlyHaveAttributes(IEnumerable attribute return Create(_ruleCreator); } + public TRuleTypeShouldConjunction HaveAnyAttributesWithArguments(IEnumerable argumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAnyAttributesWithArguments(argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction + HaveAnyAttributesWithArguments(object firstArgumentValue, params object[] moreArgumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAnyAttributesWithArguments(firstArgumentValue, + moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(string attribute, + IEnumerable argumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithArguments(attribute, argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(string attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithArguments(attribute, firstArgumentValue, + moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(Attribute attribute, + IEnumerable argumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithArguments(attribute, argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithArguments(attribute, firstArgumentValue, + moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(Type attribute, IEnumerable argumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithArguments(attribute, argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(Type attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithArguments(attribute, firstArgumentValue, + moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAnyAttributesWithNamedArguments( + IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAnyAttributesWithNamedArguments(attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAnyAttributesWithNamedArguments((string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAnyAttributesWithNamedArguments(firstAttributeArgument, + moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(string attribute, + IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithNamedArguments(attribute, attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(string attribute, + (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithNamedArguments(attribute, firstAttributeArgument, + moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(Attribute attribute, + IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithNamedArguments(attribute, attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(Attribute attribute, + (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithNamedArguments(attribute, firstAttributeArgument, + moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(Type attribute, + IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithNamedArguments(attribute, attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(Type attribute, + (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.HaveAttributeWithNamedArguments(attribute, firstAttributeArgument, + moreAttributeArguments)); + return Create(_ruleCreator); + } + public TRuleTypeShouldConjunction HaveName(string name) { _ruleCreator.AddCondition(ObjectConditionsDefinition.HaveName(name)); @@ -582,6 +719,151 @@ public TRuleTypeShouldConjunction NotHaveAnyAttributes(IEnumerable attribu return Create(_ruleCreator); } + public TRuleTypeShouldConjunction NotHaveAnyAttributesWithArguments(IEnumerable argumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAnyAttributesWithArguments(argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction + NotHaveAnyAttributesWithArguments(object firstArgumentValue, params object[] moreArgumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAnyAttributesWithArguments(firstArgumentValue, + moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithArguments(string attribute, + IEnumerable argumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithArguments(attribute, argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithArguments(string attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithArguments(attribute, firstArgumentValue, + moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithArguments(Attribute attribute, + IEnumerable argumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithArguments(attribute, argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithArguments(attribute, firstArgumentValue, + moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithArguments(Type attribute, + IEnumerable argumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithArguments(attribute, argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithArguments(Type attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithArguments(attribute, firstArgumentValue, + moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAnyAttributesWithNamedArguments( + IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAnyAttributesWithNamedArguments(attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAnyAttributesWithNamedArguments( + (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAnyAttributesWithNamedArguments(firstAttributeArgument, + moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithNamedArguments(string attribute, + IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithNamedArguments(attribute, + attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithNamedArguments(string attribute, + (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithNamedArguments(attribute, + firstAttributeArgument, + moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithNamedArguments(Attribute attribute, + IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithNamedArguments(attribute, + attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithNamedArguments(Attribute attribute, + (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithNamedArguments(attribute, + firstAttributeArgument, + moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithNamedArguments(Type attribute, + IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithNamedArguments(attribute, + attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction NotHaveAttributeWithNamedArguments(Type attribute, + (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.AddCondition( + ObjectConditionsDefinition.NotHaveAttributeWithNamedArguments(attribute, + firstAttributeArgument, + moreAttributeArguments)); + return Create(_ruleCreator); + } + public TRuleTypeShouldConjunction NotHaveName(string name) { _ruleCreator.AddCondition(ObjectConditionsDefinition.NotHaveName(name)); @@ -667,7 +949,7 @@ public TRuleTypeShouldConjunction NotBePrivateProtected() } //Relation Condition Negations - + public ShouldRelateToTypesThat NotDependOnAnyTypesThat() { _ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(true), diff --git a/ArchUnitNET/Fluent/Syntax/Elements/ShouldRelateToObjectsThat.cs b/ArchUnitNET/Fluent/Syntax/Elements/ShouldRelateToObjectsThat.cs index 779bf2382..951c71a4d 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/ShouldRelateToObjectsThat.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/ShouldRelateToObjectsThat.cs @@ -302,6 +302,126 @@ public TRuleTypeShouldConjunction OnlyHaveAttributes(IEnumerable attribute return Create(_ruleCreator); } + public TRuleTypeShouldConjunction HaveAnyAttributesWithArguments(IEnumerable argumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAnyAttributesWithArguments(argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction + HaveAnyAttributesWithArguments(object firstArgumentValue, params object[] moreArgumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAnyAttributesWithArguments(firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(string attribute, IEnumerable argumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(string attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(Attribute attribute, IEnumerable argumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(Type attribute, IEnumerable argumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithArguments(Type attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAnyAttributesWithNamedArguments(IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAnyAttributesWithNamedArguments(attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAnyAttributesWithNamedArguments((string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAnyAttributesWithNamedArguments(firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(string attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(string attribute, (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(Attribute attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(Attribute attribute, (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(Type attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction HaveAttributeWithNamedArguments(Type attribute, (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.HaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + public TRuleTypeShouldConjunction HaveName(string name) { _ruleCreator.ContinueComplexCondition(ObjectPredicatesDefinition.HaveName(name)); @@ -565,6 +685,126 @@ public TRuleTypeShouldConjunction DoNotHaveAnyAttributes(IEnumerable attri return Create(_ruleCreator); } + public TRuleTypeShouldConjunction DoNotHaveAnyAttributesWithArguments(IEnumerable argumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAnyAttributesWithArguments(argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAnyAttributesWithArguments(object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAnyAttributesWithArguments(firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithArguments(Attribute attribute, IEnumerable argumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAnyAttributesWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithArguments(Attribute attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithArguments(Type attribute, IEnumerable argumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithArguments(Type attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAnyAttributesWithNamedArguments(IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAnyAttributesWithNamedArguments(attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAnyAttributesWithNamedArguments((string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAnyAttributesWithNamedArguments(firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithArguments(string attribute, IEnumerable argumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,argumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithArguments(string attribute, object firstArgumentValue, + params object[] moreArgumentValues) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithArguments(attribute,firstArgumentValue,moreArgumentValues)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithNamedArguments(string attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithNamedArguments(string attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithNamedArguments(Attribute attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithNamedArguments(Attribute attribute, + (string, object) firstAttributeArgument, params (string, object)[] moreAttributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithNamedArguments(Type attribute, IEnumerable<(string, object)> attributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,attributeArguments)); + return Create(_ruleCreator); + } + + public TRuleTypeShouldConjunction DoNotHaveAttributeWithNamedArguments(Type attribute, (string, object) firstAttributeArgument, + params (string, object)[] moreAttributeArguments) + { + _ruleCreator.ContinueComplexCondition( + ObjectPredicatesDefinition.DoNotHaveAttributeWithNamedArguments(attribute,firstAttributeArgument,moreAttributeArguments)); + return Create(_ruleCreator); + } + public TRuleTypeShouldConjunction DoNotHaveName(string name) { _ruleCreator.ContinueComplexCondition(ObjectPredicatesDefinition.DoNotHaveName(name)); From 118caf30b8533aa85c742744d18294e6a2df5527 Mon Sep 17 00:00:00 2001 From: Fritz Brandhuber Date: Mon, 12 Jul 2021 19:02:27 +0200 Subject: [PATCH 3/4] write tests for fluent implementations Signed-off-by: Fritz Brandhuber --- .../Domain/AttributeArgumentTests.cs | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/ArchUnitNETTests/Domain/AttributeArgumentTests.cs b/ArchUnitNETTests/Domain/AttributeArgumentTests.cs index 79f5c310f..646ca7f29 100644 --- a/ArchUnitNETTests/Domain/AttributeArgumentTests.cs +++ b/ArchUnitNETTests/Domain/AttributeArgumentTests.cs @@ -10,7 +10,9 @@ using ArchUnitNET.Domain; using ArchUnitNET.Domain.Extensions; using ArchUnitNET.Loader; +using ArchUnitNET.xUnit; using Xunit; +using static ArchUnitNET.Fluent.ArchRuleDefinition; using Attribute = System.Attribute; namespace ArchUnitNETTests.Domain @@ -93,6 +95,158 @@ public void AssignNamesToAttributeParameters() Assert.Contains(namedArguments, arg => arg.Name == "Parameter2" && (string) arg.Value == "param2_1"); Assert.Contains(namedArguments, arg => arg.Name == "Parameter3" && (string) arg.Value == "param3_2"); } + + [Fact] + public void FluentPredicatesTest() + { + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .HaveAttributeWithArguments(_attributeWithStringParameters, "param1_1").Should().Exist() + .Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .HaveAnyAttributesWithArguments("param1_0").Should() + .Exist().Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .HaveAnyAttributesWithNamedArguments(("Parameter2", "param2_1")).Should() + .Exist().Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .HaveAnyAttributesWithNamedArguments(("Parameter2", "param2_1"), ("Parameter3", "param3_2")).Should() + .Exist().Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .HaveAnyAttributesWithArguments(1).Should() + .Exist().Check(Architecture); + Types().That().Are(typeof(ClassWithTypeParameterAttribute)).And() + .HaveAnyAttributesWithArguments(typeof(ClassWithArrayParameterAttribute)).Should() + .Exist().Check(Architecture); + Types().That().Are(typeof(ClassWithTypeParameterAttribute)).And() + .HaveAnyAttributesWithNamedArguments(("Type2", typeof(ClassWithArrayParameterAttribute))).Should() + .Exist().Check(Architecture); + + + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .HaveAnyAttributesWithNamedArguments(("Parameter2", "param1_1")).Should() + .NotExist().Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .HaveAttributeWithArguments(_attributeWithStringParameters, "non_existent").Should() + .NotExist().Check(Architecture); + Types().That().Are(typeof(ClassWithTypeParameterAttribute)).And() + .HaveAnyAttributesWithNamedArguments(("Type3", typeof(ClassWithArrayParameterAttribute))).Should() + .NotExist().Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .HaveAnyAttributesWithArguments("1").Should() + .NotExist().Check(Architecture); + + //Negations + + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .DoNotHaveAttributeWithArguments(_attributeWithStringParameters, "param1_1").Should().NotExist() + .Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .DoNotHaveAnyAttributesWithArguments("param1_0").Should() + .NotExist().Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .DoNotHaveAnyAttributesWithNamedArguments(("Parameter2", "param2_1")).Should() + .NotExist().Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .DoNotHaveAnyAttributesWithNamedArguments(("Parameter2", "param2_1"), ("Parameter3", "param3_2")) + .Should() + .NotExist().Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .DoNotHaveAnyAttributesWithArguments(1).Should() + .NotExist().Check(Architecture); + Types().That().Are(typeof(ClassWithTypeParameterAttribute)).And() + .DoNotHaveAnyAttributesWithArguments(typeof(ClassWithArrayParameterAttribute)).Should() + .NotExist().Check(Architecture); + Types().That().Are(typeof(ClassWithTypeParameterAttribute)).And() + .DoNotHaveAnyAttributesWithNamedArguments(("Type2", typeof(ClassWithArrayParameterAttribute))).Should() + .NotExist().Check(Architecture); + + + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .DoNotHaveAnyAttributesWithNamedArguments(("Parameter2", "param1_1")).Should() + .Exist().Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .DoNotHaveAttributeWithArguments(_attributeWithStringParameters, "non_existent").Should() + .Exist().Check(Architecture); + Types().That().Are(typeof(ClassWithTypeParameterAttribute)).And() + .DoNotHaveAnyAttributesWithNamedArguments(("Type3", typeof(ClassWithArrayParameterAttribute))).Should() + .Exist().Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).And() + .DoNotHaveAnyAttributesWithArguments("1").Should() + .Exist().Check(Architecture); + } + + [Fact] + public void FluentConditionsTest() + { + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .HaveAttributeWithArguments(_attributeWithStringParameters, "param1_1").Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .HaveAnyAttributesWithArguments("param1_0").Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .HaveAnyAttributesWithNamedArguments(("Parameter2", "param2_1")).Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .HaveAnyAttributesWithNamedArguments(("Parameter2", "param2_1"), ("Parameter3", "param3_2")) + .Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .HaveAnyAttributesWithArguments(1).Check(Architecture); + Types().That().Are(typeof(ClassWithTypeParameterAttribute)).Should() + .HaveAnyAttributesWithArguments(typeof(ClassWithArrayParameterAttribute)).Check(Architecture); + Types().That().Are(typeof(ClassWithTypeParameterAttribute)).Should() + .HaveAnyAttributesWithNamedArguments(("Type2", typeof(ClassWithArrayParameterAttribute))) + .Check(Architecture); + + + Assert.Throws(() => Types().That() + .Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .HaveAnyAttributesWithNamedArguments(("Parameter2", "param1_1")).Check(Architecture)); + Assert.Throws(() => Types().That() + .Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .HaveAttributeWithArguments(_attributeWithStringParameters, "non_existent").Check(Architecture)); + Assert.Throws(() => Types().That().Are(typeof(ClassWithTypeParameterAttribute)) + .Should() + .HaveAnyAttributesWithNamedArguments(("Type3", typeof(ClassWithArrayParameterAttribute))) + .Check(Architecture)); + Assert.Throws(() => Types().That() + .Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .HaveAnyAttributesWithArguments("1").Check(Architecture)); + + //Negations + + Assert.Throws(() => Types().That() + .Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .NotHaveAttributeWithArguments(_attributeWithStringParameters, "param1_1").Check(Architecture)); + Assert.Throws(() => Types().That() + .Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .NotHaveAnyAttributesWithArguments("param1_0").Check(Architecture)); + Assert.Throws(() => Types().That() + .Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .NotHaveAnyAttributesWithNamedArguments(("Parameter2", "param2_1")).Check(Architecture)); + Assert.Throws(() => Types().That() + .Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .NotHaveAnyAttributesWithNamedArguments(("Parameter2", "param2_1"), ("Parameter3", "param3_2")) + .Check(Architecture)); + Assert.Throws(() => Types().That() + .Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .NotHaveAnyAttributesWithArguments(1).Check(Architecture)); + Assert.Throws(() => Types().That().Are(typeof(ClassWithTypeParameterAttribute)) + .Should() + .NotHaveAnyAttributesWithArguments(typeof(ClassWithArrayParameterAttribute)).Check(Architecture)); + Assert.Throws(() => Types().That().Are(typeof(ClassWithTypeParameterAttribute)) + .Should() + .NotHaveAnyAttributesWithNamedArguments(("Type2", typeof(ClassWithArrayParameterAttribute))) + .Check(Architecture)); + + + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .NotHaveAnyAttributesWithNamedArguments(("Parameter2", "param1_1")).Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .NotHaveAttributeWithArguments(_attributeWithStringParameters, "non_existent").Check(Architecture); + Types().That().Are(typeof(ClassWithTypeParameterAttribute)).Should() + .NotHaveAnyAttributesWithNamedArguments(("Type3", typeof(ClassWithArrayParameterAttribute))) + .Check(Architecture); + Types().That().Are(typeof(ClassWithMultipleAttributesWithParameters)).Should() + .NotHaveAnyAttributesWithArguments("1").Check(Architecture); + } } [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] From bca65eb0f2a41d4b1bfa73e7a967be350e9c35c2 Mon Sep 17 00:00:00 2001 From: Fritz Brandhuber Date: Mon, 12 Jul 2021 19:12:22 +0200 Subject: [PATCH 4/4] move TypeInstance into Domain namespace, since the new Fluent methods are accessing it indirectly Signed-off-by: Fritz Brandhuber --- ArchUnitNET/{Loader => Domain}/TypeInstance.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename ArchUnitNET/{Loader => Domain}/TypeInstance.cs (97%) diff --git a/ArchUnitNET/Loader/TypeInstance.cs b/ArchUnitNET/Domain/TypeInstance.cs similarity index 97% rename from ArchUnitNET/Loader/TypeInstance.cs rename to ArchUnitNET/Domain/TypeInstance.cs index 5dd9c12cd..c30dd8080 100644 --- a/ArchUnitNET/Loader/TypeInstance.cs +++ b/ArchUnitNET/Domain/TypeInstance.cs @@ -7,9 +7,8 @@ using System.Collections.Generic; using System.Linq; -using ArchUnitNET.Domain; -namespace ArchUnitNET.Loader +namespace ArchUnitNET.Domain { public class TypeInstance : ITypeInstance where T : IType {