Skip to content

Commit 766dcb1

Browse files
committed
break up rules
1 parent 85fff61 commit 766dcb1

19 files changed

Lines changed: 1196 additions & 603 deletions

pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
34
<modelVersion>4.0.0</modelVersion>
45

56
<parent>

src/main/java/it/aboutbits/archunit/toolbox/ArchitectureTestBase.java

Lines changed: 0 additions & 560 deletions
This file was deleted.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package it.aboutbits.archunit.toolbox;
2+
3+
import it.aboutbits.archunit.toolbox.rule.base.BlacklistAnnotationsArchRule;
4+
import it.aboutbits.archunit.toolbox.rule.base.BlacklistClassesArchRule;
5+
import it.aboutbits.archunit.toolbox.rule.base.BlacklistMethodsArchRule;
6+
import it.aboutbits.archunit.toolbox.rule.base.EnforceJspecifyArchRule;
7+
import it.aboutbits.archunit.toolbox.rule.base.TestClassInCorrectPackageArchRule;
8+
import it.aboutbits.archunit.toolbox.rule.base.TestClassVisibilityArchRule;
9+
import it.aboutbits.archunit.toolbox.rule.base.TestMethodVisibilityArchRule;
10+
import it.aboutbits.archunit.toolbox.rule.base.TestNestedClassMatchNameArchRule;
11+
import it.aboutbits.archunit.toolbox.rule.base.TestNestedClassVisibilityArchRule;
12+
import org.jspecify.annotations.NullMarked;
13+
14+
@NullMarked
15+
public interface BaseArchRuleCollection extends
16+
BlacklistAnnotationsArchRule,
17+
BlacklistClassesArchRule,
18+
BlacklistMethodsArchRule,
19+
EnforceJspecifyArchRule,
20+
TestClassInCorrectPackageArchRule,
21+
TestClassVisibilityArchRule,
22+
TestMethodVisibilityArchRule,
23+
TestNestedClassMatchNameArchRule,
24+
TestNestedClassVisibilityArchRule {
25+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package it.aboutbits.archunit.toolbox;
2+
3+
import it.aboutbits.archunit.toolbox.rule.common.ControllerRequestMappingsMustBeSecurityTested;
4+
import it.aboutbits.archunit.toolbox.rule.common.SortMappingsExhaustiveArchRule;
5+
6+
public interface CommonArchRuleCollection extends
7+
ControllerRequestMappingsMustBeSecurityTested,
8+
SortMappingsExhaustiveArchRule {
9+
}

src/main/java/it/aboutbits/archunit/toolbox/InnertRule.java

Lines changed: 0 additions & 41 deletions
This file was deleted.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package it.aboutbits.archunit.toolbox.config;
2+
3+
import org.jspecify.annotations.NullMarked;
4+
5+
import java.util.HashSet;
6+
import java.util.Set;
7+
8+
@NullMarked
9+
public final class ArchRuleConfig {
10+
private ArchRuleConfig() {
11+
}
12+
13+
/**
14+
* List of supported test class name suffixes.
15+
* <p>
16+
* When introducing a new test type (e.g. IntegrationTest), add its suffix here
17+
* instead of directly modifying the regex pattern.
18+
**/
19+
public static final Set<String> TEST_CLASS_SUFFIXES = new HashSet<>(
20+
Set.of(
21+
"Test",
22+
"CacheTest",
23+
"EventTest",
24+
"SecurityTest"
25+
)
26+
);
27+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package it.aboutbits.archunit.toolbox.rule.base;
2+
3+
import com.tngtech.archunit.core.domain.JavaClass;
4+
import com.tngtech.archunit.core.domain.JavaClasses;
5+
import com.tngtech.archunit.junit.ArchTest;
6+
import com.tngtech.archunit.lang.ArchCondition;
7+
import com.tngtech.archunit.lang.ConditionEvents;
8+
import com.tngtech.archunit.lang.SimpleConditionEvent;
9+
import org.jspecify.annotations.NullMarked;
10+
11+
import java.util.HashSet;
12+
import java.util.Set;
13+
14+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
15+
16+
@SuppressWarnings({"checkstyle:InterfaceIsType", "java:S1214"})
17+
@NullMarked
18+
public interface BlacklistAnnotationsArchRule {
19+
@SuppressWarnings("java:S2386")
20+
Set<String> BLACKLISTED_ANNOTATIONS = new HashSet<>(
21+
Set.of(
22+
"org.junit.After",
23+
"org.junit.AfterClass",
24+
"org.junit.Before",
25+
"org.junit.BeforeClass",
26+
"org.junit.ClassRule",
27+
"org.junit.FixMethodOrder",
28+
"org.junit.Ignore",
29+
"org.junit.Rule",
30+
"org.junit.Test",
31+
// @NonNull (allowed is only org.jspecify.annotations.NonNull)
32+
"lombok.NonNull",
33+
"edu.umd.cs.findbugs.annotations.NonNull",
34+
"io.micrometer.common.lang.NonNull",
35+
"io.micrometer.core.lang.NonNull",
36+
"org.springframework.lang.NonNull",
37+
"org.testcontainers.shaded.org.checkerframework.checker.nullness.qual.NonNull",
38+
// @NotNull (allowed is only jakarta.validation.constraints.NotNull)
39+
"com.drew.lang.annotations.NotNull",
40+
"com.sun.istack.NotNull",
41+
"org.antlr.v4.runtime.misc.NotNull",
42+
"org.jetbrains.annotations.NotNull",
43+
"software.amazon.awssdk.annotations.NotNull",
44+
// @Nullable (allowed is only org.jspecify.annotations.Nullable)
45+
"org.springframework.lang.Nullable",
46+
"com.drew.lang.annotations.Nullable",
47+
"com.sun.istack.Nullable",
48+
"edu.umd.cs.findbugs.annotations.Nullable",
49+
"io.micrometer.common.lang.Nullable",
50+
"io.micrometer.core.lang.Nullable",
51+
"jakarta.annotation.Nullable",
52+
"javax.annotation.Nullable",
53+
"org.jetbrains.annotations.Nullable",
54+
"org.testcontainers.shaded.org.checkerframework.checker.nullness.qual.Nullable",
55+
// @Transactional (allowed is only org.springframework.transaction.annotation.Transactional)
56+
"jakarta.transaction.Transactional"
57+
)
58+
);
59+
60+
@SuppressWarnings({"unused", "checkstyle:MethodName", "java:S100"})
61+
@ArchTest
62+
default void no_blacklisted_annotations_are_used(JavaClasses classes) {
63+
classes()
64+
.should(new NotUseBlacklistedAnnotations())
65+
.check(classes);
66+
}
67+
68+
class NotUseBlacklistedAnnotations extends ArchCondition<JavaClass> {
69+
public NotUseBlacklistedAnnotations() {
70+
super("not use blacklisted annotations on classes, methods, method parameters, or fields");
71+
}
72+
73+
@Override
74+
public void check(JavaClass javaClass, ConditionEvents events) {
75+
// Check annotations on the class itself
76+
for (var annotation : javaClass.getAnnotations()) {
77+
if (BLACKLISTED_ANNOTATIONS.contains(annotation.getRawType().getFullName())) {
78+
var message = String.format(
79+
"Class %s is annotated with blacklisted annotation @%s (%s.java:%d)",
80+
javaClass.getFullName(),
81+
annotation.getRawType().getFullName(),
82+
javaClass.getSimpleName(),
83+
javaClass.getSourceCodeLocation().getLineNumber()
84+
);
85+
events.add(SimpleConditionEvent.violated(javaClass, message));
86+
}
87+
}
88+
89+
// Check annotations on methods and their parameters
90+
for (var method : javaClass.getMethods()) {
91+
// Check method annotations
92+
for (var annotation : method.getAnnotations()) {
93+
if (BLACKLISTED_ANNOTATIONS.contains(annotation.getRawType().getFullName())) {
94+
var message = String.format(
95+
"Method %s is annotated with blacklisted annotation @%s (%s.java:%d)",
96+
method.getFullName(),
97+
annotation.getRawType().getFullName(),
98+
javaClass.getSimpleName(),
99+
method.getSourceCodeLocation().getLineNumber()
100+
);
101+
events.add(SimpleConditionEvent.violated(method, message));
102+
}
103+
}
104+
// Check method parameter annotations
105+
for (var parameter : method.getParameters()) {
106+
for (var annotation : parameter.getAnnotations()) {
107+
if (BLACKLISTED_ANNOTATIONS.contains(annotation.getRawType().getFullName())) {
108+
var message = String.format(
109+
"Parameter %s of method %s is annotated with blacklisted annotation @%s (%s.java:%d)",
110+
parameter.getIndex(),
111+
method.getFullName(),
112+
annotation.getRawType().getFullName(),
113+
javaClass.getSimpleName(),
114+
method.getSourceCodeLocation().getLineNumber()
115+
); // Parameter doesn't have its own SLOC, use method's
116+
events.add(SimpleConditionEvent.violated(parameter, message));
117+
}
118+
}
119+
}
120+
}
121+
122+
// Check annotations on fields (ArchUnit includes record components as fields)
123+
for (var field : javaClass.getFields()) {
124+
for (var annotation : field.getAnnotations()) {
125+
if (BLACKLISTED_ANNOTATIONS.contains(annotation.getRawType().getFullName())) {
126+
var message = String.format(
127+
"Field %s in class %s is annotated with blacklisted annotation @%s (%s.java:%d)",
128+
field.getName(),
129+
javaClass.getFullName(),
130+
annotation.getRawType().getFullName(),
131+
javaClass.getSimpleName(),
132+
field.getSourceCodeLocation().getLineNumber()
133+
);
134+
events.add(SimpleConditionEvent.violated(field, message));
135+
}
136+
}
137+
}
138+
}
139+
}
140+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package it.aboutbits.archunit.toolbox.rule.base;
2+
3+
import com.tngtech.archunit.base.DescribedPredicate;
4+
import com.tngtech.archunit.core.domain.JavaClass;
5+
import com.tngtech.archunit.core.domain.JavaClasses;
6+
import com.tngtech.archunit.junit.ArchTest;
7+
import org.jspecify.annotations.NullMarked;
8+
9+
import java.util.HashSet;
10+
import java.util.Set;
11+
12+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
13+
14+
@SuppressWarnings({"checkstyle:InterfaceIsType", "java:S1214"})
15+
@NullMarked
16+
public interface BlacklistClassesArchRule {
17+
@SuppressWarnings("java:S2386")
18+
Set<String> BLACKLISTED_CLASSES = new HashSet<>(
19+
Set.of(
20+
// use FakerExtended from toolbox
21+
"net.datafaker.Faker"
22+
)
23+
);
24+
25+
@SuppressWarnings({"unused", "checkstyle:MethodName", "java:S100"})
26+
@ArchTest
27+
default void no_blacklisted_classes_are_used(JavaClasses classes) {
28+
noClasses()
29+
.should()
30+
.dependOnClassesThat(
31+
new DescribedPredicate<>("not use blacklisted classes") {
32+
@Override
33+
public boolean test(JavaClass javaClass) {
34+
return BLACKLISTED_CLASSES.contains(javaClass.getFullName());
35+
}
36+
}
37+
)
38+
.check(classes);
39+
}
40+
}

0 commit comments

Comments
 (0)