From fae6e48a596f311132961b69d3dd5a064fc9cef3 Mon Sep 17 00:00:00 2001 From: mnhock Date: Tue, 11 Jun 2024 20:43:28 +0200 Subject: [PATCH] Provide a New Java Rule checking fields by disallowing public fields Closes gh-18 --- docs/USERGUIDE.md | 11 ++++++++ .../taikai/java/FieldsShouldNotBePublic.java | 28 +++++++++++++++++++ .../enofex/taikai/java/JavaConfigurer.java | 10 +++++++ .../com/enofex/taikai/ArchitectureTest.java | 1 + 4 files changed, 50 insertions(+) create mode 100644 src/main/java/com/enofex/taikai/java/FieldsShouldNotBePublic.java diff --git a/docs/USERGUIDE.md b/docs/USERGUIDE.md index f8cf559..e129b61 100644 --- a/docs/USERGUIDE.md +++ b/docs/USERGUIDE.md @@ -84,6 +84,17 @@ Taikai.builder() .check(); ``` +- **Fields Should Not Be Public**: Ensure that no fields in your Java classes are declared as `public`, except constants. + +```java +Taikai.builder() + .namespace("com.enofex.taikai") + .java(java -> java + .fieldsShouldNotBePublic()) + .build() + .check(); +``` + - **Imports Configuration**: Ensure that there are no cyclic dependencies in imports and disallow specific imports. ```java diff --git a/src/main/java/com/enofex/taikai/java/FieldsShouldNotBePublic.java b/src/main/java/com/enofex/taikai/java/FieldsShouldNotBePublic.java new file mode 100644 index 0000000..3fdcb1b --- /dev/null +++ b/src/main/java/com/enofex/taikai/java/FieldsShouldNotBePublic.java @@ -0,0 +1,28 @@ +package com.enofex.taikai.java; + +import com.tngtech.archunit.core.domain.JavaField; +import com.tngtech.archunit.core.domain.JavaModifier; +import com.tngtech.archunit.lang.ArchCondition; +import com.tngtech.archunit.lang.ConditionEvents; +import com.tngtech.archunit.lang.SimpleConditionEvent; + +final class FieldsShouldNotBePublic { + + private FieldsShouldNotBePublic() { + } + + static ArchCondition notBePublic() { + return new ArchCondition<>("not be public") { + @Override + public void check(JavaField field, ConditionEvents events) { + if (!field.getModifiers().contains(JavaModifier.STATIC) + && field.getModifiers().contains(JavaModifier.PUBLIC)) { + String message = String.format("Field %s in class %s is public", + field.getName(), + field.getOwner().getFullName()); + events.add(SimpleConditionEvent.violated(field, message)); + } + } + }; + } +} diff --git a/src/main/java/com/enofex/taikai/java/JavaConfigurer.java b/src/main/java/com/enofex/taikai/java/JavaConfigurer.java index eaa8bad..119560e 100644 --- a/src/main/java/com/enofex/taikai/java/JavaConfigurer.java +++ b/src/main/java/com/enofex/taikai/java/JavaConfigurer.java @@ -1,11 +1,13 @@ package com.enofex.taikai.java; import static com.enofex.taikai.java.Deprecations.notUseDeprecatedAPIs; +import static com.enofex.taikai.java.FieldsShouldNotBePublic.notBePublic; import static com.enofex.taikai.java.HashCodeAndEquals.implementHashCodeAndEquals; import static com.enofex.taikai.java.UtilityClasses.beFinal; import static com.enofex.taikai.java.UtilityClasses.havePrivateConstructor; import static com.enofex.taikai.java.UtilityClasses.utilityClasses; import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.fields; import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.methods; import com.enofex.taikai.TaikaiRule; @@ -66,6 +68,14 @@ public JavaConfigurer classesShouldImplementHashCodeAndEquals(Configuration conf return addRule(TaikaiRule.of(classes().should(implementHashCodeAndEquals()), configuration)); } + public JavaConfigurer fieldsShouldNotBePublic() { + return fieldsShouldNotBePublic(null); + } + + public JavaConfigurer fieldsShouldNotBePublic(Configuration configuration) { + return addRule(TaikaiRule.of(fields().should(notBePublic()), configuration)); + } + @Override public void disable() { disable(ImportsConfigurer.class); diff --git a/src/test/java/com/enofex/taikai/ArchitectureTest.java b/src/test/java/com/enofex/taikai/ArchitectureTest.java index c364039..e8cb648 100644 --- a/src/test/java/com/enofex/taikai/ArchitectureTest.java +++ b/src/test/java/com/enofex/taikai/ArchitectureTest.java @@ -17,6 +17,7 @@ void shouldFulfilConstrains() { .classesShouldImplementHashCodeAndEquals() .methodsShouldNotThrowGenericException() .utilityClassesShouldBeFinalAndHavePrivateConstructor() + .fieldsShouldNotBePublic() .imports(imports -> imports .shouldHaveNoCycles() .shouldNotImport("..shaded..")