mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-25 10:59:03 +00:00
Improve handling of annotation properties in architecture checks
Closes gh-47437
This commit is contained in:
+21
-15
@@ -89,7 +89,7 @@ final class ArchitectureRules {
|
||||
rules.add(noClassesShouldCallStringToUpperCaseWithoutLocale());
|
||||
rules.add(noClassesShouldCallStringToLowerCaseWithoutLocale());
|
||||
rules.add(conditionalOnMissingBeanShouldNotSpecifyOnlyATypeThatIsTheSameAsMethodReturnType());
|
||||
rules.add(enumSourceShouldNotSpecifyOnlyATypeThatIsTheSameAsMethodParameterType());
|
||||
rules.add(enumSourceShouldNotHaveValueThatIsTheSameAsTypeOfMethodsFirstParameter());
|
||||
rules.add(allConfigurationPropertiesBindingBeanMethodsShouldBeStatic());
|
||||
return List.copyOf(rules);
|
||||
}
|
||||
@@ -222,7 +222,7 @@ final class ArchitectureRules {
|
||||
JavaAnnotation<JavaMethod> conditionalAnnotation = item
|
||||
.getAnnotationOfType("org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean");
|
||||
Map<String, Object> properties = conditionalAnnotation.getProperties();
|
||||
if (!properties.containsKey("type") && !properties.containsKey("name")) {
|
||||
if (!hasProperty("type", properties) && !hasProperty("name", properties)) {
|
||||
conditionalAnnotation.get("value").ifPresent((value) -> {
|
||||
if (containsOnlySingleType((JavaType[]) value, item.getReturnType())) {
|
||||
addViolation(events, item, conditionalAnnotation.getDescription()
|
||||
@@ -233,16 +233,24 @@ final class ArchitectureRules {
|
||||
});
|
||||
}
|
||||
|
||||
private static ArchRule enumSourceShouldNotSpecifyOnlyATypeThatIsTheSameAsMethodParameterType() {
|
||||
private static boolean hasProperty(String name, Map<String, Object> properties) {
|
||||
Object property = properties.get(name);
|
||||
if (property == null) {
|
||||
return false;
|
||||
}
|
||||
return !property.getClass().isArray() || ((Object[]) property).length > 0;
|
||||
}
|
||||
|
||||
private static ArchRule enumSourceShouldNotHaveValueThatIsTheSameAsTypeOfMethodsFirstParameter() {
|
||||
return ArchRuleDefinition.methods()
|
||||
.that()
|
||||
.areAnnotatedWith("org.junit.jupiter.params.provider.EnumSource")
|
||||
.should(notSpecifyOnlyATypeThatIsTheSameAsTheMethodParameterType())
|
||||
.should(notHaveValueThatIsTheSameAsTheTypeOfTheMethodsFirstParameter())
|
||||
.allowEmptyShould(true);
|
||||
}
|
||||
|
||||
private static ArchCondition<? super JavaMethod> notSpecifyOnlyATypeThatIsTheSameAsTheMethodParameterType() {
|
||||
return check("not specify only a type that is the same as the method's parameter type",
|
||||
private static ArchCondition<? super JavaMethod> notHaveValueThatIsTheSameAsTheTypeOfTheMethodsFirstParameter() {
|
||||
return check("not have a value that is the same as the type of the method's first parameter",
|
||||
ArchitectureRules::notSpecifyOnlyATypeThatIsTheSameAsTheMethodParameterType);
|
||||
}
|
||||
|
||||
@@ -250,15 +258,13 @@ final class ArchitectureRules {
|
||||
ConditionEvents events) {
|
||||
JavaAnnotation<JavaMethod> enumSourceAnnotation = item
|
||||
.getAnnotationOfType("org.junit.jupiter.params.provider.EnumSource");
|
||||
Map<String, Object> properties = enumSourceAnnotation.getProperties();
|
||||
if (properties.size() == 1 && item.getParameterTypes().size() == 1) {
|
||||
enumSourceAnnotation.get("value").ifPresent((value) -> {
|
||||
if (value.equals(item.getParameterTypes().get(0))) {
|
||||
addViolation(events, item, enumSourceAnnotation.getDescription()
|
||||
+ " should not specify only a value that is the same as the method's parameter type");
|
||||
}
|
||||
});
|
||||
}
|
||||
enumSourceAnnotation.get("value").ifPresent((value) -> {
|
||||
JavaType parameterType = item.getParameterTypes().get(0);
|
||||
if (value.equals(parameterType)) {
|
||||
addViolation(events, item, enumSourceAnnotation.getDescription()
|
||||
+ " should not specify a value that is the same as the type of the method's first parameter");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static ArchRule allConfigurationPropertiesBindingBeanMethodsShouldBeStatic() {
|
||||
|
||||
+25
@@ -57,6 +57,8 @@ class ArchitectureCheckTests {
|
||||
|
||||
private static final String SPRING_CONTEXT = "org.springframework:spring-context:6.2.9";
|
||||
|
||||
private static final String JUNIT_JUPITER = "org.junit.jupiter:junit-jupiter:5.12.0";
|
||||
|
||||
private static final String SPRING_INTEGRATION_JMX = "org.springframework.integration:spring-integration-jmx:6.5.1";
|
||||
|
||||
private GradleBuild gradleBuild;
|
||||
@@ -270,6 +272,29 @@ class ArchitectureCheckTests {
|
||||
build(this.gradleBuild.withDependencies(SPRING_CONTEXT), task);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenEnumSourceValueIsInferredShouldSucceedAndWriteEmptyReport() throws IOException {
|
||||
prepareTask(Task.CHECK_ARCHITECTURE_TEST, "junit/enumsource/inferredfromparametertype");
|
||||
build(this.gradleBuild.withDependencies(JUNIT_JUPITER), Task.CHECK_ARCHITECTURE_TEST);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenEnumSourceValueIsNotTheSameAsTypeOfMethodsFirstParameterShouldSucceedAndWriteEmptyReport()
|
||||
throws IOException {
|
||||
prepareTask(Task.CHECK_ARCHITECTURE_TEST, "junit/enumsource/valuenecessary");
|
||||
build(this.gradleBuild.withDependencies(JUNIT_JUPITER), Task.CHECK_ARCHITECTURE_TEST);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenEnumSourceValueIsSameAsTypeOfMethodsFirstParameterShouldFailAndWriteReport() throws IOException {
|
||||
prepareTask(Task.CHECK_ARCHITECTURE_TEST, "junit/enumsource/sameasparametertype");
|
||||
buildAndFail(this.gradleBuild.withDependencies(JUNIT_JUPITER), Task.CHECK_ARCHITECTURE_TEST,
|
||||
"method <org.springframework.boot.build.architecture.junit.enumsource.sameasparametertype"
|
||||
+ ".EnumSourceSameAsParameterType.exampleMethod(org.springframework.boot.build."
|
||||
+ "architecture.junit.enumsource.sameasparametertype.EnumSourceSameAsParameterType$Example)>",
|
||||
"should not have a value that is the same as the type of the method's first parameter");
|
||||
}
|
||||
|
||||
private void prepareTask(Task task, String... sourceDirectories) throws IOException {
|
||||
for (String sourceDirectory : sourceDirectories) {
|
||||
FileSystemUtils.copyRecursively(
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.build.architecture.junit.enumsource.inferredfromparametertype;
|
||||
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
class EnumSourceInferredFromParameterType {
|
||||
|
||||
@EnumSource
|
||||
void exampleMethod(Example example) {
|
||||
|
||||
}
|
||||
|
||||
enum Example {
|
||||
|
||||
ONE, TWO, THREE
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.build.architecture.junit.enumsource.sameasparametertype;
|
||||
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
class EnumSourceSameAsParameterType {
|
||||
|
||||
@EnumSource(Example.class)
|
||||
void exampleMethod(Example example) {
|
||||
|
||||
}
|
||||
|
||||
enum Example {
|
||||
|
||||
ONE, TWO, THREE
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.build.architecture.junit.enumsource.valuenecessary;
|
||||
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
class EnumSourceValueNecessary {
|
||||
|
||||
@EnumSource(Example.class)
|
||||
void exampleMethod(String thing, Example example) {
|
||||
|
||||
}
|
||||
|
||||
enum Example {
|
||||
|
||||
ONE, TWO, THREE
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -112,7 +112,7 @@ class SbomEndpointWebExtensionTests {
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(value = SbomType.class, names = "UNKNOWN", mode = Mode.EXCLUDE)
|
||||
@EnumSource(names = "UNKNOWN", mode = Mode.EXCLUDE)
|
||||
void shouldAutodetectFormats(SbomType type) throws IOException {
|
||||
String content = getSbomContent(type);
|
||||
assertThat(type.matches(content)).isTrue();
|
||||
|
||||
+3
-4
@@ -45,10 +45,9 @@ class JacksonHttpMessageConvertersConfiguration {
|
||||
static class MappingJackson2HttpMessageConverterConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = MappingJackson2HttpMessageConverter.class,
|
||||
ignoredType = {
|
||||
"org.springframework.hateoas.server.mvc.TypeConstrainedMappingJackson2HttpMessageConverter",
|
||||
"org.springframework.data.rest.webmvc.alps.AlpsJsonHttpMessageConverter" })
|
||||
@ConditionalOnMissingBean(ignoredType = {
|
||||
"org.springframework.hateoas.server.mvc.TypeConstrainedMappingJackson2HttpMessageConverter",
|
||||
"org.springframework.data.rest.webmvc.alps.AlpsJsonHttpMessageConverter" })
|
||||
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {
|
||||
return new MappingJackson2HttpMessageConverter(objectMapper);
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ public class ErrorWebFluxAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = ErrorWebExceptionHandler.class, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
|
||||
@Order(-1)
|
||||
public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes,
|
||||
WebProperties webProperties, ObjectProvider<ViewResolver> viewResolvers,
|
||||
|
||||
+2
-2
@@ -62,8 +62,8 @@ class BatchDataSourceScriptDatabaseInitializerTests {
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(value = DatabaseDriver.class, mode = Mode.EXCLUDE, names = { "CLICKHOUSE", "FIREBIRD", "INFORMIX",
|
||||
"JTDS", "PHOENIX", "REDSHIFT", "TERADATA", "TESTCONTAINERS", "UNKNOWN" })
|
||||
@EnumSource(mode = Mode.EXCLUDE, names = { "CLICKHOUSE", "FIREBIRD", "INFORMIX", "JTDS", "PHOENIX", "REDSHIFT",
|
||||
"TERADATA", "TESTCONTAINERS", "UNKNOWN" })
|
||||
void batchSchemaCanBeLocated(DatabaseDriver driver) throws SQLException {
|
||||
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||
BatchProperties properties = new BatchProperties();
|
||||
|
||||
Reference in New Issue
Block a user