|
24 | 24 | import java.nio.file.StandardOpenOption;
|
25 | 25 | import java.util.Collections;
|
26 | 26 | import java.util.List;
|
| 27 | +import java.util.Map; |
27 | 28 | import java.util.Objects;
|
28 | 29 | import java.util.function.Supplier;
|
29 | 30 | import java.util.stream.Collectors;
|
30 | 31 |
|
31 | 32 | import com.tngtech.archunit.base.DescribedPredicate;
|
| 33 | +import com.tngtech.archunit.core.domain.JavaAnnotation; |
32 | 34 | import com.tngtech.archunit.core.domain.JavaCall;
|
33 | 35 | import com.tngtech.archunit.core.domain.JavaClass;
|
34 | 36 | import com.tngtech.archunit.core.domain.JavaClass.Predicates;
|
35 | 37 | import com.tngtech.archunit.core.domain.JavaClasses;
|
36 | 38 | import com.tngtech.archunit.core.domain.JavaMethod;
|
37 | 39 | import com.tngtech.archunit.core.domain.JavaParameter;
|
| 40 | +import com.tngtech.archunit.core.domain.JavaType; |
38 | 41 | import com.tngtech.archunit.core.domain.properties.CanBeAnnotated;
|
39 | 42 | import com.tngtech.archunit.core.domain.properties.HasName;
|
40 | 43 | import com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With;
|
@@ -90,7 +93,8 @@ public ArchitectureCheck() {
|
90 | 93 | noClassesShouldConfigureDefaultStepVerifierTimeout(), noClassesShouldCallCollectorsToList(),
|
91 | 94 | noClassesShouldCallURLEncoderWithStringEncoding(), noClassesShouldCallURLDecoderWithStringEncoding(),
|
92 | 95 | noClassesShouldLoadResourcesUsingResourceUtils(), noClassesShouldCallStringToUpperCaseWithoutLocale(),
|
93 |
| - noClassesShouldCallStringToLowerCaseWithoutLocale()); |
| 96 | + noClassesShouldCallStringToLowerCaseWithoutLocale(), |
| 97 | + conditionalOnMissingBeanShouldNotSpecifyOnlyATypeThatIsTheSameAsMethodReturnType()); |
94 | 98 | getRules().addAll(getProhibitObjectsRequireNonNull()
|
95 | 99 | .map((prohibit) -> prohibit ? noClassesShouldCallObjectsRequireNonNull() : Collections.emptyList()));
|
96 | 100 | getRuleDescriptions().set(getRules().map((rules) -> rules.stream().map(ArchRule::getDescription).toList()));
|
@@ -265,6 +269,36 @@ private List<ArchRule> noClassesShouldCallObjectsRequireNonNull() {
|
265 | 269 | .because("org.springframework.utils.Assert.notNull(Object, Supplier) should be used instead"));
|
266 | 270 | }
|
267 | 271 |
|
| 272 | + private ArchRule conditionalOnMissingBeanShouldNotSpecifyOnlyATypeThatIsTheSameAsMethodReturnType() { |
| 273 | + return ArchRuleDefinition.methods() |
| 274 | + .that() |
| 275 | + .areAnnotatedWith("org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean") |
| 276 | + .should(notSpecifyOnlyATypeThatIsTheSameAsTheMethodReturnType()) |
| 277 | + .allowEmptyShould(true); |
| 278 | + } |
| 279 | + |
| 280 | + private ArchCondition<? super JavaMethod> notSpecifyOnlyATypeThatIsTheSameAsTheMethodReturnType() { |
| 281 | + return new ArchCondition<>("not specify only a type that is the same as the method's return type") { |
| 282 | + |
| 283 | + @Override |
| 284 | + public void check(JavaMethod item, ConditionEvents events) { |
| 285 | + JavaAnnotation<JavaMethod> conditional = item |
| 286 | + .getAnnotationOfType("org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean"); |
| 287 | + Map<String, Object> properties = conditional.getProperties(); |
| 288 | + if (!properties.containsKey("type") && !properties.containsKey("name")) { |
| 289 | + conditional.get("value").ifPresent((value) -> { |
| 290 | + JavaType[] types = (JavaType[]) value; |
| 291 | + if (types.length == 1 && item.getReturnType().equals(types[0])) { |
| 292 | + events.add(SimpleConditionEvent.violated(item, conditional.getDescription() |
| 293 | + + " should not specify only a value that is the same as the method's return type")); |
| 294 | + } |
| 295 | + }); |
| 296 | + } |
| 297 | + } |
| 298 | + |
| 299 | + }; |
| 300 | + } |
| 301 | + |
268 | 302 | public void setClasses(FileCollection classes) {
|
269 | 303 | this.classes = classes;
|
270 | 304 | }
|
|
0 commit comments