Skip to content

Commit 3699132

Browse files
kesslerjsnicoll
authored andcommitted
Respect lombok.AccessLevel attributes
See gh-13175
1 parent 0c55c54 commit 3699132

File tree

6 files changed

+584
-7
lines changed

6 files changed

+584
-7
lines changed

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

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
* @author Stephane Nicoll
5757
* @author Phillip Webb
5858
* @author Kris De Volder
59+
* @author Jonas Keßler
5960
* @since 1.2.0
6061
*/
6162
@SupportedAnnotationTypes({ "*" })
@@ -76,6 +77,11 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor
7677

7778
static final String LOMBOK_SETTER_ANNOTATION = "lombok.Setter";
7879

80+
private static final String LOMBOK_ACCESS_LEVEL = "lombok.AccessLevel";
81+
82+
private static final String LOMBOK_ACCESS_LEVEL_PUBLIC = LOMBOK_ACCESS_LEVEL
83+
+ ".PUBLIC";
84+
7985
private MetadataStore metadataStore;
8086

8187
private MetadataCollector metadataCollector;
@@ -302,16 +308,35 @@ private void processNestedLombokTypes(String prefix, TypeElement element,
302308
}
303309

304310
private boolean isLombokField(VariableElement field, TypeElement element) {
305-
return hasAnnotation(field, LOMBOK_GETTER_ANNOTATION)
306-
|| hasAnnotation(element, LOMBOK_GETTER_ANNOTATION)
307-
|| hasAnnotation(element, LOMBOK_DATA_ANNOTATION);
311+
return hasLombokPublicMethod(field, element, LOMBOK_GETTER_ANNOTATION);
308312
}
309313

310314
private boolean hasLombokSetter(VariableElement field, TypeElement element) {
311315
return !field.getModifiers().contains(Modifier.FINAL)
312-
&& (hasAnnotation(field, LOMBOK_SETTER_ANNOTATION)
313-
|| hasAnnotation(element, LOMBOK_SETTER_ANNOTATION)
314-
|| hasAnnotation(element, LOMBOK_DATA_ANNOTATION));
316+
&& hasLombokPublicMethod(field, element, LOMBOK_SETTER_ANNOTATION);
317+
}
318+
319+
private boolean hasLombokPublicMethod(VariableElement field, TypeElement element,
320+
String lombokMethodAnnotation) {
321+
AnnotationMirror lombokMethodAnnotationOnField = getAnnotation(field,
322+
lombokMethodAnnotation);
323+
if (lombokMethodAnnotationOnField != null) {
324+
return isLombokPublic(lombokMethodAnnotationOnField);
325+
}
326+
327+
AnnotationMirror lombokMethodAnnotationOnElement = getAnnotation(element,
328+
lombokMethodAnnotation);
329+
if (lombokMethodAnnotationOnElement != null) {
330+
return isLombokPublic(lombokMethodAnnotationOnElement);
331+
}
332+
333+
return hasAnnotation(element, LOMBOK_DATA_ANNOTATION);
334+
}
335+
336+
private boolean isLombokPublic(AnnotationMirror lombokAnnotation) {
337+
return lombokAnnotation.getElementValues().values().stream()
338+
.noneMatch(e -> e.toString().startsWith(LOMBOK_ACCESS_LEVEL)
339+
&& !e.toString().equals(LOMBOK_ACCESS_LEVEL_PUBLIC));
315340
}
316341

