11package org .kohsuke .github ;
22
33import com .tngtech .archunit .base .DescribedPredicate ;
4+ import com .tngtech .archunit .base .HasDescription ;
45import com .tngtech .archunit .core .domain .*;
56import com .tngtech .archunit .core .domain .properties .HasName ;
67import com .tngtech .archunit .core .domain .properties .HasOwner ;
8+ import com .tngtech .archunit .core .domain .properties .HasSourceCodeLocation ;
79import com .tngtech .archunit .core .importer .ClassFileImporter ;
810import com .tngtech .archunit .core .importer .ImportOption ;
911import com .tngtech .archunit .lang .ArchCondition ;
1012import com .tngtech .archunit .lang .ArchRule ;
13+ import com .tngtech .archunit .lang .conditions .ArchConditions ;
1114import org .apache .commons .io .IOUtils ;
1215import org .apache .commons .lang3 .StringUtils ;
1316import org .apache .commons .lang3 .builder .ReflectionToStringBuilder ;
1417import org .apache .commons .lang3 .builder .ToStringBuilder ;
1518import org .apache .commons .lang3 .builder .ToStringStyle ;
1619import org .junit .BeforeClass ;
1720import org .junit .Test ;
21+ import org .kohsuke .github .GHDiscussion .Creator ;
22+ import org .kohsuke .github .GHPullRequestCommitDetail .Commit ;
23+ import org .kohsuke .github .GHPullRequestCommitDetail .CommitPointer ;
1824
1925import java .io .Closeable ;
2026import java .io .InputStream ;
2632import java .util .stream .Collectors ;
2733
2834import static com .google .common .base .Preconditions .checkNotNull ;
35+ import static com .tngtech .archunit .base .DescribedPredicate .not ;
36+ import static com .tngtech .archunit .base .DescribedPredicate .or ;
2937import static com .tngtech .archunit .core .domain .JavaCall .Predicates .target ;
38+ import static com .tngtech .archunit .core .domain .JavaClass .Predicates .assignableTo ;
3039import static com .tngtech .archunit .core .domain .JavaClass .Predicates .resideInAPackage ;
3140import static com .tngtech .archunit .core .domain .JavaClass .Predicates .type ;
41+ import static com .tngtech .archunit .core .domain .JavaMember .Predicates .declaredIn ;
42+ import static com .tngtech .archunit .core .domain .JavaModifier .FINAL ;
43+ import static com .tngtech .archunit .core .domain .JavaModifier .STATIC ;
44+ import static com .tngtech .archunit .core .domain .properties .HasModifiers .Predicates .modifier ;
3245import static com .tngtech .archunit .core .domain .properties .HasName .Predicates .name ;
3346import static com .tngtech .archunit .core .domain .properties .HasName .Predicates .nameContaining ;
3447import static com .tngtech .archunit .core .domain .properties .HasOwner .Predicates .With .owner ;
3548import static com .tngtech .archunit .core .domain .properties .HasParameterTypes .Predicates .rawParameterTypes ;
3649import static com .tngtech .archunit .lang .conditions .ArchConditions .*;
3750import static com .tngtech .archunit .lang .syntax .ArchRuleDefinition .classes ;
51+ import static com .tngtech .archunit .lang .syntax .ArchRuleDefinition .noClasses ;
52+ import static com .tngtech .archunit .lang .syntax .ArchRuleDefinition .noFields ;
53+ import static com .tngtech .archunit .lang .syntax .ArchRuleDefinition .noMethods ;
3854import static org .hamcrest .MatcherAssert .assertThat ;
3955import static org .hamcrest .Matchers .greaterThan ;
4056
4157// TODO: Auto-generated Javadoc
4258/**
4359 * The Class ArchTests.
4460 */
61+ @ SuppressWarnings ({ "LocalVariableNamingConvention" , "TestMethodWithoutAssertion" , "UnqualifiedStaticUsage" ,
62+ "unchecked" , "MethodMayBeStatic" , "FieldNamingConvention" , "StaticCollection" })
4563public class ArchTests {
4664
4765 private static final JavaClasses classFiles = new ClassFileImporter ()
@@ -69,6 +87,46 @@ public static void beforeClass() {
6987 assertThat (classFiles .size (), greaterThan (0 ));
7088 }
7189
90+ /**
91+ * Test naming conventions
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+ // currently failing method names
109+ // TODO: 2025-03-28 Fix & remove these
110+ declaredIn (assignableTo (PagedIterable .class )).and (name ("_iterator" )),
111+ declaredIn (GHCompare .class ).and (name ("getAdded_by" )),
112+ declaredIn (GHDeployKey .class ).and (name ("getAdded_by" )),
113+ declaredIn (GHDeployKey .class ).and (name ("isRead_only" )),
114+ declaredIn (assignableTo (GHRepositoryBuilder .class )).and (name ("private_" )),
115+ declaredIn (Creator .class ).and (name ("private_" )),
116+ declaredIn (GHGistBuilder .class ).and (name ("public_" )),
117+ declaredIn (Commit .class ).and (name ("getComment_count" )),
118+ declaredIn (CommitPointer .class ).and (name ("getHtml_url" )),
119+ declaredIn (GHRelease .class ).and (name ("getPublished_at" ))))
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+
72130 /**
73131 * Test require use of assert that.
74132 */
@@ -78,10 +136,10 @@ public void testRequireUseOfAssertThat() {
78136 final String reason = "This project uses `assertThat(...)` or `assertThrows(...)` instead of other `assert*()` methods." ;
79137
80138 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" ))));
82140
83141 final ArchRule onlyAssertThatRule = classes ()
84- .should (not (callMethodWhere (target (assertMethodOtherThanAssertThat ))))
142+ .should (ArchConditions . not (callMethodWhere (target (assertMethodOtherThanAssertThat ))))
85143 .because (reason );
86144
87145 onlyAssertThatRule .check (testClassFiles );
@@ -135,6 +193,29 @@ public void testRequireUseOfOnlySpecificApacheCommons() {
135193 onlyApprovedApacheCommonsMethods .check (classFiles );
136194 }
137195
196+ /**
197+ * Have names containing unless.
198+ *
199+ * @param <T>
200+ * the generic type
201+ * @param infix
202+ * the infix
203+ * @param unlessPredicates
204+ * the unless predicates
205+ * @return the arch condition
206+ */
207+ public static <T extends HasDescription & HasSourceCodeLocation & HasName > ArchCondition <T > haveNamesContainingUnless (
208+ final String infix ,
209+ final DescribedPredicate <? super T >... unlessPredicates ) {
210+ DescribedPredicate <? super T > restrictedNameContaining = nameContaining (infix );
211+
212+ if (unlessPredicates .length > 0 ) {
213+ final DescribedPredicate <T > allowed = or (unlessPredicates );
214+ restrictedNameContaining = unless (nameContaining (infix ), allowed );
215+ }
216+ return have (restrictedNameContaining );
217+ }
218+
138219 /**
139220 * Not call methods in package unless.
140221 *
@@ -156,7 +237,7 @@ public static ArchCondition<JavaClass> notCallMethodsInPackageUnless(final Strin
156237 }
157238 restrictedPackageCalls = unless (restrictedPackageCalls , allowed );
158239 }
159- return not (callMethodWhere (restrictedPackageCalls ));
240+ return ArchConditions . not (callMethodWhere (restrictedPackageCalls ));
160241 }
161242
162243 /**
@@ -200,6 +281,15 @@ public static <T> DescribedPredicate<T> unless(DescribedPredicate<? super T> fir
200281 return new UnlessPredicate (first , second );
201282 }
202283
284+ /**
285+ * Enum constants.
286+ *
287+ * @return the described predicate
288+ */
289+ private DescribedPredicate <? super JavaField > enumConstants () {
290+ return new EnumConstantFieldPredicate ();
291+ }
292+
203293 private static class UnlessPredicate <T > extends DescribedPredicate <T > {
204294 private final DescribedPredicate <T > current ;
205295 private final DescribedPredicate <? super T > other ;
@@ -215,4 +305,16 @@ public boolean test(T input) {
215305 return current .test (input ) && !other .test (input );
216306 }
217307 }
308+
309+ private static final class EnumConstantFieldPredicate extends DescribedPredicate <JavaField > {
310+ private EnumConstantFieldPredicate () {
311+ super ("are not enum constants" );
312+ }
313+
314+ @ Override
315+ public boolean test (JavaField javaField ) {
316+ JavaClass owner = javaField .getOwner ();
317+ return owner .isEnum () && javaField .getRawType ().isAssignableTo (owner .reflect ());
318+ }
319+ }
218320}
0 commit comments