From d60158ceb7cad822985c900d915c861b7570d2b9 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Jan 2026 10:11:39 +0000 Subject: [PATCH] Check that auto-configuration classes are listed in imports file Closes gh-48821 --- .../CheckAutoConfigurationClasses.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/CheckAutoConfigurationClasses.java b/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/CheckAutoConfigurationClasses.java index a6fbc857dae..c8132e1f0c1 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/CheckAutoConfigurationClasses.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/CheckAutoConfigurationClasses.java @@ -37,6 +37,7 @@ import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.FileCollection; import org.gradle.api.provider.SetProperty; import org.gradle.api.tasks.Classpath; +import org.gradle.api.tasks.Input; import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.VerificationException; @@ -113,16 +114,20 @@ public abstract class CheckAutoConfigurationClasses extends AutoConfigurationImp @OutputDirectory public abstract DirectoryProperty getOutputDirectory(); + @Input + public abstract SetProperty getOmittedFromImports(); + @TaskAction void execute() { Map> problems = new TreeMap<>(); Set optionalOnlyClassNames = new HashSet<>(this.optionalDependencyClassNames.get()); Set requiredClassNames = this.requiredDependencyClassNames.get(); optionalOnlyClassNames.removeAll(requiredClassNames); + List imports = loadImports(); classFiles().forEach((classFile) -> { AutoConfigurationClass autoConfigurationClass = AutoConfigurationClass.of(classFile); if (autoConfigurationClass != null) { - check(autoConfigurationClass, optionalOnlyClassNames, requiredClassNames, problems); + check(autoConfigurationClass, optionalOnlyClassNames, requiredClassNames, imports, problems); } }); File outputFile = getOutputDirectory().file("failure-report.txt").get().getAsFile(); @@ -151,11 +156,21 @@ public abstract class CheckAutoConfigurationClasses extends AutoConfigurationImp } private void check(AutoConfigurationClass autoConfigurationClass, Set optionalOnlyClassNames, - Set requiredClassNames, Map> problems) { + Set requiredClassNames, List imports, Map> problems) { if (!autoConfigurationClass.name().endsWith("AutoConfiguration")) { problems.computeIfAbsent(autoConfigurationClass.name(), (name) -> new ArrayList<>()) .add("Name of a class annotated with @AutoConfiguration should end with AutoConfiguration"); } + if (!getOmittedFromImports().getOrElse(Collections.emptySet()).contains(autoConfigurationClass.name()) + && !imports.contains(autoConfigurationClass.name())) { + problems.computeIfAbsent(autoConfigurationClass.name(), (name) -> new ArrayList<>()) + .add("Class is not registered in AutoConfiguration.imports"); + } + if (getOmittedFromImports().getOrElse(requiredClassNames).contains(autoConfigurationClass.name()) + && imports.contains(autoConfigurationClass.name())) { + problems.computeIfAbsent(autoConfigurationClass.name(), (name) -> new ArrayList<>()) + .add("Class should not be registered in AutoConfiguration.imports"); + } autoConfigurationClass.before().forEach((before) -> { if (optionalOnlyClassNames.contains(before)) { problems.computeIfAbsent(autoConfigurationClass.name(), (name) -> new ArrayList<>())