From e56a1ba561ac6ef19658c01e1d75985acde65db8 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 21 Nov 2014 14:16:37 -0800 Subject: [PATCH] Refine inner class detection algorithm Update the ConfigurationMetadataAnnotationProcessor nested class algorithm to prevent inner classes being added as both groups and properties. Fixes gh-1975 --- ...figurationMetadataAnnotationProcessor.java | 34 +++++++++++-------- ...ationMetadataAnnotationProcessorTests.java | 7 ++-- .../ConfigurationMetadataMatchers.java | 7 ++-- 3 files changed, 26 insertions(+), 22 deletions(-) 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 065be929f7..2835e1740f 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 @@ -175,8 +175,9 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor ExecutableElement getter = entry.getValue(); ExecutableElement setter = members.getPublicSetters().get(name); VariableElement field = members.getFields().get(name); - boolean isNested = getAnnotation(field, - nestedConfigurationPropertyAnnotation()) != null; + Element returnType = this.processingEnv.getTypeUtils().asElement( + getter.getReturnType()); + boolean isNested = isNested(returnType, field, element); boolean isCollection = this.typeUtils.isCollectionOrMap(getter .getReturnType()); if (!isNested && (setter != null || isCollection)) { @@ -203,24 +204,27 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor getter.getReturnType()); AnnotationMirror annotation = getAnnotation(getter, configurationPropertiesAnnotation()); - boolean isNested = getAnnotation(field, - nestedConfigurationPropertyAnnotation()) != null; + boolean isNested = isNested(returnType, field, element); if (returnType != null && returnType instanceof TypeElement - && annotation == null) { - TypeElement returns = (TypeElement) returnType; - if ((this.typeUtils.isEnclosedIn(returnType, element) && returnType - .getKind() != ElementKind.ENUM) || isNested) { - String nestedPrefix = ConfigurationMetadata - .nestedPrefix(prefix, name); - this.metadata.add(ItemMetadata.newGroup(nestedPrefix, - this.typeUtils.getType(returns), - this.typeUtils.getType(element), getter.toString())); - processTypeElement(nestedPrefix, returns); - } + && annotation == null && isNested) { + String nestedPrefix = ConfigurationMetadata.nestedPrefix(prefix, name); + this.metadata.add(ItemMetadata.newGroup(nestedPrefix, + this.typeUtils.getType(returnType), + this.typeUtils.getType(element), getter.toString())); + processTypeElement(nestedPrefix, (TypeElement) returnType); } } } + private boolean isNested(Element returnType, VariableElement field, + TypeElement element) { + if (getAnnotation(field, nestedConfigurationPropertyAnnotation()) != null) { + return true; + } + return this.typeUtils.isEnclosedIn(returnType, element) + && returnType.getKind() != ElementKind.ENUM; + } + private boolean hasDeprecateAnnotation(Element element) { return getAnnotation(element, "java.lang.Deprecated") != null; } 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 dabc9359f7..a42c82d903 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 @@ -236,17 +236,14 @@ public class ConfigurationMetadataAnnotationProcessorTests { assertThat(metadata, containsProperty("config.first.name")); assertThat(metadata, containsProperty("config.first.bar.name")); assertThat(metadata, - containsProperty("config.the-second", InnerClassProperties.Foo.class) + containsGroup("config.the-second", InnerClassProperties.Foo.class) .fromSource(InnerClassProperties.class)); assertThat(metadata, containsProperty("config.the-second.name")); assertThat(metadata, containsProperty("config.the-second.bar.name")); assertThat(metadata, containsGroup("config.third").ofType(SimplePojo.class) .fromSource(InnerClassProperties.class)); assertThat(metadata, containsProperty("config.third.value")); - assertThat( - metadata, - containsProperty("config.fourth").ofType( - InnerClassProperties.Fourth.class)); + assertThat(metadata, containsProperty("config.fourth")); assertThat(metadata, not(containsGroup("config.fourth"))); } diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataMatchers.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataMatchers.java index d6ee84bb96..353ee1d693 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataMatchers.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataMatchers.java @@ -119,10 +119,13 @@ public class ConfigurationMetadataMatchers { ConfigurationMetadata metadata = (ConfigurationMetadata) item; ItemMetadata property = getFirstPropertyWithName(metadata, this.name); if (property == null) { - description.appendText("missing property " + this.name); + description.appendText("missing " + + this.itemType.toString().toLowerCase() + " " + this.name); } else { - description.appendText("was property ").appendValue(property); + description.appendText( + "was " + this.itemType.toString().toLowerCase() + " ") + .appendValue(property); } }