317342
private void processNestedType(String prefix, TypeElement element,

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

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
import org.springframework.boot.configurationsample.incremental.BarProperties;
3939
import org.springframework.boot.configurationsample.incremental.FooProperties;
4040
import org.springframework.boot.configurationsample.incremental.RenamedBarProperties;
41+
import org.springframework.boot.configurationsample.lombok.LombokAccessLevelOverwriteDataProperties;
42+
import org.springframework.boot.configurationsample.lombok.LombokAccessLevelOverwriteDefaultProperties;
43+
import org.springframework.boot.configurationsample.lombok.LombokAccessLevelOverwriteExplicitProperties;
44+
import org.springframework.boot.configurationsample.lombok.LombokAccessLevelProperties;
4145
import org.springframework.boot.configurationsample.lombok.LombokExplicitProperties;
4246
import org.springframework.boot.configurationsample.lombok.LombokInnerClassProperties;
4347
import org.springframework.boot.configurationsample.lombok.LombokInnerClassWithGetterProperties;
@@ -83,6 +87,7 @@
8387
* @author Phillip Webb
8488
* @author Andy Wilkinson
8589
* @author Kris De Volder
90+
* @author Jonas Keßler
8691
*/
8792
public class ConfigurationMetadataAnnotationProcessorTests {
8893

@@ -483,6 +488,40 @@ public void lombokSimpleProperties() throws Exception {
483488
assertSimpleLombokProperties(metadata, LombokSimpleProperties.class, "simple");
484489
}
485490

491+
@Test
492+
public void lombokAccessLevelOverwriteDataProperties() {
493+
ConfigurationMetadata metadata = compile(
494+
LombokAccessLevelOverwriteDataProperties.class);
495+
assertAccessLevelOverwriteLombokProperties(metadata,
496+
LombokAccessLevelOverwriteDataProperties.class,
497+
"accesslevel.overwrite.data");
498+
}
499+
500+
@Test
501+
public void lombokAccessLevelOverwriteExplicitProperties() {
502+
ConfigurationMetadata metadata = compile(
503+
LombokAccessLevelOverwriteExplicitProperties.class);
504+
assertAccessLevelOverwriteLombokProperties(metadata,
505+
LombokAccessLevelOverwriteExplicitProperties.class,
506+
"accesslevel.overwrite.explicit");
507+
}
508+
509+
@Test
510+
public void lombokAccessLevelOverwriteDefaultProperties() {
511+
ConfigurationMetadata metadata = compile(
512+
LombokAccessLevelOverwriteDefaultProperties.class);
513+
assertAccessLevelOverwriteLombokProperties(metadata,
514+
LombokAccessLevelOverwriteDefaultProperties.class,
515+
"accesslevel.overwrite.default");
516+
}
517+
518+
@Test
519+
public void lombokAccessLevelProperties() {
520+
ConfigurationMetadata metadata = compile(LombokAccessLevelProperties.class);
521+
assertAccessLevelLombokProperties(metadata, LombokAccessLevelProperties.class,
522+
"accesslevel", 2, 20);
523+
}
524+
486525
@Test
487526
public void lombokExplicitProperties() throws Exception {
488527
ConfigurationMetadata metadata = compile(LombokExplicitProperties.class);
@@ -789,7 +828,26 @@ private void assertSimpleLombokProperties(ConfigurationMetadata metadata,
789828
assertThat(metadata).doesNotHave(Metadata.withProperty(prefix + ".ignored"));
790829
}
791830

792-
private ConfigurationMetadata compile(Class<?>... types) throws IOException {
831+
private void assertAccessLevelOverwriteLombokProperties(
832+
ConfigurationMetadata metadata, Class<?> source, String prefix) {
833+
assertAccessLevelLombokProperties(metadata, source, prefix, 7, 15);
834+
}
835+
836+
private void assertAccessLevelLombokProperties(ConfigurationMetadata metadata,
837+
Class<?> source, String prefix, int countNameFields, int countIgnoredFields) {
838+
assertThat(metadata).has(Metadata.withGroup(prefix).fromSource(source));
839+
for (int i = 0; i < countNameFields; i++) {
840+
assertThat(metadata)
841+
.has(Metadata.withProperty(prefix + ".name" + i, String.class));
842+
}
843+
844+
for (int i = 0; i < countIgnoredFields; i++) {
845+
assertThat(metadata)
846+
.doesNotHave(Metadata.withProperty(prefix + ".ignored" + i));
847+
}
848+
}
849+
850+
private ConfigurationMetadata compile(Class<?>... types) {
793851
TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor(
794852
this.compiler.getOutputLocation());
795853
this.compiler.getTask(types).call(processor);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2012-2017 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+
* http://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.lombok;
18+
19+
import lombok.AccessLevel;
20+
import lombok.Data;
21+
import lombok.Getter;
22+
import lombok.Setter;
23+
24+
import org.springframework.boot.configurationsample.ConfigurationProperties;
25+
26+
/**
27+
* Configuration properties using lombok @Data on element level and overwriting behaviour
28+
* with @Getter und @Setter at field level.
29+
*
30+
* @author Jonas Keßler
31+
*/
32+
@Data
33+
@ConfigurationProperties(prefix = "accesslevel.overwrite.data")
34+
public class LombokAccessLevelOverwriteDataProperties {
35+
36+
private String name0;
37+
38+
@Getter(AccessLevel.PUBLIC)
39+
@Setter(AccessLevel.PUBLIC)
40+
private String name1;
41+
42+
@Getter(AccessLevel.PUBLIC)
43+
private String name2;
44+
45+
@Setter(AccessLevel.PUBLIC)
46+
private String name3;
47+
48+
@Getter
49+
@Setter
50+
private String name4;
51+
52+
@Getter
53+
private String name5;
54+
55+
@Setter
56+
private String name6;
57+
58+
/*
59+
* AccessLevel.NONE
60+
*/
61+
@Getter(AccessLevel.NONE)
62+
@Setter(AccessLevel.NONE)
63+
private String ignored0;
64+
65+
@Getter(AccessLevel.NONE)
66+
private String ignored1;
67+
68+
@Setter(AccessLevel.NONE)
69+
private String ignored2;
70+
71+
/*
72+
* AccessLevel.PRIVATE
73+
*/
74+
@Getter(AccessLevel.PRIVATE)
75+
@Setter(AccessLevel.PRIVATE)
76+
private String ignored3;
77+
78+
@Getter(AccessLevel.PRIVATE)
79+
private String ignored4;
80+
81+
@Setter(AccessLevel.PRIVATE)
82+
private String ignored5;
83+
84+
/*
85+
* AccessLevel.PACKAGE
86+
*/
87+
@Getter(AccessLevel.PACKAGE)
88+
@Setter(AccessLevel.PACKAGE)
89+
private String ignored6;
90+
91+
@Getter(AccessLevel.PACKAGE)
92+
private String ignored7;
93+
94+
@Setter(AccessLevel.PACKAGE)
95+
private String ignored8;
96+
97+
/*
98+
* AccessLevel.PROTECTED
99+
*/
100+
@Getter(AccessLevel.PROTECTED)
101+
@Setter(AccessLevel.PROTECTED)
102+
private String ignored9;
103+
104+
@Getter(AccessLevel.PROTECTED)
105+
private String ignored10;
106+
107+
@Setter(AccessLevel.PROTECTED)
108+
private String ignored11;
109+
110+
/*
111+
* AccessLevel.MODULE
112+
*/
113+
@Getter(AccessLevel.MODULE)
114+
@Setter(AccessLevel.MODULE)
115+
private String ignored12;
116+
117+
@Getter(AccessLevel.MODULE)
118+
private String ignored13;
119+
120+
@Setter(AccessLevel.MODULE)
121+
private String ignored14;
122+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2012-2017 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+
* http://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.lombok;
18+
19+
import lombok.AccessLevel;
20+
import lombok.Getter;
21+
import lombok.Setter;
22+
23+
import org.springframework.boot.configurationsample.ConfigurationProperties;
24+
25+
/**
26+
* Configuration properties using lombok @Getter and @Setter without explicitly defining
27+
* AccessLevel on element level and overwriting behaviour at field level.
28+
*
29+
* @author Jonas Keßler
30+
*/
31+
@Getter
32+
@Setter
33+
@ConfigurationProperties(prefix = "accesslevel.overwrite.default")
34+
public class LombokAccessLevelOverwriteDefaultProperties {
35+
36+
private String name0;
37+
38+
@Getter(AccessLevel.PUBLIC)
39+
@Setter(AccessLevel.PUBLIC)
40+
private String name1;
41+
42+
@Getter(AccessLevel.PUBLIC)
43+
private String name2;
44+
45+
@Setter(AccessLevel.PUBLIC)
46+
private String name3;
47+
48+
@Getter
49+
@Setter
50+
private String name4;
51+
52+
@Getter
53+
private String name5;
54+
55+
@Setter
56+
private String name6;
57+
58+
/*
59+
* AccessLevel.NONE
60+
*/
61+
@Getter(AccessLevel.NONE)
62+
@Setter(AccessLevel.NONE)
63+
private String ignored0;
64+
65+
@Getter(AccessLevel.NONE)
66+
private String ignored1;
67+
68+
@Setter(AccessLevel.NONE)
69+
private String ignored2;
70+
71+
/*
72+
* AccessLevel.PRIVATE
73+
*/
74+
@Getter(AccessLevel.PRIVATE)
75+
@Setter(AccessLevel.PRIVATE)
76+
private String ignored3;
77+
78+
@Getter(AccessLevel.PRIVATE)
79+
private String ignored4;
80+
81+
@Setter(AccessLevel.PRIVATE)
82+
private String ignored5;
83+
84+
/*
85+
* AccessLevel.PACKAGE
86+
*/
87+
@Getter(AccessLevel.PACKAGE)
88+
@Setter(AccessLevel.PACKAGE)
89+
private String ignored6;
90+
91+
@Getter(AccessLevel.PACKAGE)
92+
private String ignored7;
93+
94+
@Setter(AccessLevel.PACKAGE)
95+
private String ignored8;
96+
97+
/*
98+
* AccessLevel.PROTECTED
99+
*/
100+
@Getter(AccessLevel.PROTECTED)
101+
@Setter(AccessLevel.PROTECTED)
102+
private String ignored9;
103+
104+
@Getter(AccessLevel.PROTECTED)
105+
private String ignored10;
106+
107+
@Setter(AccessLevel.PROTECTED)
108+
private String ignored11;
109+
110+
/*
111+
* AccessLevel.MODULE
112+
*/
113+
@Getter(AccessLevel.MODULE)
114+
@Setter(AccessLevel.MODULE)
115+
private String ignored12;
116+
117+
@Getter(AccessLevel.MODULE)
118+
private String ignored13;
119+
120+
@Setter(AccessLevel.MODULE)
121+
private String ignored14;
122+
}

0 commit comments

Comments
 (0)