Skip to content

Commit 6a090a5

Browse files
added Fluent Syntax for classes that are records
1 parent 98f7f0e commit 6a090a5

File tree

8 files changed

+105
-3
lines changed

8 files changed

+105
-3
lines changed

ArchUnitNET/Domain/Class.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,20 @@ public class Class : IType
1616
{
1717
private IType Type { get; }
1818

19-
public Class(IType type, bool? isAbstract = null, bool? isSealed = null)
19+
public Class(IType type, bool? isAbstract = null, bool? isSealed = null, bool? isRecord = null)
2020
{
2121
Type = type;
2222
IsAbstract = isAbstract;
2323
IsSealed = isSealed;
24+
IsRecord = isRecord;
2425
}
2526

2627
public Class(Class @class)
2728
{
2829
Type = @class.Type;
2930
IsAbstract = @class.IsAbstract;
3031
IsSealed = @class.IsSealed;
32+
IsRecord = @class.IsRecord;
3133
}
3234

3335
public IEnumerable<ITypeDependency> DependenciesIncludingInherited =>
@@ -47,6 +49,7 @@ public Class(Class @class)
4749
public IEnumerable<MethodMember> Constructors => Type.GetConstructors();
4850
public bool? IsAbstract { get; }
4951
public bool? IsSealed { get; }
52+
public bool? IsRecord { get; }
5053

5154
public IEnumerable<Class> InheritedClasses =>
5255
BaseClass == null
@@ -86,7 +89,8 @@ private bool Equals(Class other)
8689
{
8790
return Equals(Type, other.Type)
8891
&& Equals(IsAbstract, other.IsAbstract)
89-
&& Equals(IsSealed, other.IsSealed);
92+
&& Equals(IsSealed, other.IsSealed)
93+
&& Equals(IsRecord, other.IsRecord);
9094
}
9195

9296
public override bool Equals(object obj)
@@ -111,6 +115,7 @@ public override int GetHashCode()
111115
var hashCode = Type != null ? Type.GetHashCode() : 0;
112116
hashCode = (hashCode * 397) ^ IsAbstract.GetHashCode();
113117
hashCode = (hashCode * 397) ^ IsSealed.GetHashCode();
118+
hashCode = (hashCode * 397) ^ IsRecord.GetHashCode();
114119
return hashCode;
115120
}
116121
}

ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassConditionsDefinition.cs

+17
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ public static ICondition<Class> BeSealed()
3030
);
3131
}
3232

33+
public static ICondition<Class> BeRecord()
34+
{
35+
return new SimpleCondition<Class>(
36+
cls => !cls.IsRecord.HasValue || cls.IsRecord.Value,
37+
"be record",
38+
"is not record"
39+
);
40+
}
41+
3342
public static ICondition<Class> BeImmutable()
3443
{
3544
return new SimpleCondition<Class>(
@@ -61,6 +70,14 @@ public static ICondition<Class> NotBeSealed()
6170
"is sealed"
6271
);
6372
}
73+
public static ICondition<Class> NotBeRecord()
74+
{
75+
return new SimpleCondition<Class>(
76+
cls => !cls.IsRecord.HasValue || !cls.IsRecord.Value,
77+
"not be record",
78+
"is record"
79+
);
80+
}
6481

6582
public static ICondition<Class> NotBeImmutable()
6683
{

ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassPredicatesDefinition.cs

+16
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ public static IPredicate<Class> AreSealed()
2828
);
2929
}
3030

31+
public static IPredicate<Class> AreRecord()
32+
{
33+
return new SimplePredicate<Class>(
34+
cls => !cls.IsRecord.HasValue || cls.IsRecord.Value,
35+
"are record"
36+
);
37+
}
38+
3139
public static IPredicate<Class> AreImmutable()
3240
{
3341
return new SimplePredicate<Class>(
@@ -56,6 +64,14 @@ public static IPredicate<Class> AreNotSealed()
5664
);
5765
}
5866

