1
1
package org .kohsuke .github ;
2
2
3
3
import com .tngtech .archunit .base .DescribedPredicate ;
4
+ import com .tngtech .archunit .base .HasDescription ;
4
5
import com .tngtech .archunit .core .domain .*;
5
6
import com .tngtech .archunit .core .domain .properties .HasName ;
6
7
import com .tngtech .archunit .core .domain .properties .HasOwner ;
8
+ import com .tngtech .archunit .core .domain .properties .HasSourceCodeLocation ;
7
9
import com .tngtech .archunit .core .importer .ClassFileImporter ;
8
10
import com .tngtech .archunit .core .importer .ImportOption ;
9
11
import com .tngtech .archunit .lang .ArchCondition ;
10
12
import com .tngtech .archunit .lang .ArchRule ;
13
+ import com .tngtech .archunit .lang .conditions .ArchConditions ;
11
14
import org .apache .commons .io .IOUtils ;
12
15
import org .apache .commons .lang3 .StringUtils ;
13
16
import org .apache .commons .lang3 .builder .ReflectionToStringBuilder ;
14
17
import org .apache .commons .lang3 .builder .ToStringBuilder ;
15
18
import org .apache .commons .lang3 .builder .ToStringStyle ;
16
19
import org .junit .BeforeClass ;
17
20
import org .junit .Test ;
21
+ import org .kohsuke .github .GHDiscussion .Creator ;
22
+ import org .kohsuke .github .GHPullRequestCommitDetail .Commit ;
23
+ import org .kohsuke .github .GHPullRequestCommitDetail .CommitPointer ;
18
24
19
25
import java .io .Closeable ;
20
26
import java .io .InputStream ;
21
27
import java .io .OutputStream ;
22
28
import java .io .Reader ;
23
29
import java .lang .reflect .Field ;
30
+ import java .net .URL ;
24
31
import java .nio .charset .Charset ;
32
+ import java .time .Instant ;
25
33
import java .util .Arrays ;
26
34
import java .util .stream .Collectors ;
27
35
28
36
import static com .google .common .base .Preconditions .checkNotNull ;
37
+ import static com .tngtech .archunit .base .DescribedPredicate .not ;
38
+ import static com .tngtech .archunit .base .DescribedPredicate .or ;
29
39
import static com .tngtech .archunit .core .domain .JavaCall .Predicates .target ;
30
40
import static com .tngtech .archunit .core .domain .JavaClass .Predicates .resideInAPackage ;
31
41
import static com .tngtech .archunit .core .domain .JavaClass .Predicates .type ;
42
+ import static com .tngtech .archunit .core .domain .JavaMember .Predicates .declaredIn ;
43
+ import static com .tngtech .archunit .core .domain .JavaModifier .FINAL ;
44
+ import static com .tngtech .archunit .core .domain .JavaModifier .STATIC ;
45
+ import static com .tngtech .archunit .core .domain .properties .HasModifiers .Predicates .modifier ;
32
46
import static com .tngtech .archunit .core .domain .properties .HasName .Predicates .name ;
33
47
import static com .tngtech .archunit .core .domain .properties .HasName .Predicates .nameContaining ;
48
+ import static com .tngtech .archunit .core .domain .properties .HasName .Predicates .nameMatching ;
34
49
import static com .tngtech .archunit .core .domain .properties .HasOwner .Predicates .With .owner ;
35
50
import static com .tngtech .archunit .core .domain .properties .HasParameterTypes .Predicates .rawParameterTypes ;
51
+ import static com .tngtech .archunit .core .domain .properties .HasReturnType .Predicates .rawReturnType ;
36
52
import static com .tngtech .archunit .lang .conditions .ArchConditions .*;
37
53
import static com .tngtech .archunit .lang .syntax .ArchRuleDefinition .classes ;
54
+ import static com .tngtech .archunit .lang .syntax .ArchRuleDefinition .noClasses ;
55
+ import static com .tngtech .archunit .lang .syntax .ArchRuleDefinition .noFields ;
56
+ import static com .tngtech .archunit .lang .syntax .ArchRuleDefinition .noMethods ;
38
57
import static org .hamcrest .MatcherAssert .assertThat ;
39
58
import static org .hamcrest .Matchers .greaterThan ;
40
59
41
60
// TODO: Auto-generated Javadoc
42
61
/**
43
62
* The Class ArchTests.
44
63
*/
64
+ @ SuppressWarnings ({ "LocalVariableNamingConvention" , "TestMethodWithoutAssertion" , "UnqualifiedStaticUsage" ,
65
+ "unchecked" , "MethodMayBeStatic" , "FieldNamingConvention" , "StaticCollection" })
45
66
public class ArchTests {
46
67
47
68
private static final JavaClasses classFiles = new ClassFileImporter ()
@@ -69,6 +90,43 @@ public static void beforeClass() {
69
90
assertThat (classFiles .size (), greaterThan (0 ));
70
91
}
71
92
93
+ @ Test
94
+ public void testRequireFollowingNamingConvention () {
95
+ final String reason = "This project follows standard java naming conventions and does not allow the use of underscores in names." ;
96
+
97
+ final ArchRule fieldsNotFollowingConvention = noFields ().that ()
98
+ .arePublic ()
99
+ .and (not (enumConstants ()))
100
+ .and (not (modifier (STATIC ).and (modifier (FINAL )).as ("static final" )))
101
+ .should (haveNamesContainingUnless ("_" ))
102
+ .because (reason );
103
+
104
+ @ SuppressWarnings ("AccessStaticViaInstance" )
105
+ final ArchRule methodsNotFollowingConvention = noMethods ().that ()
106
+ .arePublic ()
107
+ .should (haveNamesContainingUnless ("_" ,
108
+ nameMatching ("[A-Z0-9\\ _]+" ),
109
+ // currently failing cases
110
+ // TODO: 2025-03-28 Fix & remove these
111
+ declaredIn (PagedIterable .class ).and (name ("_iterator" )).and (rawReturnType (PagedIterator .class )),
112
+ declaredIn (GHRepositoryBuilder .class ).and (name ("private_" )).and (rawReturnType (Object .class )),
113
+ declaredIn (GHDeployKey .class ).and (name ("getAdded_by" )).and (rawReturnType (String .class )),
114
+ declaredIn (GHDeployKey .class ).and (name ("isRead_only" )).and (rawReturnType (boolean .class )),
115
+ declaredIn (Creator .class ).and (name ("private_" )).and (rawReturnType (Creator .class )),
116
+ declaredIn (GHGistBuilder .class ).and (name ("public_" )).and (rawReturnType (GHGistBuilder .class )),
117
+ declaredIn (Commit .class ).and (name ("getComment_count" )).and (rawReturnType (int .class )),
118
+ declaredIn (CommitPointer .class ).and (name ("getHtml_url" )).and (rawReturnType (URL .class )),
119
+ declaredIn (GHRelease .class ).and (name ("getPublished_at" )).and (rawReturnType (Instant .class ))))
120
+ .because (reason );
121
+
122
+ final ArchRule classesNotFollowingConvention = noClasses ().should (haveNamesContainingUnless ("_" ))
123
+ .because (reason );
124
+
125
+ fieldsNotFollowingConvention .check (classFiles );
126
+ methodsNotFollowingConvention .check (classFiles );
127
+ classesNotFollowingConvention .check (classFiles );
128
+ }
129
+
72
130
/**
73
131
* Test require use of assert that.
74
132
*/
@@ -78,10 +136,10 @@ public void testRequireUseOfAssertThat() {
78
136
final String reason = "This project uses `assertThat(...)` or `assertThrows(...)` instead of other `assert*()` methods." ;
79
137
80
138
final DescribedPredicate <HasName > assertMethodOtherThanAssertThat = nameContaining ("assert" )
81
- .and (DescribedPredicate . not (name ("assertThat" )).and (DescribedPredicate . not (name ("assertThrows" ))));
139
+ .and (not (name ("assertThat" )).and (not (name ("assertThrows" ))));
82
140
83
141
final ArchRule onlyAssertThatRule = classes ()
84
- .should (not (callMethodWhere (target (assertMethodOtherThanAssertThat ))))
142
+ .should (ArchConditions . not (callMethodWhere (target (assertMethodOtherThanAssertThat ))))
85
143
.because (reason );
86
144
87
145
onlyAssertThatRule .check (testClassFiles );
@@ -135,6 +193,27 @@ public void testRequireUseOfOnlySpecificApacheCommons() {
135
193
onlyApprovedApacheCommonsMethods .check (classFiles );
136
194
}
137
195
196
+ /**
197
+ * Have names containing unless.
198
+ *
199
+ * @param infix
200
+ * the infix
201
+ * @param unlessPredicates
202
+ * the unless predicates
203
+ * @return the arch condition
204
+ */
205
+ public static <T extends HasDescription & HasSourceCodeLocation & HasName > ArchCondition <T > haveNamesContainingUnless (
206
+ final String infix ,
207
+ final DescribedPredicate <? super T >... unlessPredicates ) {
208
+ DescribedPredicate <? super T > restrictedNameContaining = nameContaining (infix );
209
+
210
+ if (unlessPredicates .length > 0 ) {
211
+ final DescribedPredicate <T > allowed = or (unlessPredicates );
212
+ restrictedNameContaining = unless (nameContaining (infix ), allowed );
213
+ }
214
+ return have (restrictedNameContaining );
215
+ }
216
+
138
217
/**
139
218
* Not call methods in package unless.
140
219
*
@@ -156,7 +235,7 @@ public static ArchCondition<JavaClass> notCallMethodsInPackageUnless(final Strin
156
235
}
157
236
restrictedPackageCalls = unless (restrictedPackageCalls , allowed );
158
237
}
159
- return not (callMethodWhere (restrictedPackageCalls ));
238
+ return ArchConditions . not (callMethodWhere (restrictedPackageCalls ));
160
239
}
161
240
162
241
/**
@@ -200,6 +279,10 @@ public static <T> DescribedPredicate<T> unless(DescribedPredicate<? super T> fir
200
279
return new UnlessPredicate (first , second );
201
280
}
202
281
282
+ private DescribedPredicate <? super JavaField > enumConstants () {
283
+ return new EnumConstantFieldPredicate ();
284
+ }
285
+
203
286
private static class UnlessPredicate <T > extends DescribedPredicate <T > {
204
287
private final DescribedPredicate <T > current ;
205
288
private final DescribedPredicate <? super T > other ;
@@ -215,4 +298,16 @@ public boolean test(T input) {
215
298
return current .test (input ) && !other .test (input );
216
299
}
217
300
}
301
+
302
+ private static final class EnumConstantFieldPredicate extends DescribedPredicate <JavaField > {
303
+ private EnumConstantFieldPredicate () {
304
+ super ("are not enum constants" );
305
+ }
306
+
307
+ @ Override
308
+ public boolean test (JavaField javaField ) {
309
+ JavaClass owner = javaField .getOwner ();
310
+ return owner .isEnum () && javaField .getRawType ().isAssignableTo (owner .reflect ());
311
+ }
312
+ }
218
313
}
0 commit comments