Skip to content

Commit

Permalink
Merge pull request #84 from brandhuf/fix-complex-conditions
Browse files Browse the repository at this point in the history
Fix complex conditions
  • Loading branch information
fgather authored Jun 10, 2021
2 parents abc5242 + 9e53a12 commit 7bd1cac
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 55 deletions.
24 changes: 16 additions & 8 deletions ArchUnitNET/Fluent/ArchRuleDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,35 @@ namespace ArchUnitNET.Fluent
{
public static class ArchRuleDefinition
{
public static GivenTypes Types()
public static GivenTypes Types(bool includeReferenced = false)
{
var ruleCreator = new ArchRuleCreator<IType>(BasicObjectProviderDefinition.Types);
var ruleCreator = includeReferenced
? new ArchRuleCreator<IType>(BasicObjectProviderDefinition.TypesIncludingReferenced)
: new ArchRuleCreator<IType>(BasicObjectProviderDefinition.Types);
return new GivenTypes(ruleCreator);
}

public static GivenAttributes Attributes()
public static GivenAttributes Attributes(bool includeReferenced = false)
{
var ruleCreator = new ArchRuleCreator<Attribute>(BasicObjectProviderDefinition.Attributes);
var ruleCreator = includeReferenced
? new ArchRuleCreator<Attribute>(BasicObjectProviderDefinition.AttributesIncludingReferenced)
: new ArchRuleCreator<Attribute>(BasicObjectProviderDefinition.Attributes);
return new GivenAttributes(ruleCreator);
}

public static GivenClasses Classes()
public static GivenClasses Classes(bool includeReferenced = false)
{
var ruleCreator = new ArchRuleCreator<Class>(BasicObjectProviderDefinition.Classes);
var ruleCreator = includeReferenced
? new ArchRuleCreator<Class>(BasicObjectProviderDefinition.ClassesIncludingReferenced)
: new ArchRuleCreator<Class>(BasicObjectProviderDefinition.Classes);
return new GivenClasses(ruleCreator);
}

public static GivenInterfaces Interfaces()
public static GivenInterfaces Interfaces(bool includeReferenced = false)
{
var ruleCreator = new ArchRuleCreator<Interface>(BasicObjectProviderDefinition.Interfaces);
var ruleCreator = includeReferenced
? new ArchRuleCreator<Interface>(BasicObjectProviderDefinition.InterfacesIncludingReferenced)
: new ArchRuleCreator<Interface>(BasicObjectProviderDefinition.Interfaces);
return new GivenInterfaces(ruleCreator);
}

Expand Down
19 changes: 19 additions & 0 deletions ArchUnitNET/Fluent/BasicObjectProviderDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//
// SPDX-License-Identifier: Apache-2.0

using System.Linq;
using ArchUnitNET.Domain;

namespace ArchUnitNET.Fluent
Expand Down Expand Up @@ -33,5 +34,23 @@ public static class BasicObjectProviderDefinition

public static readonly BasicObjectProvider<PropertyMember> PropertyMembers =
new BasicObjectProvider<PropertyMember>(architecture => architecture.PropertyMembers, "Property members");

public static readonly BasicObjectProvider<IType> TypesIncludingReferenced =
new BasicObjectProvider<IType>(architecture => architecture.Types.Concat(architecture.ReferencedTypes),
"Types (including referenced)");

public static readonly BasicObjectProvider<Attribute> AttributesIncludingReferenced =
new BasicObjectProvider<Attribute>(
architecture => architecture.Attributes.Concat(architecture.ReferencedAttributes),
"Attributes (including referenced)");

public static readonly BasicObjectProvider<Class> ClassesIncludingReferenced =
new BasicObjectProvider<Class>(architecture => architecture.Classes.Concat(architecture.ReferencedClasses),
"Classes (including referenced)");

public static readonly BasicObjectProvider<Interface> InterfacesIncludingReferenced =
new BasicObjectProvider<Interface>(
architecture => architecture.Interfaces.Concat(architecture.ReferencedInterfaces),
"Interfaces (including referenced)");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// SPDX-License-Identifier: Apache-2.0

using ArchUnitNET.Domain;
using ArchUnitNET.Fluent.Syntax.Elements.Members.MethodMembers;
using ArchUnitNET.Fluent.Syntax.Elements.Types;
using ArchUnitNET.Fluent.Syntax.Elements.Types.Attributes;

Expand All @@ -17,7 +16,6 @@ public interface
where TRuleType : ICanBeAnalyzed
where TRuleTypeShouldConjunction : SyntaxElement<TRuleType>
{
ShouldRelateToMethodMembersThat<TRuleTypeShouldConjunction, TRuleType> CallAnyMethodsThat();
ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType> DependOnAnyTypesThat();
ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType> OnlyDependOnTypesThat();
ShouldRelateToAttributesThat<TRuleTypeShouldConjunction, TRuleType> HaveAnyAttributesThat();
Expand All @@ -26,7 +24,6 @@ public interface

//Negations

ShouldRelateToMethodMembersThat<TRuleTypeShouldConjunction, TRuleType> NotCallAnyMethodsThat();
ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType> NotDependOnAnyTypesThat();
ShouldRelateToAttributesThat<TRuleTypeShouldConjunction, TRuleType> NotHaveAnyAttributesThat();
}
Expand Down
4 changes: 2 additions & 2 deletions ArchUnitNET/Fluent/Syntax/Elements/Members/MembersShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public TRuleTypeShouldConjunction BeDeclaredIn(IEnumerable<Type> types)

public ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType> BeDeclaredInTypesThat()
{
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(),
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(true),
MemberConditionsDefinition<TRuleType>.BeDeclaredInTypesThat());
return new ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType>(_ruleCreator);
}
Expand Down Expand Up @@ -130,7 +130,7 @@ public TRuleTypeShouldConjunction NotBeDeclaredIn(IEnumerable<Type> types)

public ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType> NotBeDeclaredInTypesThat()
{
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(),
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(true),
MemberConditionsDefinition<TRuleType>.NotBeDeclaredInTypesThat());
return new ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType>(_ruleCreator);
}
Expand Down
15 changes: 1 addition & 14 deletions ArchUnitNET/Fluent/Syntax/Elements/ObjectConditionsDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1089,13 +1089,7 @@ public static ICondition<TRuleType> BePrivateProtected()