67+
public static IPredicate<Class> AreNotRecord()
68+
{
69+
return new SimplePredicate<Class>(
70+
cls => !cls.IsRecord.HasValue || !cls.IsRecord.Value,
71+
"are not record"
72+
);
73+
}
74+
5975
public static IPredicate<Class> AreNotImmutable()
6076
{
6177
return new SimplePredicate<Class>(

ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/ClassesShould.cs

+12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ public ClassesShouldConjunction BeSealed()
2727
return new ClassesShouldConjunction(_ruleCreator);
2828
}
2929

30+
public ClassesShouldConjunction BeRecord()
31+
{
32+
_ruleCreator.AddCondition(ClassConditionsDefinition.BeRecord());
33+
return new ClassesShouldConjunction(_ruleCreator);
34+
}
35+
3036
public ClassesShouldConjunction BeImmutable()
3137
{
3238
_ruleCreator.AddCondition(ClassConditionsDefinition.BeImmutable());
@@ -48,6 +54,12 @@ public ClassesShouldConjunction NotBeSealed()
4854
return new ClassesShouldConjunction(_ruleCreator);
4955
}
5056

57+
public ClassesShouldConjunction NotBeRecord()
58+
{
59+
_ruleCreator.AddCondition(ClassConditionsDefinition.NotBeRecord());
60+
return new ClassesShouldConjunction(_ruleCreator);
61+
}
62+
5163
public ClassesShouldConjunction NotBeImmutable()
5264
{
5365
_ruleCreator.AddCondition(ClassConditionsDefinition.NotBeImmutable());

ArchUnitNET/Fluent/Syntax/Elements/Types/Classes/GivenClassesThat.cs

+12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ public GivenClassesConjunction AreSealed()
2727
return new GivenClassesConjunction(_ruleCreator);
2828
}
2929

30+
public GivenClassesConjunction AreRecord()
31+
{
32+
_ruleCreator.AddPredicate(ClassPredicatesDefinition.AreRecord());
33+
return new GivenClassesConjunction(_ruleCreator);
34+
}
35+
3036
public GivenClassesConjunction AreImmutable()
3137
{
3238
_ruleCreator.AddPredicate(ClassPredicatesDefinition.AreImmutable());
@@ -48,6 +54,12 @@ public GivenClassesConjunction AreNotSealed()
4854
return new GivenClassesConjunction(_ruleCreator);
4955
}
5056

57+
public GivenClassesConjunction AreNotRecord()
58+
{
59+
_ruleCreator.AddPredicate(ClassPredicatesDefinition.AreNotRecord());
60+
return new GivenClassesConjunction(_ruleCreator);
61+
}
62+
5163
public GivenClassesConjunction AreNotImmutable()
5264
{
5365
_ruleCreator.AddPredicate(ClassPredicatesDefinition.AreNotImmutable());

ArchUnitNET/Loader/MonoCecilTypeExtensions.cs

+7
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
//
77

88
using System;
9+
using System.Linq;
910
using ArchUnitNET.Domain;
1011
using JetBrains.Annotations;
1112
using Mono.Cecil;
13+
using Mono.Cecil.Rocks;
1214
using static ArchUnitNET.Domain.Visibility;
1315
using GenericParameter = Mono.Cecil.GenericParameter;
1416

@@ -102,5 +104,10 @@ internal static Visibility GetVisibility([CanBeNull] this TypeDefinition typeDef
102104
"The provided type definition seems to have no visibility."
103105
);
104106
}
107+
108+
internal static bool IsRecord(this TypeDefinition typeDefinition)
109+
{
110+
return typeDefinition.IsClass && typeDefinition.GetMethods().Any(x => x.Name == "<Clone>$");
111+
}
105112
}
106113
}

ArchUnitNET/Loader/TypeFactory.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ bool isStub
353353
else
354354
{
355355
createdTypeInstance = new TypeInstance<Class>(
356-
new Class(type, typeDefinition.IsAbstract, typeDefinition.IsSealed)
356+
new Class(type, typeDefinition.IsAbstract, typeDefinition.IsSealed, typeDefinition.IsRecord())
357357
);
358358
}
359359

ArchUnitNETTests/Fluent/Syntax/Elements/ClassSyntaxElementsTests.cs

+33
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,39 @@ public void AreImmutableTest()
230230
Assert.True(notImmutableClassesAreNotImmutabled.HasNoViolations(Architecture));
231231
}
232232

233+
[Fact]
234+
public void AreRecordTest()
235+
{
236+
var recordsAreRecord = Classes()
237+
.That()
238+
.AreRecord()
239+
.Should()
240+
.BeRecord();
241+
242+
var recordsAreNotRecord = Classes()
243+
.That()
244+
.AreRecord()
245+
.Should()
246+
.NotBeRecord();
247+
248+
var notRecordsAreRecord = Classes()
249+
.That()
250+
.AreNotRecord()
251+
.Should()
252+
.BeRecord();
253+
254+
var notRecordsAreNotRecord = Classes()
255+
.That()
256+
.AreNotRecord()
257+
.Should()
258+
.NotBeRecord();
259+
260+
Assert.True(recordsAreRecord.HasNoViolations(Architecture));
261+
Assert.False(recordsAreNotRecord.HasNoViolations(Architecture));
262+
Assert.False(notRecordsAreRecord.HasNoViolations(Architecture));
263+
Assert.True(notRecordsAreNotRecord.HasNoViolations(Architecture));
264+
}
265+
233266
private record ImmutableRecord(string Property, string AnotherProperty);
234267

235268
private class ImmutableClass

0 commit comments

Comments
 (0)