diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java index 63c2f916c42..ff31fa15847 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java @@ -180,7 +180,8 @@ public class MetricFilterAutoConfigurationTests { @Test public void skipsFilterIfPropertyDisabled() throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - EnvironmentTestUtils.addEnvironment(context, "endpoints.metrics.filter.enabled:false"); + EnvironmentTestUtils.addEnvironment(context, + "endpoints.metrics.filter.enabled:false"); context.register(Config.class, MetricFilterAutoConfiguration.class); context.refresh(); assertThat(context.getBeansOfType(Filter.class).size(), equalTo(0)); diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java index 96df30c179b..4875ab8fe7d 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java @@ -276,19 +276,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor String name = entry.getKey(); ExecutableElement getter = entry.getValue(); VariableElement field = members.getFields().get(name); - Element returnType = this.processingEnv.getTypeUtils() - .asElement(getter.getReturnType()); - AnnotationMirror annotation = getAnnotation(getter, - configurationPropertiesAnnotation()); - boolean isNested = isNested(returnType, field, element); - if (returnType != null && returnType instanceof TypeElement - && annotation == null && isNested) { - String nestedPrefix = ConfigurationMetadata.nestedPrefix(prefix, name); - this.metadataCollector.add(ItemMetadata.newGroup(nestedPrefix, - this.typeUtils.getType(returnType), - this.typeUtils.getType(element), getter.toString())); - processTypeElement(nestedPrefix, (TypeElement) returnType); - } + processNestedType(prefix, element, name, getter, field, + getter.getReturnType()); } } @@ -297,19 +286,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor for (Map.Entry entry : members.getFields().entrySet()) { String name = entry.getKey(); VariableElement field = entry.getValue(); - if (!isLombokField(field, element)) { - continue; - } - Element returnType = this.processingEnv.getTypeUtils() - .asElement(field.asType()); - boolean isNested = isNested(returnType, field, element); - if (returnType != null && returnType instanceof TypeElement - && isNested) { - String nestedPrefix = ConfigurationMetadata.nestedPrefix(prefix, name); - this.metadataCollector.add(ItemMetadata.newGroup(nestedPrefix, - this.typeUtils.getType(returnType), - this.typeUtils.getType(element), null)); - processTypeElement(nestedPrefix, (TypeElement) returnType); + if (isLombokField(field, element)) { + processNestedType(prefix, element, name, null, field, field.asType()); } } } @@ -327,6 +305,23 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor || hasAnnotation(element, LOMBOK_DATA_ANNOTATION)); } + private void processNestedType(String prefix, TypeElement element, String name, + ExecutableElement getter, VariableElement field, TypeMirror returnType) { + Element returnElement = this.processingEnv.getTypeUtils().asElement(returnType); + boolean isNested = isNested(returnElement, field, element); + AnnotationMirror annotation = getAnnotation(getter, + configurationPropertiesAnnotation()); + if (returnElement != null && returnElement instanceof TypeElement + && annotation == null && isNested) { + String nestedPrefix = ConfigurationMetadata.nestedPrefix(prefix, name); + this.metadataCollector.add(ItemMetadata.newGroup(nestedPrefix, + this.typeUtils.getType(returnElement), + this.typeUtils.getType(element), + (getter == null ? null : getter.toString()))); + processTypeElement(nestedPrefix, (TypeElement) returnElement); + } + } + private boolean isNested(Element returnType, VariableElement field, TypeElement element) { if (hasAnnotation(field, nestedConfigurationPropertyAnnotation())) { diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java index 7059a242d87..99fa18ad0de 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java @@ -366,11 +366,12 @@ public class ConfigurationMetadataAnnotationProcessorTests { assertThat(metadata, containsProperty("config.second.bar.name")); assertThat(metadata, containsGroup("config.third").ofType(SimpleLombokPojo.class) .fromSource(LombokInnerClassProperties.class)); - // For some reason the annotation processor resolves a type for SimpleLombokPojo that - // is resolved (compiled) and the source annotations are gone. Because we don't see the - // @Data annotation anymore, no field is harvested. What is crazy is that a sample project - // works fine so this seem to be related to the unit test environment for some reason. - //assertThat(metadata, containsProperty("config.third.value")); + // For some reason the annotation processor resolves a type for SimpleLombokPojo + // that is resolved (compiled) and the source annotations are gone. Because we + // don't see the @Data annotation anymore, no field is harvested. What is crazy is + // that a sample project works fine so this seem to be related to the unit test + // environment for some reason. assertThat(metadata, + // containsProperty("config.third.value")); assertThat(metadata, containsProperty("config.fourth")); assertThat(metadata, not(containsGroup("config.fourth"))); } @@ -507,34 +508,52 @@ public class ConfigurationMetadataAnnotationProcessorTests { .withDeprecation("Lame name.", "simple.the-name")); } + @Test + public void mergingOfAdditionalMetadata() throws Exception { + File metaInfFolder = new File(this.compiler.getOutputLocation(), "META-INF"); + metaInfFolder.mkdirs(); + File additionalMetadataFile = new File(metaInfFolder, + "additional-spring-configuration-metadata.json"); + additionalMetadataFile.createNewFile(); + JSONObject property = new JSONObject(); + property.put("name", "foo"); + property.put("type", "java.lang.String"); + property.put("sourceType", AdditionalMetadata.class.getName()); + JSONArray properties = new JSONArray(); + properties.put(property); + JSONObject additionalMetadata = new JSONObject(); + additionalMetadata.put("properties", properties); + FileWriter writer = new FileWriter(additionalMetadataFile); + additionalMetadata.write(writer); + writer.flush(); + ConfigurationMetadata metadata = compile(SimpleProperties.class); + assertThat(metadata, containsProperty("simple.comparator")); + assertThat(metadata, containsProperty("foo", String.class) + .fromSource(AdditionalMetadata.class)); + } + @Test public void incrementalBuild() throws Exception { TestProject project = new TestProject(this.temporaryFolder, FooProperties.class, BarProperties.class); assertFalse(project.getOutputFile(MetadataStore.METADATA_PATH).exists()); - ConfigurationMetadata metadata = project.fullBuild(); assertTrue(project.getOutputFile(MetadataStore.METADATA_PATH).exists()); - assertThat(metadata, containsProperty("foo.counter").fromSource(FooProperties.class)); assertThat(metadata, containsProperty("bar.counter").fromSource(BarProperties.class)); - metadata = project.incrementalBuild(BarProperties.class); - assertThat(metadata, containsProperty("foo.counter").fromSource(FooProperties.class)); assertThat(metadata, containsProperty("bar.counter").fromSource(BarProperties.class)); - project.addSourceCode(BarProperties.class, BarProperties.class.getResourceAsStream("BarProperties.snippet")); metadata = project.incrementalBuild(BarProperties.class); assertThat(metadata, containsProperty("bar.extra")); assertThat(metadata, containsProperty("foo.counter")); assertThat(metadata, containsProperty("bar.counter")); - project.revert(BarProperties.class); metadata = project.incrementalBuild(BarProperties.class); assertThat(metadata, not(containsProperty("bar.extra"))); @@ -549,7 +568,6 @@ public class ConfigurationMetadataAnnotationProcessorTests { ConfigurationMetadata metadata = project.fullBuild(); assertThat(metadata, containsProperty("foo.counter")); assertThat(metadata, containsProperty("bar.counter")); - project.replaceText(BarProperties.class, "@ConfigurationProperties", "//@ConfigurationProperties"); metadata = project.incrementalBuild(BarProperties.class); @@ -568,7 +586,6 @@ public class ConfigurationMetadataAnnotationProcessorTests { containsProperty("bar.counter").fromSource(BarProperties.class)); assertThat(metadata, not( containsProperty("bar.counter").fromSource(RenamedBarProperties.class))); - project.delete(BarProperties.class); project.add(RenamedBarProperties.class); metadata = project.incrementalBuild(RenamedBarProperties.class); diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/TestProject.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/TestProject.java index 81e1b36cafb..094280df776 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/TestProject.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/TestProject.java @@ -161,7 +161,7 @@ public class TestProject { /** * Restore source code of given class to its original contents. * @param type the class to revert - * @throws IOException in case of I/O errors + * @throws IOException on IO error */ public void revert(Class type) throws IOException { Assert.assertTrue(getSourceFile(type).exists()); @@ -171,7 +171,7 @@ public class TestProject { /** * Add source code of given class to this project. * @param type the class to add - * @throws IOException in case of I/O errors + * @throws IOException on IO error */ public void add(Class type) throws IOException { Assert.assertFalse(getSourceFile(type).exists()); diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/lombok/LombokInnerClassProperties.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/lombok/LombokInnerClassProperties.java index 9a2e1ae0244..3294d8e514a 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/lombok/LombokInnerClassProperties.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/lombok/LombokInnerClassProperties.java @@ -28,6 +28,7 @@ import org.springframework.boot.configurationsample.NestedConfigurationProperty; */ @Data @ConfigurationProperties(prefix = "config") +@SuppressWarnings("unused") public class LombokInnerClassProperties { private final Foo first = new Foo(); @@ -58,4 +59,5 @@ public class LombokInnerClassProperties { public enum Fourth { YES, NO } + } diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/lombok/SimpleLombokPojo.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/lombok/SimpleLombokPojo.java index e5ae9ae8848..c22e8a183a2 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/lombok/SimpleLombokPojo.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/lombok/SimpleLombokPojo.java @@ -24,6 +24,7 @@ import lombok.Data; * @author Stephane Nicoll */ @Data +@SuppressWarnings("unused") public class SimpleLombokPojo { private int value; diff --git a/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java b/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java index 1c3b7d00d65..539954b75b7 100644 --- a/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java +++ b/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java @@ -133,19 +133,15 @@ public abstract class AnsiOutput { private static boolean isEnabled() { if (enabled == Enabled.DETECT) { - return detectIfAnsiCapable(); + if (ansiCapable == null) { + ansiCapable = detectIfAnsiCapable(); + } + return ansiCapable; } return enabled == Enabled.ALWAYS; } private static boolean detectIfAnsiCapable() { - if (ansiCapable == null) { - ansiCapable = doDetectIfAnsiCapable(); - } - return ansiCapable; - } - - private static boolean doDetectIfAnsiCapable() { try { if (Boolean.FALSE.equals(consoleAvailable)) { return false;