|
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.JavaClass;
|
33 | 35 | import com.tngtech.archunit.core.domain.JavaClass.Predicates;
|
34 | 36 | import com.tngtech.archunit.core.domain.JavaClasses;
|
35 | 37 | import com.tngtech.archunit.core.domain.JavaMethod;
|
36 | 38 | import com.tngtech.archunit.core.domain.JavaParameter;
|
| 39 | +import com.tngtech.archunit.core.domain.JavaType; |
37 | 40 | import com.tngtech.archunit.core.domain.properties.CanBeAnnotated;
|
38 | 41 | import com.tngtech.archunit.core.importer.ClassFileImporter;
|
39 | 42 | import com.tngtech.archunit.lang.ArchCondition;
|
@@ -83,7 +86,8 @@ public ArchitectureCheck() {
|
83 | 86 | noClassesShouldConfigureDefaultStepVerifierTimeout(), noClassesShouldCallCollectorsToList(),
|
84 | 87 | noClassesShouldCallURLEncoderWithStringEncoding(), noClassesShouldCallURLDecoderWithStringEncoding(),
|
85 | 88 | noClassesShouldCallStringToUpperCaseWithoutLocale(),
|
86 |
| - noClassesShouldCallStringToLowerCaseWithoutLocale()); |
| 89 | + noClassesShouldCallStringToLowerCaseWithoutLocale(), |
| 90 | + conditionalOnMissingBeanShouldNotSpecifyOnlyATypeThatIsTheSameAsMethodReturnType()); |
87 | 91 | getRules().addAll(getProhibitObjectsRequireNonNull()
|
88 | 92 | .map((prohibit) -> prohibit ? noClassesShouldCallObjectsRequireNonNull() : Collections.emptyList()));
|
89 | 93 | getRuleDescriptions().set(getRules().map((rules) -> rules.stream().map(ArchRule::getDescription).toList()));
|
@@ -244,6 +248,36 @@ private List<ArchRule> noClassesShouldCallObjectsRequireNonNull() {
|
244 | 248 | .because("org.springframework.utils.Assert.notNull(Object, Supplier) should be used instead"));
|
245 | 249 | }
|
246 | 250 |
|
| 251 | + private ArchRule conditionalOnMissingBeanShouldNotSpecifyOnlyATypeThatIsTheSameAsMethodReturnType() { |
| 252 | + return ArchRuleDefinition.methods() |
| 253 | + .that() |
| 254 | + .areAnnotatedWith("org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean") |
| 255 | + .should(notSpecifyOnlyATypeThatIsTheSameAsTheMethodReturnType()) |
| 256 | + .allowEmptyShould(true); |
| 257 | + } |
| 258 | + |
| 259 | + private ArchCondition<? super JavaMethod> notSpecifyOnlyATypeThatIsTheSameAsTheMethodReturnType() { |
| 260 | + return new ArchCondition<>("not specify only a type that is the same as the method's return type") { |
| 261 | + |
| 262 | + @Override |
| 263 | + public void check(JavaMethod item, ConditionEvents events) { |
| 264 | + JavaAnnotation<JavaMethod> conditional = item |
| 265 | + .getAnnotationOfType("org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean"); |
| 266 | + Map<String, Object> properties = conditional.getProperties(); |
| 267 | + if (!properties.containsKey("type") && !properties.containsKey("name")) { |
| 268 | + conditional.get("value").ifPresent((value) -> { |
| 269 | + JavaType[] types = (JavaType[]) value; |
| 270 | + if (types.length == 1 && item.getReturnType().equals(types[0])) { |
| 271 | + events.add(SimpleConditionEvent.violated(item, conditional.getDescription() |
| 272 | + + " should not specify only a value that is the same as the method's return type")); |
| 273 | + } |
| 274 | + }); |
| 275 | + } |
| 276 | + } |
| 277 | + |
| 278 | + }; |
| 279 | + } |
| 280 | + |
247 | 281 | public void setClasses(FileCollection classes) {
|
248 | 282 | this.classes = classes;
|
249 | 283 | }
|
|
0 commit comments