Generate meta-data for nested Lombok types
Closes gh-4397
This commit is contained in:
		
							parent
							
								
									8ede966708
								
							
						
					
					
						commit
						ae13082e0d
					
				|  | @ -176,8 +176,9 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor | |||
| 		TypeElementMembers members = new TypeElementMembers(this.processingEnv, element); | ||||
| 		Map<String, Object> fieldValues = getFieldValues(element); | ||||
| 		processSimpleTypes(prefix, element, members, fieldValues); | ||||
| 		processLombokTypes(prefix, element, members, fieldValues); | ||||
| 		processSimpleLombokTypes(prefix, element, members, fieldValues); | ||||
| 		processNestedTypes(prefix, element, members); | ||||
| 		processNestedLombokTypes(prefix, element, members); | ||||
| 	} | ||||
| 
 | ||||
| 	private Map<String, Object> getFieldValues(TypeElement element) { | ||||
|  | @ -218,7 +219,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void processLombokTypes(String prefix, TypeElement element, | ||||
| 	private void processSimpleLombokTypes(String prefix, TypeElement element, | ||||
| 			TypeElementMembers members, Map<String, Object> fieldValues) { | ||||
| 		for (Map.Entry<String, VariableElement> entry : members.getFields().entrySet()) { | ||||
| 			String name = entry.getKey(); | ||||
|  | @ -247,19 +248,6 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean isLombokField(VariableElement field, TypeElement element) { | ||||
| 		return hasAnnotation(field, LOMBOK_GETTER_ANNOTATION) | ||||
| 				|| hasAnnotation(element, LOMBOK_GETTER_ANNOTATION) | ||||
| 				|| hasAnnotation(element, LOMBOK_DATA_ANNOTATION); | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean hasLombokSetter(VariableElement field, TypeElement element) { | ||||
| 		return !field.getModifiers().contains(Modifier.FINAL) | ||||
| 				&& (hasAnnotation(field, LOMBOK_SETTER_ANNOTATION) | ||||
| 						|| hasAnnotation(element, LOMBOK_SETTER_ANNOTATION) | ||||
| 						|| hasAnnotation(element, LOMBOK_DATA_ANNOTATION)); | ||||
| 	} | ||||
| 
 | ||||
| 	private void processNestedTypes(String prefix, TypeElement element, | ||||
| 			TypeElementMembers members) { | ||||
| 		for (Map.Entry<String, ExecutableElement> entry : members.getPublicGetters() | ||||
|  | @ -283,6 +271,41 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void processNestedLombokTypes(String prefix, TypeElement element, | ||||
| 			TypeElementMembers members) { | ||||
| 		for (Map.Entry<String, VariableElement> 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); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean isLombokField(VariableElement field, TypeElement element) { | ||||
| 		return hasAnnotation(field, LOMBOK_GETTER_ANNOTATION) | ||||
| 				|| hasAnnotation(element, LOMBOK_GETTER_ANNOTATION) | ||||
| 				|| hasAnnotation(element, LOMBOK_DATA_ANNOTATION); | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean hasLombokSetter(VariableElement field, TypeElement element) { | ||||
| 		return !field.getModifiers().contains(Modifier.FINAL) | ||||
| 				&& (hasAnnotation(field, LOMBOK_SETTER_ANNOTATION) | ||||
| 						|| hasAnnotation(element, LOMBOK_SETTER_ANNOTATION) | ||||
| 						|| hasAnnotation(element, LOMBOK_DATA_ANNOTATION)); | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean isNested(Element returnType, VariableElement field, | ||||
| 			TypeElement element) { | ||||
| 		if (hasAnnotation(field, nestedConfigurationPropertyAnnotation())) { | ||||
|  |  | |||
|  | @ -32,8 +32,10 @@ import org.springframework.boot.configurationsample.incremental.BarProperties; | |||
| import org.springframework.boot.configurationsample.incremental.FooProperties; | ||||
| import org.springframework.boot.configurationsample.incremental.RenamedBarProperties; | ||||
| import org.springframework.boot.configurationsample.lombok.LombokExplicitProperties; | ||||
| import org.springframework.boot.configurationsample.lombok.LombokInnerClassProperties; | ||||
| 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.EmptyTypeMethodConfig; | ||||
| import org.springframework.boot.configurationsample.method.InvalidMethodConfig; | ||||
| import org.springframework.boot.configurationsample.method.MethodAndClassConfig; | ||||
|  | @ -300,6 +302,32 @@ public class ConfigurationMetadataAnnotationProcessorTests { | |||
| 				"explicit"); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void lombokInnerClassProperties() throws Exception { | ||||
| 		ConfigurationMetadata metadata = compile(LombokInnerClassProperties.class); | ||||
| 		assertThat(metadata, | ||||
| 				containsGroup("config").fromSource(LombokInnerClassProperties.class)); | ||||
| 		assertThat(metadata, | ||||
| 				containsGroup("config.first").ofType(LombokInnerClassProperties.Foo.class) | ||||
| 						.fromSource(LombokInnerClassProperties.class)); | ||||
| 		assertThat(metadata, containsProperty("config.first.name")); | ||||
| 		assertThat(metadata, containsProperty("config.first.bar.name")); | ||||
| 		assertThat(metadata, | ||||
| 				containsGroup("config.second", LombokInnerClassProperties.Foo.class) | ||||
| 						.fromSource(LombokInnerClassProperties.class)); | ||||
| 		assertThat(metadata, containsProperty("config.second.name")); | ||||
| 		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")); | ||||
| 		assertThat(metadata, containsProperty("config.fourth")); | ||||
| 		assertThat(metadata, not(containsGroup("config.fourth"))); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void mergingOfAdditionalMetadata() throws Exception { | ||||
| 		File metaInfFolder = new File(this.compiler.getOutputLocation(), "META-INF"); | ||||
|  |  | |||
|  | @ -0,0 +1,61 @@ | |||
| /* | ||||
|  * Copyright 2012-2015 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.lombok; | ||||
| 
 | ||||
| import lombok.Data; | ||||
| 
 | ||||
| import org.springframework.boot.configurationsample.ConfigurationProperties; | ||||
| import org.springframework.boot.configurationsample.NestedConfigurationProperty; | ||||
| 
 | ||||
| /** | ||||
|  * Demonstrate the auto-detection of inner config classes using Lombok. | ||||
|  * | ||||
|  * @author Stephane Nicoll | ||||
|  */ | ||||
| @Data | ||||
| @ConfigurationProperties(prefix = "config") | ||||
| public class LombokInnerClassProperties { | ||||
| 
 | ||||
| 	private final Foo first = new Foo(); | ||||
| 
 | ||||
| 	private Foo second = new Foo(); | ||||
| 
 | ||||
| 	@NestedConfigurationProperty | ||||
| 	private final SimpleLombokPojo third = new SimpleLombokPojo(); | ||||
| 
 | ||||
| 	private Fourth fourth; | ||||
| 
 | ||||
| 	@Data | ||||
| 	public static class Foo { | ||||
| 
 | ||||
| 		private String name; | ||||
| 
 | ||||
| 		private final Bar bar = new Bar(); | ||||
| 
 | ||||
| 		@Data | ||||
| 		public static class Bar { | ||||
| 
 | ||||
| 			private String name; | ||||
| 
 | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	public enum Fourth { | ||||
| 		YES, NO | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,31 @@ | |||
| /* | ||||
|  * Copyright 2012-2015 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.lombok; | ||||
| 
 | ||||
| import lombok.Data; | ||||
| 
 | ||||
| /** | ||||
|  * Lombok POJO for use with samples. | ||||
|  * | ||||
|  * @author Stephane Nicoll | ||||
|  */ | ||||
| @Data | ||||
| public class SimpleLombokPojo { | ||||
| 
 | ||||
| 	private int value; | ||||
| 
 | ||||
| } | ||||
|  | @ -1,5 +1,5 @@ | |||
| /* | ||||
|  * Copyright 2012-2014 the original author or authors. | ||||
|  * Copyright 2012-2015 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. | ||||
|  | @ -20,7 +20,7 @@ import org.springframework.boot.configurationsample.ConfigurationProperties; | |||
| import org.springframework.boot.configurationsample.NestedConfigurationProperty; | ||||
| 
 | ||||
| /** | ||||
|  * Demonstrate the auto-detection of a inner config classes. | ||||
|  * Demonstrate the auto-detection of inner config classes. | ||||
|  * | ||||
|  * @author Stephane Nicoll | ||||
|  */ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue