Skip to content

Commit 4a8646b

Browse files
committed
Merge branch '2.2.x' into 2.3.x
Closes gh-24058
2 parents 1e10067 + 59ea7c1 commit 4a8646b

File tree

5 files changed

+118
-26
lines changed

5 files changed

+118
-26
lines changed

spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/PropertyDescriptorResolver.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -91,10 +91,12 @@ Stream<PropertyDescriptor<?>> resolveJavaBeanProperties(TypeElement type, Execut
9191
TypeElementMembers members) {
9292
// First check if we have regular java bean properties there
9393
Map<String, PropertyDescriptor<?>> candidates = new LinkedHashMap<>();
94-
members.getPublicGetters().forEach((name, getter) -> {
94+
members.getPublicGetters().forEach((name, getters) -> {
95+
VariableElement field = members.getFields().get(name);
96+
ExecutableElement getter = findMatchingGetter(members, getters, field);
9597
TypeMirror propertyType = getter.getReturnType();
96-
register(candidates, new JavaBeanPropertyDescriptor(type, factoryMethod, getter, name, propertyType,
97-
members.getFields().get(name), members.getPublicSetter(name, propertyType)));
98+
register(candidates, new JavaBeanPropertyDescriptor(type, factoryMethod, getter, name, propertyType, field,
99+
members.getPublicSetter(name, propertyType)));
98100
});
99101
// Then check for Lombok ones
100102
members.getFields().forEach((name, field) -> {
@@ -107,6 +109,14 @@ Stream<PropertyDescriptor<?>> resolveJavaBeanProperties(TypeElement type, Execut
107109
return candidates.values().stream();
108110
}
109111

112+
private ExecutableElement findMatchingGetter(TypeElementMembers members, List<ExecutableElement> candidates,
113+
VariableElement field) {
114+
if (candidates.size() > 1 && field != null) {
115+
return members.getMatchingGetter(candidates, field.asType());
116+
}
117+
return candidates.get(0);
118+
}
119+
110120
private void register(Map<String, PropertyDescriptor<?>> candidates, PropertyDescriptor<?> descriptor) {
111121
if (!candidates.containsKey(descriptor.getName()) && isCandidate(descriptor)) {
112122
candidates.put(descriptor.getName(), descriptor);

spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeElementMembers.java

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.List;
2323
import java.util.Map;
2424
import java.util.Set;
25+
import java.util.function.Function;
2526

2627
import javax.lang.model.element.Element;
2728
import javax.lang.model.element.ExecutableElement;
@@ -48,7 +49,7 @@ class TypeElementMembers {
4849

4950
private final Map<String, VariableElement> fields = new LinkedHashMap<>();
5051

51-
private final Map<String, ExecutableElement> publicGetters = new LinkedHashMap<>();
52+
private final Map<String, List<ExecutableElement>> publicGetters = new LinkedHashMap<>();
5253

5354
private final Map<String, List<ExecutableElement>> publicSetters = new LinkedHashMap<>();
5455

@@ -74,8 +75,14 @@ private void process(TypeElement element) {
7475
private void processMethod(ExecutableElement method) {
7576
if (isPublic(method)) {
7677
String name = method.getSimpleName().toString();
77-
if (isGetter(method) && !this.publicGetters.containsKey(getAccessorName(name))) {
78-
this.publicGetters.put(getAccessorName(name), method);
78+
if (isGetter(method)) {
79+
String propertyName = getAccessorName(name);
80+
List<ExecutableElement> matchingGetters = this.publicGetters.computeIfAbsent(propertyName,
81+
(k) -> new ArrayList<>());
82+
TypeMirror returnType = method.getReturnType();
83+
if (getMatchingGetter(matchingGetters, returnType) == null) {
84+
matchingGetters.add(method);
85+
}
7986
}
8087
else if (isSetter(method)) {
8188
String propertyName = getAccessorName(name);
@@ -95,10 +102,19 @@ private boolean isPublic(ExecutableElement method) {
95102
&& !modifiers.contains(Modifier.STATIC);
96103
}
97104

105+
ExecutableElement getMatchingGetter(List<ExecutableElement> candidates, TypeMirror type) {
106+
return getMatchingAccessor(candidates, type, ExecutableElement::getReturnType);
107+
}
108+
98109
private ExecutableElement getMatchingSetter(List<ExecutableElement> candidates, TypeMirror type) {
110+
return getMatchingAccessor(candidates, type, (candidate) -> candidate.getParameters().get(0).asType());
111+
}
112+
113+
private ExecutableElement getMatchingAccessor(List<ExecutableElement> candidates, TypeMirror type,
114+
Function<ExecutableElement, TypeMirror> typeExtractor) {
99115
for (ExecutableElement candidate : candidates) {
100-
TypeMirror paramType = candidate.getParameters().get(0).asType();
101-
if (this.env.getTypeUtils().isSameType(paramType, type)) {
116+
TypeMirror candidateType = typeExtractor.apply(candidate);
117+
if (this.env.getTypeUtils().isSameType(candidateType, type)) {
102118
return candidate;
103119
}
104120
}
@@ -151,35 +167,30 @@ Map<String, VariableElement> getFields() {
151167
return Collections.unmodifiableMap(this.fields);
152168
}
153169

154-
Map<String, ExecutableElement> getPublicGetters() {
170+
Map<String, List<ExecutableElement>> getPublicGetters() {
155171
return Collections.unmodifiableMap(this.publicGetters);
156172
}
157173

158174
ExecutableElement getPublicGetter(String name, TypeMirror type) {
159-
ExecutableElement candidate = this.publicGetters.get(name);
160-
if (candidate != null) {
161-
TypeMirror returnType = candidate.getReturnType();
162-
if (this.env.getTypeUtils().isSameType(returnType, type)) {
163-
return candidate;
164-
}
165-
TypeMirror alternative = this.env.getTypeUtils().getWrapperOrPrimitiveFor(type);
166-
if (alternative != null && this.env.getTypeUtils().isSameType(returnType, alternative)) {
167-
return candidate;
168-
}
169-
}
170-
return null;
175+
List<ExecutableElement> candidates = this.publicGetters.get(name);
176+
return getPublicAccessor(candidates, type, (specificType) -> getMatchingGetter(candidates, specificType));
171177
}
172178

173179
ExecutableElement getPublicSetter(String name, TypeMirror type) {
174180
List<ExecutableElement> candidates = this.publicSetters.get(name);
181+
return getPublicAccessor(candidates, type, (specificType) -> getMatchingSetter(candidates, specificType));
182+
}
183+
184+
private ExecutableElement getPublicAccessor(List<ExecutableElement> candidates, TypeMirror type,
185+
Function<TypeMirror, ExecutableElement> matchingAccessorExtractor) {
175186
if (candidates != null) {
176-
ExecutableElement matching = getMatchingSetter(candidates, type);
187+
ExecutableElement matching = matchingAccessorExtractor.apply(type);
177188
if (matching != null) {
178189
return matching;
179190
}
180191
TypeMirror alternative = this.env.getTypeUtils().getWrapperOrPrimitiveFor(type);
181192
if (alternative != null) {
182-
return getMatchingSetter(candidates, alternative);
193+
return matchingAccessorExtractor.apply(alternative);
183194
}
184195
}
185196
return null;

spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.springframework.boot.configurationsample.specific.AnnotatedGetter;
3939
import org.springframework.boot.configurationsample.specific.BoxingPojo;
4040
import org.springframework.boot.configurationsample.specific.BuilderPojo;
41+
import org.springframework.boot.configurationsample.specific.DeprecatedLessPreciseTypePojo;
4142
import org.springframework.boot.configurationsample.specific.DeprecatedUnrelatedMethodPojo;
4243
import org.springframework.boot.configurationsample.specific.DoubleRegistrationProperties;
4344
import org.springframework.boot.configurationsample.specific.EmptyDefaultValueProperties;
@@ -192,12 +193,22 @@ void deprecatedOnUnrelatedSetter() {
192193
}
193194

194195
@Test
195-
void boxingOnSetter() {
196+
void deprecatedWithLessPreciseType() {
197+
Class<?> type = DeprecatedLessPreciseTypePojo.class;
198+
ConfigurationMetadata metadata = compile(type);
199+
assertThat(metadata).has(Metadata.withGroup("not.deprecated").fromSource(type));
200+
assertThat(metadata).has(Metadata.withProperty("not.deprecated.flag", Boolean.class).withDefaultValue(false)
201+
.withNoDeprecation().fromSource(type));
202+
}
203+
204+
@Test
205+
void typBoxing() {
196206
Class<?> type = BoxingPojo.class;
197207
ConfigurationMetadata metadata = compile(type);
198208
assertThat(metadata).has(Metadata.withGroup("boxing").fromSource(type));
199209
assertThat(metadata)
200210
.has(Metadata.withProperty("boxing.flag", Boolean.class).withDefaultValue(false).fromSource(type));
211+
assertThat(metadata).has(Metadata.withProperty("boxing.another-flag", Boolean.class).fromSource(type));
201212
assertThat(metadata).has(Metadata.withProperty("boxing.counter", Integer.class).fromSource(type));
202213
}
203214

spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/specific/BoxingPojo.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,6 +29,8 @@ public class BoxingPojo {
2929

3030
private boolean flag;
3131

32+
private Boolean anotherFlag;
33+
3234
private Integer counter;
3335

3436
public boolean isFlag() {
@@ -40,6 +42,14 @@ public void setFlag(Boolean flag) {
4042
this.flag = flag;
4143
}
4244

45+
public boolean isAnotherFlag() {
46+
return Boolean.TRUE.equals(this.anotherFlag);
47+
}
48+
49+
public void setAnotherFlag(boolean anotherFlag) {
50+
this.anotherFlag = anotherFlag;
51+
}
52+
4353
public Integer getCounter() {
4454
return this.counter;
4555
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.configurationsample.specific;
18+
19+
import org.springframework.boot.configurationsample.ConfigurationProperties;
20+
21+
/**
22+
* Demonstrate that deprecating accessor with not the same type is not taken into account
23+
* to detect the deprecated flag.
24+
*
25+
* @author Stephane Nicoll
26+
*/
27+
@ConfigurationProperties("not.deprecated")
28+
public class DeprecatedLessPreciseTypePojo {
29+
30+
private boolean flag;
31+
32+
@Deprecated
33+
public Boolean getFlag() {
34+
return this.flag;
35+
}
36+
37+
public boolean isFlag() {
38+
return this.flag;
39+
}
40+
41+
public void setFlag(boolean flag) {
42+
this.flag = flag;
43+
}
44+
45+
@Deprecated
46+
public void setFlag(Boolean flag) {
47+
this.flag = flag;
48+
}
49+
50+
}

0 commit comments

Comments
 (0)