Skip to content

Commit ef62a15

Browse files
committed
The one with slices
1 parent cde5a75 commit ef62a15

25 files changed

Lines changed: 698 additions & 135 deletions

src/NetArchTest.Rules/Assemblies/TypeSpec.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ public TypeSpec(TypeDefinition definition)
1515
}
1616

1717

18+
19+
public TypeWrapper CreateWrapper()
20+
{
21+
return new TypeWrapper(Definition);
22+
}
23+
24+
1825
public static implicit operator TypeDefinition(TypeSpec type)
1926
{
2027
return type.Definition;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Diagnostics;
3+
using Mono.Cecil;
4+
using NetArchTest.Rules.Extensions;
5+
6+
namespace NetArchTest.Rules.Assemblies
7+
{
8+
/// <summary>
9+
/// Type wrapper.
10+
/// </summary>
11+
[DebuggerDisplay("{FullName}")]
12+
internal sealed class TypeWrapper : IType
13+
{
14+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
15+
private readonly TypeDefinition _monoTypeDefinition;
16+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
17+
private readonly Lazy<Type> _type;
18+
19+
internal TypeWrapper(TypeDefinition monoTypeDefinition)
20+
{
21+
_monoTypeDefinition = monoTypeDefinition;
22+
_type = new Lazy<Type>(() =>
23+
{
24+
Type type = null;
25+
try
26+
{
27+
type = _monoTypeDefinition.ToType();
28+
}
29+
catch { }
30+
return type;
31+
});
32+
}
33+
34+
/// <summary>
35+
/// System.Type
36+
/// </summary>
37+
/// <remarks>
38+
/// This property may be null if the test project does not have a direct dependency on the type.
39+
/// </remarks>
40+
public Type Type { get => _type.Value; }
41+
42+
/// <summary>
43+
/// FullName of the type
44+
/// </summary>
45+
public string FullName { get => _monoTypeDefinition.FullName; }
46+
47+
/// <summary>
48+
/// Name of the type
49+
/// </summary>
50+
public string Name { get => _monoTypeDefinition.Name; }
51+
52+
53+
public static implicit operator System.Type(TypeWrapper type)
54+
{
55+
return type.Type;
56+
}
57+
}
58+
}

src/NetArchTest.Rules/ConditionList.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,14 @@ public TestResult GetResult()
6161
/// Returns the list of types that satisfy the conditions.
6262
/// </summary>
6363
/// <returns>A list of types.</returns>
64-
public IEnumerable<Type> GetTypes()
64+
public IEnumerable<IType> GetTypes()
6565
{
66-
return _sequence.Execute(_types).Select(t => t.Definition.ToType());
66+
return _sequence.Execute(_types).Select(t => t.CreateWrapper());
67+
}
68+
69+
internal IEnumerable<Type> GetNetTypes()
70+
{
71+
return GetTypes().Select(x => x.Type);
6772
}
6873

6974
/// <summary>

src/NetArchTest.Rules/IType.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace NetArchTest.Rules
6+
{
7+
/// <summary>
8+
/// Type wrapper.
9+
/// </summary>
10+
public interface IType
11+
{
12+
/// <summary>
13+
/// System.Type
14+
/// </summary>
15+
/// <remarks>
16+
/// This property may be null if the test project does not have a direct dependency on the type.
17+
/// </remarks>
18+
Type Type { get; }
19+
20+
/// <summary>
21+
/// FullName of the type
22+
/// </summary>
23+
string FullName { get; }
24+
25+
/// <summary>
26+
/// Name of the type
27+
/// </summary>
28+
string Name { get; }
29+
}
30+
}

src/NetArchTest.Rules/Policies/PolicyResult.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
using System;
44
using System.Collections.Generic;
5+
using NetArchTest.Rules.Assemblies;
56

67
/// <summary>
78
/// A single test result for a policy.
@@ -27,7 +28,7 @@ internal PolicyResult(TestResult result, string name, string description)
2728
/// <summary>
2829
/// Gets a collection populated with a list of any types that failed the test.
2930
/// </summary>
30-
public IEnumerable<Type> FailingTypes { get; private set; }
31+
public IEnumerable<IType> FailingTypes { get; private set; }
3132

3233
/// <summary>
3334
/// Gets the simple name associated with the test.

src/NetArchTest.Rules/PredicateList.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using NetArchTest.Rules.Assemblies;
55
using NetArchTest.Rules.Extensions;
6+
using NetArchTest.Rules.Slices;
67

78
namespace NetArchTest.Rules
89
{
@@ -44,21 +45,31 @@ public Condition ShouldNot()
4445
}
4546

4647
/// <summary>
47-
/// Returns the type definitions returned by these predicate.
48+
/// Allows dividing types into groups, also called slices.
4849
/// </summary>
49-
/// <returns>A list of type definitions.</returns>
50+
/// <returns></returns>
51+
public SlicePredicate Slice()
52+
{
53+
return new SlicePredicate(GetTypeSpecifications());
54+
}
55+
56+
5057
internal IEnumerable<TypeSpec> GetTypeSpecifications()
5158
{
5259
return _sequence.Execute(_types);
5360
}
61+
internal IEnumerable<Type> GetNetTypes()
62+
{
63+
return GetTypes().Select(x => x.Type);
64+
}
5465

5566
/// <summary>
5667
/// Returns the types returned by these predicates.
5768
/// </summary>
5869
/// <returns>A list of types.</returns>
59-
public IEnumerable<Type> GetTypes()
70+
public IEnumerable<IType> GetTypes()
6071
{
61-
return GetTypeSpecifications().Select(t => t.Definition.ToType());
72+
return GetTypeSpecifications().Select(t => t.CreateWrapper());
6273
}
6374

6475
/// <summary>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using NetArchTest.Rules.Assemblies;
4+
using NetArchTest.Rules.Dependencies;
5+
6+
namespace NetArchTest.Rules.Slices.Model
7+
{
8+
internal sealed class HaveDependenciesBetweenSlices : IFilter
9+
{
10+
public IEnumerable<TypeTestResult> Execute(SlicedTypes slicedTypes)
11+
{
12+
var dependencySearch = new DependencySearch();
13+
var result = new List<TypeTestResult>(slicedTypes.TypeCount);
14+
15+
for (int i = 0; i < slicedTypes.Slices.Count; i++)
16+
{
17+
var slice = slicedTypes.Slices[i];
18+
var dependencies = slicedTypes.Slices.Where((_, index) => index != i).Select(x => x.Name).ToList();
19+
20+
var foundTypes = dependencySearch.FindTypesThatHaveDependencyOnAny(slice.Types, dependencies);
21+
var lookup = new HashSet<TypeSpec>(foundTypes);
22+
23+
foreach (var type in slice.Types)
24+
{
25+
bool isPassing = lookup.Contains(type);
26+
var typeResult = new TypeTestResult(type, isPassing);
27+
result.Add(typeResult);
28+
}
29+
}
30+
31+
return result;
32+
}
33+
}
34+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Collections.Generic;
2+
3+
namespace NetArchTest.Rules.Slices.Model
4+
{
5+
internal interface IFilter
6+
{
7+
IEnumerable<TypeTestResult> Execute(SlicedTypes slicedTypes);
8+
}
9+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System.Collections.Generic;
2+
using NetArchTest.Rules.Assemblies;
3+
4+
namespace NetArchTest.Rules.Slices.Model
5+
{
6+
internal sealed class Slice
7+
{
8+
public string Name { get; }
9+
public IEnumerable<TypeSpec> Types { get; }
10+
11+
12+
public Slice(string sliceName, List<TypeSpec> types)
13+
{
14+
Name = sliceName;
15+
Types = types;
16+
}
17+
}
18+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Collections.Generic;
2+
3+
namespace NetArchTest.Rules.Slices.Model
4+
{
5+
internal sealed class SlicedTypes
6+
{
7+
public int TypeCount { get; }
8+
public IReadOnlyList<Slice> Slices { get; }
9+
10+
11+
public SlicedTypes(int typeCount, List<Slice> slices)
12+
{
13+
TypeCount = typeCount;
14+
Slices = slices;
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)