Skip to content

Commit 39b75c5

Browse files
committed
add rules: AreUsedByAny, AreNotUsedByAny, BeUsedByAny, NotBeUsedByAny
1 parent d0e74fc commit 39b75c5

File tree

9 files changed

+286
-75
lines changed

9 files changed

+286
-75
lines changed

sources/NetArchTest/Condition_Dependencies.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,28 @@ public ConditionList HaveDependencyOtherThan(params string[] dependencies)
6969
AddFunctionCall((context, inputTypes) => FunctionDelegates.OnlyHaveDependenciesOnAnyOrNone(context, inputTypes, dependencies, false));
7070
return CreateConditionList();
7171
}
72+
73+
74+
/// <summary>
75+
/// Selects types that are used by any of the supplied types.
76+
/// </summary>
77+
/// <param name="users">The types to match against. These can be namespaces or specific types.</param>
78+
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
79+
public ConditionList BeUsedByAny(params string[] users)
80+
{
81+
AddFunctionCall((context, inputTypes) => FunctionDelegates.AreUsedByAny(context, inputTypes, users, true));
82+
return CreateConditionList();
83+
}
84+
85+
/// <summary>
86+
/// Selects types that are not used by any of the particular types.
87+
/// </summary>
88+
/// <param name="users">The types to match against. These can be namespaces or specific types.</param>
89+
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
90+
public ConditionList NotBeUsedByAny(params string[] users)
91+
{
92+
AddFunctionCall((context, inputTypes) => FunctionDelegates.AreUsedByAny(context, inputTypes, users, false));
93+
return CreateConditionList();
94+
}
7295
}
7396
}
Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using NetArchTest.Assemblies;
35
using NetArchTest.Dependencies.DataStructures;
46
using NetArchTest.Rules;
@@ -13,63 +15,93 @@ internal class DependencySearch
1315
private readonly bool explainYourself;
1416
private readonly IDependencyFilter dependencyFilter;
1517

18+
1619
public DependencySearch(bool explainYourself, IDependencyFilter dependencyFilter = null)
1720
{
1821
this.explainYourself = explainYourself;
1922
this.dependencyFilter = dependencyFilter;
2023
}
2124

25+
2226
/// <summary>
2327
/// Finds types that have a dependency on any item in the given list of dependencies.
2428
/// </summary>
2529
public IEnumerable<TypeSpec> FindTypesThatHaveDependencyOnAny(IEnumerable<TypeSpec> input, IEnumerable<string> dependencies)
2630
{
27-
return FindTypes(input, TypeDefinitionCheckingResult.SearchType.HaveDependencyOnAny, dependencies, true);
31+
return FindTypes(input, HaveDependency_CheckingStrategy.TypeOfCheck.HaveDependencyOnAny, dependencies, true);
2832
}
2933

3034
/// <summary>
3135
/// Finds types that have a dependency on every item in the given list of dependencies.
3236
/// </summary>
3337
public IEnumerable<TypeSpec> FindTypesThatHaveDependencyOnAll(IEnumerable<TypeSpec> input, IEnumerable<string> dependencies)
3438
{
35-
return FindTypes(input, TypeDefinitionCheckingResult.SearchType.HaveDependencyOnAll, dependencies, true);
39+
return FindTypes(input, HaveDependency_CheckingStrategy.TypeOfCheck.HaveDependencyOnAll, dependencies, true);
3640
}
3741

3842
/// <summary>
3943
/// Finds types that may have a dependency on any item in the given list of dependencies, but cannot have a dependency that is not in the list.
4044
/// </summary>
4145
public IEnumerable<TypeSpec> FindTypesThatOnlyHaveDependencyOnAnyOrNone(IEnumerable<TypeSpec> input, IEnumerable<string> dependencies)
4246
{
43-
return FindTypes(input, TypeDefinitionCheckingResult.SearchType.OnlyHaveDependenciesOnAnyOrNone, dependencies, false);
47+
return FindTypes(input, HaveDependency_CheckingStrategy.TypeOfCheck.OnlyHaveDependenciesOnAnyOrNone, dependencies, false);
4448
}
4549

4650
/// <summary>
4751
/// Finds types that have a dependency on any item in the given list of dependencies, but cannot have a dependency that is not in the list.
4852
/// </summary>
4953
public IEnumerable<TypeSpec> FindTypesThatOnlyHaveDependencyOnAny(IEnumerable<TypeSpec> input, IEnumerable<string> dependencies)
5054
{
51-
return FindTypes(input, TypeDefinitionCheckingResult.SearchType.OnlyHaveDependenciesOnAny, dependencies, false);
55+
return FindTypes(input, HaveDependency_CheckingStrategy.TypeOfCheck.OnlyHaveDependenciesOnAny, dependencies, false);
5256
}
5357

5458
/// <summary>
5559
/// Finds types that have a dependency on every item in the given list of dependencies, but cannot have a dependency that is not in the list.
5660
/// </summary>
5761
public IEnumerable<TypeSpec> FindTypesThatOnlyOnlyHaveDependencyOnAll(IEnumerable<TypeSpec> input, IEnumerable<string> dependencies)
5862
{
59-
return FindTypes(input, TypeDefinitionCheckingResult.SearchType.OnlyHaveDependenciesOnAll, dependencies, false);
63+
return FindTypes(input, HaveDependency_CheckingStrategy.TypeOfCheck.OnlyHaveDependenciesOnAll, dependencies, false);
6064
}
6165

