Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ static List<ArchRule> standard() {
rules.add(methodLevelConfigurationPropertiesShouldNotSpecifyOnlyPrefixAttribute());
rules.add(conditionsShouldNotBePublic());
rules.add(allConfigurationPropertiesBindingBeanMethodsShouldBeStatic());
rules.add(allDeprecatedConfigurationPropertiesShouldIncludeSince());
return List.copyOf(rules);
}

Expand Down Expand Up @@ -348,6 +349,22 @@ private static ArchRule allConfigurationPropertiesBindingBeanMethodsShouldBeStat
.allowEmptyShould(true);
}

private static ArchRule allDeprecatedConfigurationPropertiesShouldIncludeSince() {
return methodsThatAreAnnotatedWith(
"org.springframework.boot.context.properties.DeprecatedConfigurationProperty")
.should(check("include a non-empty 'since' attribute", (method, events) -> {
JavaAnnotation<JavaMethod> annotation = method
.getAnnotationOfType("org.springframework.boot.context.properties.DeprecatedConfigurationProperty");
Map<String, Object> properties = annotation.getProperties();
Object since = properties.get("since");
if (!(since instanceof String) || ((String) since).isEmpty()) {
addViolation(events, method, annotation.getDescription()
+ " should include a non-empty 'since' attribute of @DeprecatedConfigurationProperty");
}
}))
.allowEmptyShould(true);
}

private static boolean containsOnlySingleType(JavaType[] types, JavaType type) {
return types.length == 1 && type.equals(types[0]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.gradle.api.file.FileTree;
import org.gradle.api.file.RegularFileProperty;
Expand Down Expand Up @@ -65,7 +63,7 @@ public FileTree getSource() {
}

@TaskAction
void check() throws JsonParseException, IOException {
void check() throws IOException {
Report report = createReport();
File reportFile = getReportLocation().get().getAsFile();
Files.write(reportFile.toPath(), report, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
Expand All @@ -76,21 +74,22 @@ void check() throws JsonParseException, IOException {
}

@SuppressWarnings("unchecked")
private Report createReport() throws IOException, JsonParseException, JsonMappingException {
private Report createReport() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
Report report = new Report();
for (File file : getSource().getFiles()) {
Analysis analysis = report.analysis(this.projectDir.toPath().relativize(file.toPath()));
Map<String, Object> json = objectMapper.readValue(file, Map.class);
check("groups", json, analysis);
check("properties", json, analysis);
check("hints", json, analysis);
checkSorting("groups", json, analysis);
checkSorting("properties", json, analysis);
checkSorting("hints", json, analysis);
checkPropertyDeprecationSince(json, analysis);
}
return report;
}

@SuppressWarnings("unchecked")
private void check(String key, Map<String, Object> json, Analysis analysis) {
private void checkSorting(String key, Map<String, Object> json, Analysis analysis) {
List<Map<String, Object>> groups = (List<Map<String, Object>>) json.getOrDefault(key, Collections.emptyList());
List<String> names = groups.stream().map((group) -> (String) group.get("name")).toList();
List<String> sortedNames = sortedCopy(names);
Expand All @@ -110,6 +109,18 @@ private List<String> sortedCopy(Collection<String> original) {
return copy;
}

@SuppressWarnings("unchecked")
private void checkPropertyDeprecationSince(Map<String, Object> json, Analysis analysis) {
List<Map<String, Object>> properties = (List<Map<String, Object>>) json.get("properties");
properties.stream().filter((property) -> property.containsKey("deprecation")).forEach((property) -> {
Map<String, Object> deprecation = (Map<String, Object>) property.get("deprecation");
if (!deprecation.containsKey("since")) {
analysis.problems.add("Property with name '" + property.get("name")
+ "' contains 'deprecation' without 'since' attribute");
}
});
}

private static final class Report implements Iterable<String> {

private final List<Analysis> analyses = new ArrayList<>();
Expand Down
Loading