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 47ea1361212..b3d7768f1f5 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 @@ -163,7 +163,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor private void processAnnotatedTypeElement(String prefix, TypeElement element) { String type = this.typeUtils.getType(element); this.metadataCollector.add(ItemMetadata.newGroup(prefix, type, type, null)); - processTypeElement(prefix, element); + processTypeElement(prefix, element, null); } private void processExecutableElement(String prefix, ExecutableElement element) { @@ -184,19 +184,20 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor } else { this.metadataCollector.add(group); - processTypeElement(prefix, (TypeElement) returns); + processTypeElement(prefix, (TypeElement) returns, element); } } } } - private void processTypeElement(String prefix, TypeElement element) { + private void processTypeElement(String prefix, TypeElement element, + ExecutableElement source) { TypeElementMembers members = new TypeElementMembers(this.processingEnv, element); Map fieldValues = getFieldValues(element); - processSimpleTypes(prefix, element, members, fieldValues); - processSimpleLombokTypes(prefix, element, members, fieldValues); - processNestedTypes(prefix, element, members); - processNestedLombokTypes(prefix, element, members); + processSimpleTypes(prefix, element, source, members, fieldValues); + processSimpleLombokTypes(prefix, element, source, members, fieldValues); + processNestedTypes(prefix, element, source, members); + processNestedLombokTypes(prefix, element, source, members); } private Map getFieldValues(TypeElement element) { @@ -209,7 +210,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor } private void processSimpleTypes(String prefix, TypeElement element, - TypeElementMembers members, Map fieldValues) { + ExecutableElement source, TypeElementMembers members, + Map fieldValues) { for (Map.Entry entry : members.getPublicGetters() .entrySet()) { String name = entry.getKey(); @@ -228,7 +230,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor String description = this.typeUtils.getJavaDoc(field); Object defaultValue = fieldValues.get(name); boolean deprecated = isDeprecated(getter) || isDeprecated(setter) - || isDeprecated(element); + || isDeprecated(source); this.metadataCollector.add(ItemMetadata.newProperty(prefix, name, dataType, sourceType, null, description, defaultValue, (deprecated ? getItemDeprecation(getter) : null))); @@ -251,7 +253,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor } private void processSimpleLombokTypes(String prefix, TypeElement element, - TypeElementMembers members, Map fieldValues) { + ExecutableElement source, TypeElementMembers members, + Map fieldValues) { for (Map.Entry entry : members.getFields().entrySet()) { String name = entry.getKey(); VariableElement field = entry.getValue(); @@ -270,7 +273,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor String sourceType = this.typeUtils.getType(element); String description = this.typeUtils.getJavaDoc(field); Object defaultValue = fieldValues.get(name); - boolean deprecated = isDeprecated(field) || isDeprecated(element); + boolean deprecated = isDeprecated(field) || isDeprecated(source); this.metadataCollector.add(ItemMetadata.newProperty(prefix, name, dataType, sourceType, null, description, defaultValue, (deprecated ? new ItemDeprecation() : null))); @@ -279,24 +282,25 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor } private void processNestedTypes(String prefix, TypeElement element, - TypeElementMembers members) { + ExecutableElement source, TypeElementMembers members) { for (Map.Entry entry : members.getPublicGetters() .entrySet()) { String name = entry.getKey(); ExecutableElement getter = entry.getValue(); VariableElement field = members.getFields().get(name); - processNestedType(prefix, element, name, getter, field, + processNestedType(prefix, element, source, name, getter, field, getter.getReturnType()); } } private void processNestedLombokTypes(String prefix, TypeElement element, - TypeElementMembers members) { + ExecutableElement source, TypeElementMembers members) { for (Map.Entry entry : members.getFields().entrySet()) { String name = entry.getKey(); VariableElement field = entry.getValue(); if (isLombokField(field, element)) { - processNestedType(prefix, element, name, null, field, field.asType()); + processNestedType(prefix, element, source, name, null, field, + field.asType()); } } } @@ -314,8 +318,9 @@ 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) { + private void processNestedType(String prefix, TypeElement element, + ExecutableElement source, 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, @@ -327,7 +332,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor this.typeUtils.getType(returnElement), this.typeUtils.getType(element), (getter == null ? null : getter.toString()))); - processTypeElement(nestedPrefix, (TypeElement) returnElement); + processTypeElement(nestedPrefix, (TypeElement) returnElement, source); } } @@ -341,6 +346,17 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor } private boolean isDeprecated(Element element) { + if (isElementDeprecated(element)) { + return true; + } + if (element != null && (element instanceof VariableElement + || element instanceof ExecutableElement)) { + return isElementDeprecated(element.getEnclosingElement()); + } + return false; + } + + private boolean isElementDeprecated(Element element) { return hasAnnotation(element, "java.lang.Deprecated") || hasAnnotation(element, deprecatedConfigurationPropertyAnnotation()); } 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 c33fb0f7311..9a2f65f8771 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 @@ -42,6 +42,8 @@ import org.springframework.boot.configurationsample.lombok.LombokInnerClassPrope import org.springframework.boot.configurationsample.lombok.LombokSimpleDataProperties; import org.springframework.boot.configurationsample.lombok.LombokSimpleProperties; import org.springframework.boot.configurationsample.lombok.SimpleLombokPojo; +import org.springframework.boot.configurationsample.method.DeprecatedClassMethodConfig; +import org.springframework.boot.configurationsample.method.DeprecatedMethodConfig; import org.springframework.boot.configurationsample.method.EmptyTypeMethodConfig; import org.springframework.boot.configurationsample.method.InvalidMethodConfig; import org.springframework.boot.configurationsample.method.MethodAndClassConfig; @@ -284,6 +286,34 @@ public class ConfigurationMetadataAnnotationProcessorTests { assertThat(metadata).isNotEqualTo(Metadata.withProperty("something.foo")); } + @Test + public void deprecatedMethodConfig() throws Exception { + Class type = DeprecatedMethodConfig.class; + ConfigurationMetadata metadata = compile(type); + assertThat(metadata) + .has(Metadata.withGroup("foo").fromSource(type)); + assertThat(metadata).has(Metadata.withProperty("foo.name", String.class) + .fromSource(DeprecatedMethodConfig.Foo.class) + .withDeprecation(null, null)); + assertThat(metadata).has(Metadata.withProperty("foo.flag", Boolean.class) + .fromSource(DeprecatedMethodConfig.Foo.class) + .withDeprecation(null, null)); + } + + @Test + public void deprecatedMethodConfigOnClass() throws Exception { + Class type = DeprecatedClassMethodConfig.class; + ConfigurationMetadata metadata = compile(type); + assertThat(metadata) + .has(Metadata.withGroup("foo").fromSource(type)); + assertThat(metadata).has(Metadata.withProperty("foo.name", String.class) + .fromSource(DeprecatedClassMethodConfig.Foo.class) + .withDeprecation(null, null)); + assertThat(metadata).has(Metadata.withProperty("foo.flag", Boolean.class) + .fromSource(DeprecatedClassMethodConfig.Foo.class) + .withDeprecation(null, null)); + } + @Test public void innerClassRootConfig() throws Exception { ConfigurationMetadata metadata = compile(InnerClassRootConfig.class); diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/method/DeprecatedClassMethodConfig.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/method/DeprecatedClassMethodConfig.java new file mode 100644 index 00000000000..99d9494bea7 --- /dev/null +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/method/DeprecatedClassMethodConfig.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012-2016 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 + * + * http://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.configurationsample.method; + +import org.springframework.boot.configurationsample.ConfigurationProperties; + +/** + * Sample for testing method configuration with deprecated class. + * + * @author Stephane Nicoll + */ +@Deprecated +public class DeprecatedClassMethodConfig { + + @ConfigurationProperties(prefix = "foo") + public Foo foo() { + return new Foo(); + } + + public static class Foo { + + private String name; + + private boolean flag; + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isFlag() { + return this.flag; + } + + public void setFlag(boolean flag) { + this.flag = flag; + } + } + +} diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/method/DeprecatedMethodConfig.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/method/DeprecatedMethodConfig.java new file mode 100644 index 00000000000..fc3e4abe6ad --- /dev/null +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/method/DeprecatedMethodConfig.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012-2016 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 + * + * http://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.configurationsample.method; + +import org.springframework.boot.configurationsample.ConfigurationProperties; + +/** + * Sample for testing deprecated method configuration. + * + * @author Stephane Nicoll + */ +public class DeprecatedMethodConfig { + + @ConfigurationProperties(prefix = "foo") + @Deprecated + public Foo foo() { + return new Foo(); + } + + public static class Foo { + + private String name; + + private boolean flag; + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isFlag() { + return this.flag; + } + + public void setFlag(boolean flag) { + this.flag = flag; + } + } + +}