Merge branch '2.7.x'
Closes gh-33871
This commit is contained in:
@@ -59,23 +59,22 @@ class PropertyDescriptorResolver {
|
||||
if (factoryMethod != null) {
|
||||
return resolveJavaBeanProperties(type, factoryMethod, members);
|
||||
}
|
||||
return resolve(ConfigurationPropertiesTypeElement.of(type, this.environment), factoryMethod, members);
|
||||
return resolve(ConfigurationPropertiesTypeElement.of(type, this.environment), members);
|
||||
}
|
||||
|
||||
private Stream<PropertyDescriptor<?>> resolve(ConfigurationPropertiesTypeElement type,
|
||||
ExecutableElement factoryMethod, TypeElementMembers members) {
|
||||
private Stream<PropertyDescriptor<?>> resolve(ConfigurationPropertiesTypeElement type, TypeElementMembers members) {
|
||||
if (type.isConstructorBindingEnabled()) {
|
||||
ExecutableElement constructor = type.getBindConstructor();
|
||||
if (constructor != null) {
|
||||
return resolveConstructorProperties(type.getType(), factoryMethod, members, constructor);
|
||||
return resolveConstructorProperties(type.getType(), members, constructor);
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
return resolveJavaBeanProperties(type.getType(), factoryMethod, members);
|
||||
return resolveJavaBeanProperties(type.getType(), null, members);
|
||||
}
|
||||
|
||||
Stream<PropertyDescriptor<?>> resolveConstructorProperties(TypeElement type, ExecutableElement factoryMethod,
|
||||
TypeElementMembers members, ExecutableElement constructor) {
|
||||
Stream<PropertyDescriptor<?>> resolveConstructorProperties(TypeElement type, TypeElementMembers members,
|
||||
ExecutableElement constructor) {
|
||||
Map<String, PropertyDescriptor<?>> candidates = new LinkedHashMap<>();
|
||||
constructor.getParameters().forEach((parameter) -> {
|
||||
String name = getParameterName(parameter);
|
||||
@@ -83,8 +82,8 @@ class PropertyDescriptorResolver {
|
||||
ExecutableElement getter = members.getPublicGetter(name, propertyType);
|
||||
ExecutableElement setter = members.getPublicSetter(name, propertyType);
|
||||
VariableElement field = members.getFields().get(name);
|
||||
register(candidates, new ConstructorParameterPropertyDescriptor(type, factoryMethod, parameter, name,
|
||||
propertyType, field, getter, setter));
|
||||
register(candidates, new ConstructorParameterPropertyDescriptor(type, null, parameter, name, propertyType,
|
||||
field, getter, setter));
|
||||
});
|
||||
return candidates.values().stream();
|
||||
}
|
||||
|
||||
@@ -38,15 +38,20 @@ import javax.lang.model.util.ElementFilter;
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class TypeElementMembers {
|
||||
|
||||
private static final String OBJECT_CLASS_NAME = Object.class.getName();
|
||||
|
||||
private static final String RECORD_CLASS_NAME = "java.lang.Record";
|
||||
|
||||
private final MetadataGenerationEnvironment env;
|
||||
|
||||
private final TypeElement targetType;
|
||||
|
||||
private final boolean isRecord;
|
||||
|
||||
private final Map<String, VariableElement> fields = new LinkedHashMap<>();
|
||||
|
||||
private final Map<String, List<ExecutableElement>> publicGetters = new LinkedHashMap<>();
|
||||
@@ -56,18 +61,20 @@ class TypeElementMembers {
|
||||
TypeElementMembers(MetadataGenerationEnvironment env, TypeElement targetType) {
|
||||
this.env = env;
|
||||
this.targetType = targetType;
|
||||
this.isRecord = RECORD_CLASS_NAME.equals(targetType.getSuperclass().toString());
|
||||
process(targetType);
|
||||
}
|
||||
|
||||
private void process(TypeElement element) {
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) {
|
||||
processMethod(method);
|
||||
}
|
||||
for (VariableElement field : ElementFilter.fieldsIn(element.getEnclosedElements())) {
|
||||
processField(field);
|
||||
}
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) {
|
||||
processMethod(method);
|
||||
}
|
||||
Element superType = this.env.getTypeUtils().asElement(element.getSuperclass());
|
||||
if (superType instanceof TypeElement && !OBJECT_CLASS_NAME.equals(superType.toString())) {
|
||||
if (superType instanceof TypeElement && !OBJECT_CLASS_NAME.equals(superType.toString())
|
||||
&& !RECORD_CLASS_NAME.equals(superType.toString())) {
|
||||
process((TypeElement) superType);
|
||||
}
|
||||
}
|
||||
@@ -122,12 +129,22 @@ class TypeElementMembers {
|
||||
}
|
||||
|
||||
private boolean isGetter(ExecutableElement method) {
|
||||
boolean hasParameters = !method.getParameters().isEmpty();
|
||||
boolean returnsVoid = TypeKind.VOID == method.getReturnType().getKind();
|
||||
if (hasParameters || returnsVoid) {
|
||||
return false;
|
||||
}
|
||||
String name = method.getSimpleName().toString();
|
||||
return ((name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2))
|
||||
&& method.getParameters().isEmpty() && (TypeKind.VOID != method.getReturnType().getKind());
|
||||
if (this.isRecord && this.fields.containsKey(name)) {
|
||||
return true;
|
||||
}
|
||||
return (name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2);
|
||||
}
|
||||
|
||||
private boolean isSetter(ExecutableElement method) {
|
||||
if (this.isRecord) {
|
||||
return false;
|
||||
}
|
||||
final String name = method.getSimpleName().toString();
|
||||
return (name.startsWith("set") && name.length() > 3 && method.getParameters().size() == 1
|
||||
&& isSetterReturnType(method));
|
||||
@@ -151,16 +168,29 @@ class TypeElementMembers {
|
||||
}
|
||||
|
||||
private String getAccessorName(String methodName) {
|
||||
String name = methodName.startsWith("is") ? methodName.substring(2) : methodName.substring(3);
|
||||
if (this.isRecord) {
|
||||
return methodName;
|
||||
}
|
||||
String name;
|
||||
if (methodName.startsWith("is")) {
|
||||
name = methodName.substring(2);
|
||||
}
|
||||
else if (methodName.startsWith("get")) {
|
||||
name = methodName.substring(3);
|
||||
}
|
||||
else if (methodName.startsWith("set")) {
|
||||
name = methodName.substring(3);
|
||||
}
|
||||
else {
|
||||
throw new AssertionError("methodName must start with 'is', 'get' or 'set', was '" + methodName + "'");
|
||||
}
|
||||
name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
|
||||
return name;
|
||||
}
|
||||
|
||||
private void processField(VariableElement field) {
|
||||
String name = field.getSimpleName().toString();
|
||||
if (!this.fields.containsKey(name)) {
|
||||
this.fields.put(name, field);
|
||||
}
|
||||
this.fields.putIfAbsent(name, field);
|
||||
}
|
||||
|
||||
Map<String, VariableElement> getFields() {
|
||||
|
||||
Reference in New Issue
Block a user