diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java index 7cc52dfac7..a1ac4c102d 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -177,7 +177,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor } if (roundEnv.processingOver()) { try { - writeMetaData(); + writeMetadata(); } catch (Exception ex) { throw new IllegalStateException("Failed to write metadata", ex); @@ -324,7 +324,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor return null; } - protected ConfigurationMetadata writeMetaData() throws Exception { + protected ConfigurationMetadata writeMetadata() throws Exception { ConfigurationMetadata metadata = this.metadataCollector.getMetadata(); metadata = mergeAdditionalMetadata(metadata); if (!metadata.getItems().isEmpty()) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/PropertyDescriptor.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/PropertyDescriptor.java index 355ac02b1a..83cc347042 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/PropertyDescriptor.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/PropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2022 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. @@ -119,7 +119,7 @@ abstract class PropertyDescriptor { if (isCyclePresent(typeElement, getOwnerElement())) { return false; } - return isParentTheSame(typeElement, getOwnerElement()); + return isParentTheSame(environment, typeElement, getOwnerElement()); } ItemMetadata resolveItemMetadata(String prefix, MetadataGenerationEnvironment environment) { @@ -169,11 +169,20 @@ abstract class PropertyDescriptor { return isCyclePresent(returnType, element.getEnclosingElement()); } - private boolean isParentTheSame(Element returnType, TypeElement element) { + private boolean isParentTheSame(MetadataGenerationEnvironment environment, Element returnType, + TypeElement element) { if (returnType == null || element == null) { return false; } - return getTopLevelType(returnType).equals(getTopLevelType(element)); + returnType = getTopLevelType(returnType); + Element candidate = element; + while (candidate != null && candidate instanceof TypeElement) { + if (returnType.equals(getTopLevelType(candidate))) { + return true; + } + candidate = environment.getTypeUtils().asElement(((TypeElement) candidate).getSuperclass()); + } + return false; } private Element getTopLevelType(Element element) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/InheritanceMetadataGenerationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/InheritanceMetadataGenerationTests.java new file mode 100644 index 0000000000..48c7217228 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/InheritanceMetadataGenerationTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.configurationprocessor; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata; +import org.springframework.boot.configurationprocessor.metadata.Metadata; +import org.springframework.boot.configurationsample.inheritance.ChildProperties; +import org.springframework.boot.configurationsample.inheritance.ChildPropertiesConfig; +import org.springframework.boot.configurationsample.inheritance.OverrideChildProperties; +import org.springframework.boot.configurationsample.inheritance.OverrideChildPropertiesConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +class InheritanceMetadataGenerationTests extends AbstractMetadataGenerationTests { + + @Test + void childProperties() throws Exception { + ConfigurationMetadata metadata = compile(ChildPropertiesConfig.class); + assertThat(metadata).has(Metadata.withGroup("inheritance").fromSource(ChildPropertiesConfig.class)); + assertThat(metadata).has(Metadata.withGroup("inheritance.nest").fromSource(ChildProperties.class)); + assertThat(metadata).has(Metadata.withGroup("inheritance.child-nest").fromSource(ChildProperties.class)); + assertThat(metadata).has(Metadata.withProperty("inheritance.bool-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.int-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.long-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.nest.bool-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.nest.int-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.child-nest.bool-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.child-nest.int-value")); + } + + @Test + void overrideChildProperties() throws Exception { + ConfigurationMetadata metadata = compile(OverrideChildPropertiesConfig.class); + assertThat(metadata).has(Metadata.withGroup("inheritance").fromSource(OverrideChildPropertiesConfig.class)); + assertThat(metadata).has(Metadata.withGroup("inheritance.nest").fromSource(OverrideChildProperties.class)); + assertThat(metadata).has(Metadata.withProperty("inheritance.bool-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.int-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.long-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.nest.bool-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.nest.int-value")); + assertThat(metadata).has(Metadata.withProperty("inheritance.nest.long-value")); + + } + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/test/TestConfigurationMetadataAnnotationProcessor.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/test/TestConfigurationMetadataAnnotationProcessor.java index 592a5a5f45..59e7f52dd4 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/test/TestConfigurationMetadataAnnotationProcessor.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/test/TestConfigurationMetadataAnnotationProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -127,8 +127,8 @@ public class TestConfigurationMetadataAnnotationProcessor extends ConfigurationM } @Override - protected ConfigurationMetadata writeMetaData() throws Exception { - super.writeMetaData(); + protected ConfigurationMetadata writeMetadata() throws Exception { + super.writeMetadata(); try { File metadataFile = new File(this.outputLocation, "META-INF/spring-configuration-metadata.json"); if (metadataFile.isFile()) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/BaseProperties.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/BaseProperties.java new file mode 100644 index 0000000000..b83d54e0e1 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/BaseProperties.java @@ -0,0 +1,71 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.inheritance; + +public class BaseProperties { + + private boolean boolValue; + + private int intValue; + + private final Nest nest = new Nest(); + + public boolean isBoolValue() { + return this.boolValue; + } + + public void setBoolValue(boolean boolValue) { + this.boolValue = boolValue; + } + + public int getIntValue() { + return this.intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + public Nest getNest() { + return this.nest; + } + + public static class Nest { + + private boolean boolValue; + + private int intValue; + + public boolean isBoolValue() { + return this.boolValue; + } + + public void setBoolValue(boolean boolValue) { + this.boolValue = boolValue; + } + + public int getIntValue() { + return this.intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + } + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/ChildProperties.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/ChildProperties.java new file mode 100644 index 0000000000..a4832030b0 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/ChildProperties.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.inheritance; + +public class ChildProperties extends BaseProperties { + + private long longValue; + + private final NestInChild childNest = new NestInChild(); + + public long getLongValue() { + return this.longValue; + } + + public void setLongValue(long longValue) { + this.longValue = longValue; + } + + public NestInChild getChildNest() { + return this.childNest; + } + + public static class NestInChild { + + private boolean boolValue; + + private int intValue; + + public boolean isBoolValue() { + return this.boolValue; + } + + public void setBoolValue(boolean boolValue) { + this.boolValue = boolValue; + } + + public int getIntValue() { + return this.intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + } + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/ChildPropertiesConfig.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/ChildPropertiesConfig.java new file mode 100644 index 0000000000..3ff388df6e --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/ChildPropertiesConfig.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.inheritance; + +import org.springframework.boot.configurationsample.ConfigurationProperties; + +public class ChildPropertiesConfig { + + @ConfigurationProperties(prefix = "inheritance") + public ChildProperties childConfig() { + return new ChildProperties(); + } + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/OverrideChildProperties.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/OverrideChildProperties.java new file mode 100644 index 0000000000..012cc9f264 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/OverrideChildProperties.java @@ -0,0 +1,36 @@ +package org.springframework.boot.configurationsample.inheritance; + +public class OverrideChildProperties extends BaseProperties { + + private long longValue; + + private final CustomNest nest = new CustomNest(); + + public long getLongValue() { + return this.longValue; + } + + public void setLongValue(long longValue) { + this.longValue = longValue; + } + + @Override + public CustomNest getNest() { + return this.nest; + } + + public static class CustomNest extends Nest { + + private long longValue; + + public long getLongValue() { + return this.longValue; + } + + public void setLongValue(long longValue) { + this.longValue = longValue; + } + + } + +} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/OverrideChildPropertiesConfig.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/OverrideChildPropertiesConfig.java new file mode 100644 index 0000000000..324d12c2a4 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/inheritance/OverrideChildPropertiesConfig.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.inheritance; + +import org.springframework.boot.configurationsample.ConfigurationProperties; + +public class OverrideChildPropertiesConfig { + + @ConfigurationProperties(prefix = "inheritance") + public OverrideChildProperties overrideChildProperties() { + return new OverrideChildProperties(); + } + +}