//Relation Conditions


public static RelationCondition<TRuleType, MethodMember> CallAnyMethodsThat()
{
return new RelationCondition<TRuleType, MethodMember>(CallAny, "call any methods that",
"does not call any methods that");
}


public static RelationCondition<TRuleType, IType> DependOnAnyTypesThat()
{
Expand Down Expand Up @@ -1828,13 +1822,6 @@ public static ICondition<TRuleType> NotBePrivateProtected()

//Relation Condition Negations


public static RelationCondition<TRuleType, MethodMember> NotCallAnyMethodsThat()
{
return new RelationCondition<TRuleType, MethodMember>(NotCallAny, "not call any methods that",
"does call any methods that");
}

public static RelationCondition<TRuleType, IType> NotDependOnAnyTypesThat()
{
return new RelationCondition<TRuleType, IType>(NotDependOnAny, "not depend on any types that",
Expand Down
30 changes: 7 additions & 23 deletions ArchUnitNET/Fluent/Syntax/Elements/ObjectsShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.Collections.Generic;
using ArchUnitNET.Domain;
using ArchUnitNET.Fluent.Conditions;
using ArchUnitNET.Fluent.Syntax.Elements.Members.MethodMembers;
using ArchUnitNET.Fluent.Syntax.Elements.Types;
using ArchUnitNET.Fluent.Syntax.Elements.Types.Attributes;
using static ArchUnitNET.Fluent.Syntax.ConjunctionFactory;
Expand Down Expand Up @@ -388,37 +387,30 @@ public TRuleTypeShouldConjunction BePrivateProtected()

//Relation Conditions

public ShouldRelateToMethodMembersThat<TRuleTypeShouldConjunction, TRuleType> CallAnyMethodsThat()
{
_ruleCreator.BeginComplexCondition(MethodMembers(),
ObjectConditionsDefinition<TRuleType>.CallAnyMethodsThat());
return new ShouldRelateToMethodMembersThat<TRuleTypeShouldConjunction, TRuleType>(_ruleCreator);
}

public ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType> DependOnAnyTypesThat()
{
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(),
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(true),
ObjectConditionsDefinition<TRuleType>.DependOnAnyTypesThat());
return new ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType>(_ruleCreator);
}

public ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType> OnlyDependOnTypesThat()
{
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(),
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(true),
ObjectConditionsDefinition<TRuleType>.OnlyDependOnTypesThat());
return new ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType>(_ruleCreator);
}

public ShouldRelateToAttributesThat<TRuleTypeShouldConjunction, TRuleType> HaveAnyAttributesThat()
{
_ruleCreator.BeginComplexCondition(Attributes(),
_ruleCreator.BeginComplexCondition(Attributes(true),
ObjectConditionsDefinition<TRuleType>.HaveAnyAttributesThat());
return new ShouldRelateToAttributesThat<TRuleTypeShouldConjunction, TRuleType>(_ruleCreator);
}

public ShouldRelateToAttributesThat<TRuleTypeShouldConjunction, TRuleType> OnlyHaveAttributesThat()
{
_ruleCreator.BeginComplexCondition(Attributes(),
_ruleCreator.BeginComplexCondition(Attributes(true),
ObjectConditionsDefinition<TRuleType>.OnlyHaveAttributesThat());
return new ShouldRelateToAttributesThat<TRuleTypeShouldConjunction, TRuleType>(_ruleCreator);
}
Expand Down Expand Up @@ -675,25 +667,17 @@ public TRuleTypeShouldConjunction NotBePrivateProtected()
}

//Relation Condition Negations


public ShouldRelateToMethodMembersThat<TRuleTypeShouldConjunction, TRuleType> NotCallAnyMethodsThat()
{
_ruleCreator.BeginComplexCondition(MethodMembers(),
ObjectConditionsDefinition<TRuleType>.NotCallAnyMethodsThat());
return new ShouldRelateToMethodMembersThat<TRuleTypeShouldConjunction, TRuleType>(_ruleCreator);
}


public ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType> NotDependOnAnyTypesThat()
{
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(),
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(true),
ObjectConditionsDefinition<TRuleType>.NotDependOnAnyTypesThat());
return new ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType>(_ruleCreator);
}

public ShouldRelateToAttributesThat<TRuleTypeShouldConjunction, TRuleType> NotHaveAnyAttributesThat()
{
_ruleCreator.BeginComplexCondition(Attributes(),
_ruleCreator.BeginComplexCondition(Attributes(true),
ObjectConditionsDefinition<TRuleType>.NotHaveAnyAttributesThat());
return new ShouldRelateToAttributesThat<TRuleTypeShouldConjunction, TRuleType>(_ruleCreator);
}
Expand Down
4 changes: 2 additions & 2 deletions ArchUnitNET/Fluent/Syntax/Elements/Types/TypesShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public TRuleTypeShouldConjunction BeNested()

public ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType> BeAssignableToTypesThat()
{
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(),
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(true),
TypeConditionsDefinition<TRuleType>.BeAssignableToTypesThat());
return new ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType>(_ruleCreator);
}
Expand Down Expand Up @@ -301,7 +301,7 @@ public TRuleTypeShouldConjunction NotBeNested()

public ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType> NotBeAssignableToTypesThat()
{
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(),
_ruleCreator.BeginComplexCondition(ArchRuleDefinition.Types(true),
TypeConditionsDefinition<TRuleType>.NotBeAssignableToTypesThat());
return new ShouldRelateToTypesThat<TRuleTypeShouldConjunction, IType, TRuleType>(_ruleCreator);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright 2019 Florian Gather <[email protected]>
// Copyright 2019 Fritz Brandhuber <[email protected]>
// Copyright 2020 Pavel Fischer <[email protected]>
//
// SPDX-License-Identifier: Apache-2.0
//

using ArchUnitNET.Domain;
using ArchUnitNET.Domain.Extensions;
using ArchUnitNET.Loader;
using ArchUnitNET.xUnit;
using TestAssembly.DependencyTargets;
using Xunit;
using static ArchUnitNET.Fluent.ArchRuleDefinition;

namespace ArchUnitNETTests.Fluent.Syntax
{
public class DependenciesToOtherAssembliesTests
{
public class TestDependencyIssue
{
private static readonly Architecture Architecture =
new ArchLoader().LoadAssemblies(typeof(DependenciesToOtherAssembliesTests).Assembly).Build();

[Fact]
public void DependOnAnyTypesThatTest()
{
Types().That().Are(typeof(DependingClass)).Should()
.DependOnAnyTypesThat().Are(typeof(ClassInTestAssembly)).Check(Architecture);
Assert.Throws<FailedArchRuleException>(() => Types().That().Are(typeof(DependingClass)).Should()
.NotDependOnAnyTypesThat().Are(typeof(ClassInTestAssembly)).Check(Architecture));
}

[Fact]
public void BeAssignableToTypesThatTest()
{
Types().That().Are(typeof(DependingClass)).Should()
.BeAssignableToTypesThat().Are(typeof(IInterfaceInTestAssembly)).Check(Architecture);
Assert.Throws<FailedArchRuleException>(() => Types().That().Are(typeof(DependingClass)).Should()
.NotBeAssignableToTypesThat().Are(typeof(IInterfaceInTestAssembly)).Check(Architecture));
}

[Fact]
public void OnlyDependOnTypesThatTest()
{
Types().That().Are(typeof(DependingClass)).Should()
.OnlyDependOnTypesThat().Are(typeof(object), typeof(AttributeInTestAssembly),
typeof(IInterfaceInTestAssembly), typeof(ClassInTestAssembly), typeof(DependingClass))
.Check(Architecture);
}

[Fact]
public void HaveAnyAttributesThatTest()
{
Types().That().Are(typeof(DependingClass)).Should()
.HaveAnyAttributesThat().Are(typeof(AttributeInTestAssembly)).Check(Architecture);
Assert.Throws<FailedArchRuleException>(() => Types().That().Are(typeof(DependingClass)).Should()
.NotHaveAnyAttributesThat().Are(typeof(AttributeInTestAssembly)).Check(Architecture));
}

[Fact]
public void OnlyHaveAttributesThatTest()
{
Types().That().Are(typeof(DependingClass)).Should()
.OnlyHaveAttributesThat().Are(typeof(AttributeInTestAssembly)).Check(Architecture);
}

[Fact]
public void IncludeReferencedTypesTest()
{
var classInTestAssembly = Architecture.GetClassOfType(typeof(ClassInTestAssembly));
Assert.Contains(classInTestAssembly, Types(true).GetObjects(Architecture));
Assert.Contains(classInTestAssembly, Classes(true).GetObjects(Architecture));

var attributeInTestAssembly = Architecture.GetAttributeOfType(typeof(AttributeInTestAssembly));
Assert.Contains(attributeInTestAssembly, Types(true).GetObjects(Architecture));
Assert.Contains(attributeInTestAssembly, Attributes(true).GetObjects(Architecture));

var interfaceInTestAssembly = Architecture.GetInterfaceOfType(typeof(IInterfaceInTestAssembly));
Assert.Contains(interfaceInTestAssembly, Types(true).GetObjects(Architecture));
Assert.Contains(interfaceInTestAssembly, Interfaces(true).GetObjects(Architecture));
}
}
}

[AttributeInTestAssembly]
public class DependingClass : IInterfaceInTestAssembly
{
private ClassInTestAssembly dep;

public DependingClass()
{
dep = new ClassInTestAssembly();
dep.MethodInTestAssembly();
}
}
}
15 changes: 15 additions & 0 deletions TestAssembly/DependencyTargets/AttributeInTestAssembly.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2019 Florian Gather <[email protected]>
// Copyright 2019 Fritz Brandhuber <[email protected]>
// Copyright 2020 Pavel Fischer <[email protected]>
//
// SPDX-License-Identifier: Apache-2.0
//

using System;

namespace TestAssembly.DependencyTargets
{
public class AttributeInTestAssembly : Attribute
{
}
}
14 changes: 14 additions & 0 deletions TestAssembly/DependencyTargets/ClassInTestAssembly.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2019 Florian Gather <[email protected]>
// Copyright 2019 Fritz Brandhuber <[email protected]>
// Copyright 2020 Pavel Fischer <[email protected]>
//
// SPDX-License-Identifier: Apache-2.0
//

namespace TestAssembly.DependencyTargets
{
public class ClassInTestAssembly
{
public void MethodInTestAssembly(){}
}
}
13 changes: 13 additions & 0 deletions TestAssembly/DependencyTargets/IInterfaceInTestAssembly.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2019 Florian Gather <[email protected]>
// Copyright 2019 Fritz Brandhuber <[email protected]>
// Copyright 2020 Pavel Fischer <[email protected]>
//
// SPDX-License-Identifier: Apache-2.0
//

namespace TestAssembly.DependencyTargets
{
public interface IInterfaceInTestAssembly
{
}
}
Loading

0 comments on commit 7bd1cac

Please sign in to comment.