62-
private IEnumerable<TypeSpec> FindTypes(IEnumerable<TypeSpec> input, TypeDefinitionCheckingResult.SearchType searchType, IEnumerable<string> dependencies, bool serachForDependencyInFieldConstant)
66+
private IEnumerable<TypeSpec> FindTypes(IEnumerable<TypeSpec> input, HaveDependency_CheckingStrategy.TypeOfCheck typeOfCheck, IEnumerable<string> dependencies, bool serachForDependencyInFieldConstant)
6367
{
64-
var searchTree = new CachedNamespaceTree(dependencies);
68+
var searchTree = new CachedNamespaceTree(dependencies);
69+
var context = new TypeCheckingContext(serachForDependencyInFieldConstant, explainYourself, dependencyFilter);
6570

6671
foreach (var type in input)
6772
{
68-
var context = new TypeDefinitionCheckingContext(type, searchType, searchTree, serachForDependencyInFieldConstant, explainYourself, dependencyFilter);
69-
type.IsPassing = context.IsTypeFound();
73+
var strategy = new HaveDependency_CheckingStrategy(typeOfCheck, searchTree);
74+
context.PerformCheck(type, strategy);
75+
type.IsPassing = strategy.DoesTypePassCheck();
76+
}
77+
78+
return input;
79+
}
80+
81+
82+
public IEnumerable<TypeSpec> FindTypesThatAreUsedByAny(IEnumerable<TypeSpec> input, IEnumerable<string> users, IEnumerable<TypeSpec> allTypes)
83+
{
84+
var filterTree = new CachedNamespaceTree(users);
85+
var context = new TypeCheckingContext(false, explainYourself, dependencyFilter);
86+
var strategy = new AreUsedBy_CheckingStrategy();
87+
88+
89+
foreach (var type in allTypes)
90+
{
91+
bool shouldBeChecked = filterTree.GetAllMatchingNames(type.Definition).Any();
92+
93+
if (shouldBeChecked)
94+
{
95+
context.PerformCheck(type, strategy);
96+
}
97+
}
98+
99+
foreach (var type in input)
100+
{
101+
type.IsPassing = strategy.IsTypeUsed(type.Definition);
70102
}
71103

72104
return input;
73-
}
105+
}
74106
}
75107
}

sources/NetArchTest/Dependencies/TypeDefinitionCheckingContext.cs renamed to sources/NetArchTest/Dependencies/TypeCheckingContext.cs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,36 @@
11
using Mono.Cecil;
22
using NetArchTest.Assemblies;
3-
using NetArchTest.Dependencies.DataStructures;
43
using NetArchTest.Rules;
54

65
namespace NetArchTest.Dependencies
76
{
8-
internal class TypeDefinitionCheckingContext
9-
{
10-
private readonly TypeSpec _typeToCheck;
11-
private readonly TypeDefinitionCheckingResult _result;
7+
internal class TypeCheckingContext
8+
{
129
private readonly bool _serachForDependencyInFieldConstant;
1310
private readonly bool explainYourself;
1411
private readonly IDependencyFilter dependencyFilter;
12+
private TypeSpec _typeToCheck;
13+
private ITypeCheckingStrategy _result;
1514

16-
public TypeDefinitionCheckingContext(TypeSpec typeToCheck, TypeDefinitionCheckingResult.SearchType searchType, ISearchTree searchTree, bool serachForDependencyInFieldConstant = false, bool explainYourself = false, IDependencyFilter dependencyFilter = null)
17-
{
18-
_typeToCheck = typeToCheck;
19-
_result = new TypeDefinitionCheckingResult(searchType, searchTree);
15+
16+
public TypeCheckingContext(bool serachForDependencyInFieldConstant = false, bool explainYourself = false, IDependencyFilter dependencyFilter = null)
17+
{
2018
_serachForDependencyInFieldConstant = serachForDependencyInFieldConstant;
2119
this.explainYourself = explainYourself;
2220
this.dependencyFilter = dependencyFilter;
2321
}
2422

25-
public bool IsTypeFound()
23+
24+
public void PerformCheck(TypeSpec typeToCheck, ITypeCheckingStrategy checkingStrategy)
2625
{
26+
_typeToCheck = typeToCheck;
27+
_result = checkingStrategy;
28+
2729
CheckType(_typeToCheck.Definition);
2830
if (explainYourself)
2931
{
3032
_typeToCheck.Explanation = _result.ExplainWhy();
31-
}
32-
return _result.IsTypeFound();
33+
}
3334
}
3435

3536

@@ -106,7 +107,7 @@ private void CheckFields(TypeDefinition typeToCheck)
106107
CheckTypeReference(field.FieldType);
107108
if (_serachForDependencyInFieldConstant && field.HasConstant && field.FieldType.FullName == typeof(string).FullName)
108109
{
109-
_result.CheckDependency(field.Constant.ToString());
110+
_result.CheckType(field.Constant.ToString());
110111
}
111112
}
112113
}
@@ -287,15 +288,13 @@ private void CheckTypeReference(TypeReference reference)
287288
}
288289
}
289290
private void CheckDependency(TypeReference dependency)
290-
{
291-
if (dependencyFilter != null)
291+
{
292+
if (dependencyFilter?.ShouldDependencyBeChecked(dependency) == false)
292293
{
293-
if (dependencyFilter.ShouldDependencyBeChecked(dependency) == false)
294-
{
295-
return;
296-
}
297-
}
298-
_result.CheckDependency(dependency);
294+
return;
295+
}
296+
297+
_result.CheckType(dependency);
299298
}
300299
}
301300
}

0 commit comments

Comments
 (0)