Skip to content

Commit 22a195b

Browse files
committed
[fixes #2891] Skip excluded fields in builder-generated toString
1 parent 87e8af4 commit 22a195b

13 files changed

+430
-1
lines changed

src/core/lombok/eclipse/handlers/HandleBuilder.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,8 +565,15 @@ private static final char[] prefixWith(char[] prefix, char[] name) {
565565
}
566566

567567
if (methodExists("toString", job.builderType, 0) == MemberExistsResult.NOT_EXISTS) {
568+
List<String> oldExcludes = findOldToStringExcludes(job.parentType);
568569
List<Included<EclipseNode, ToString.Include>> fieldNodes = new ArrayList<Included<EclipseNode, ToString.Include>>();
569570
for (BuilderFieldData bfd : job.builderFields) {
571+
if (bfd.originalFieldNode.hasAnnotation(ToString.Exclude.class)) {
572+
continue;
573+
}
574+
if (oldExcludes.contains(bfd.originalFieldNode.getName())) {
575+
continue;
576+
}
570577
for (EclipseNode f : bfd.createdFields) {
571578
fieldNodes.add(new Included<EclipseNode, ToString.Include>(f, null, true, false));
572579
}
@@ -1137,4 +1144,12 @@ private SingularData getSingularData(EclipseNode node, ASTNode source, final Str
11371144

11381145
return null;
11391146
}
1147+
1148+
private List<String> findOldToStringExcludes(EclipseNode parentType) {
1149+
EclipseNode toStringAnnotationNode = findAnnotation(ToString.class, parentType);
1150+
if (toStringAnnotationNode == null) return Collections.emptyList();
1151+
1152+
AnnotationValues<ToString> toStringAnnotation = createAnnotation(ToString.class, toStringAnnotationNode);
1153+
return toStringAnnotation.getAsStringList("exclude");
1154+
}
11401155
}

src/core/lombok/javac/handlers/HandleBuilder.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import static lombok.javac.handlers.JavacHandlerUtil.*;
2828

2929
import java.util.ArrayList;
30+
import java.util.Collections;
3031

3132
import javax.lang.model.element.Modifier;
3233

@@ -505,8 +506,15 @@ static class BuilderFieldData {
505506
}
506507

507508
if (methodExists("toString", job.builderType, 0) == MemberExistsResult.NOT_EXISTS) {
509+
java.util.List<String> oldExcludes = findOldToStringExcludes(job.parentType);
508510
java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>();
509511
for (BuilderFieldData bfd : job.builderFields) {
512+
if (hasAnnotation(ToString.Exclude.class, bfd.originalFieldNode)) {
513+
continue;
514+
}
515+
if (oldExcludes.contains(bfd.originalFieldNode.getName())) {
516+
continue;
517+
}
510518
for (JavacNode f : bfd.createdFields) {
511519
fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true, false));
512520
}
@@ -1020,4 +1028,12 @@ private SingularData getSingularData(JavacNode node, String setterPrefix) {
10201028

10211029
return null;
10221030
}
1031+
1032+
private java.util.List<String> findOldToStringExcludes(JavacNode parentType) {
1033+
JavacNode toStringAnnotationNode = findAnnotation(ToString.class, parentType);
1034+
if (toStringAnnotationNode == null) return Collections.emptyList();
1035+
1036+
AnnotationValues<ToString> toStringAnnotation = createAnnotation(ToString.class, toStringAnnotationNode);
1037+
return toStringAnnotation.getAsStringList("exclude");
1038+
}
10231039
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (C) 2025 The Project Lombok Authors.
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
* THE SOFTWARE.
21+
*/
22+
package lombok.javac.handlers;
23+
24+
import static lombok.javac.handlers.JavacHandlerUtil.*;
25+
26+
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
27+
28+
import lombok.ToString;
29+
import lombok.ToString.Exclude;
30+
import lombok.core.AlreadyHandledAnnotations;
31+
import lombok.core.AnnotationValues;
32+
import lombok.core.HandlerPriority;
33+
import lombok.javac.JavacAnnotationHandler;
34+
import lombok.javac.JavacNode;
35+
import lombok.spi.Provides;
36+
37+
@Provides
38+
@HandlerPriority(32768)
39+
@AlreadyHandledAnnotations
40+
public class HandleToStringExcludeRemove extends JavacAnnotationHandler<ToString.Exclude> {
41+
@Override public void handle(AnnotationValues<Exclude> annotation, JCAnnotation ast, JavacNode annotationNode) {
42+
deleteAnnotationIfNeccessary(annotationNode, ToString.Exclude.class);
43+
deleteImportFromCompilationUnit(annotationNode, ToString.class);
44+
deleteImportFromCompilationUnit(annotationNode, ToString.Exclude.class);
45+
}
46+
}

src/core/lombok/javac/handlers/JavacHandlerUtil.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,17 +556,22 @@ private static void deleteAnnotationIfNeccessary0(JavacNode annotation, String..
556556
}
557557
}
558558

559+
public static void deleteImportFromCompilationUnit(JavacNode node, Class<?> annotationType) {
560+
deleteImportFromCompilationUnit(node, annotationType.getName());
561+
}
562+
559563
public static void deleteImportFromCompilationUnit(JavacNode node, String name) {
560564
if (inNetbeansEditor(node)) return;
561565
if (!node.shouldDeleteLombokAnnotations()) return;
562566

563567
JCCompilationUnit unit = (JCCompilationUnit) node.top().get();
564568

569+
String importName = name.replace('$', '.');
565570
for (JCTree def : unit.defs) {
566571
if (!(def instanceof JCImport)) continue;
567572
JCImport imp0rt = (JCImport) def;
568573
if (imp0rt.staticImport) continue;
569-
if (!Javac.getQualid(imp0rt).toString().equals(name)) continue;
574+
if (!Javac.getQualid(imp0rt).toString().equals(importName)) continue;
570575
JavacAugments.JCImport_deletable.set(imp0rt, true);
571576
}
572577
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
public class BuilderWithToStringExclude {
2+
private String a;
3+
private String secret;
4+
@java.lang.SuppressWarnings("all")
5+
@lombok.Generated
6+
BuilderWithToStringExclude(final String a, final String secret) {
7+
this.a = a;
8+
this.secret = secret;
9+
}
10+
@java.lang.SuppressWarnings("all")
11+
@lombok.Generated
12+
public static class BuilderWithToStringExcludeBuilder {
13+
@java.lang.SuppressWarnings("all")
14+
@lombok.Generated
15+
private String a;
16+
@java.lang.SuppressWarnings("all")
17+
@lombok.Generated
18+
private String secret;
19+
@java.lang.SuppressWarnings("all")
20+
@lombok.Generated
21+
BuilderWithToStringExcludeBuilder() {
22+
}
23+
/**
24+
* @return {@code this}.
25+
*/
26+
@java.lang.SuppressWarnings("all")
27+
@lombok.Generated
28+
public BuilderWithToStringExclude.BuilderWithToStringExcludeBuilder a(final String a) {
29+
this.a = a;
30+
return this;
31+
}
32+
/**
33+
* @return {@code this}.
34+
*/
35+
@java.lang.SuppressWarnings("all")
36+
@lombok.Generated
37+
public BuilderWithToStringExclude.BuilderWithToStringExcludeBuilder secret(final String secret) {
38+
this.secret = secret;
39+
return this;
40+
}
41+
@java.lang.SuppressWarnings("all")
42+
@lombok.Generated
43+
public BuilderWithToStringExclude build() {
44+
return new BuilderWithToStringExclude(this.a, this.secret);
45+
}
46+
@java.lang.Override
47+
@java.lang.SuppressWarnings("all")
48+
@lombok.Generated
49+
public java.lang.String toString() {
50+
return "BuilderWithToStringExclude.BuilderWithToStringExcludeBuilder(a=" + this.a + ")";
51+
}
52+
}
53+
@java.lang.SuppressWarnings("all")
54+
@lombok.Generated
55+
public static BuilderWithToStringExclude.BuilderWithToStringExcludeBuilder builder() {
56+
return new BuilderWithToStringExclude.BuilderWithToStringExcludeBuilder();
57+
}
58+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
public class BuilderWithToStringExcludeAndToString {
2+
private String a;
3+
private String secret;
4+
@java.lang.SuppressWarnings("all")
5+
@lombok.Generated
6+
BuilderWithToStringExcludeAndToString(final String a, final String secret) {
7+
this.a = a;
8+
this.secret = secret;
9+
}
10+
@java.lang.SuppressWarnings("all")
11+
@lombok.Generated
12+
public static class BuilderWithToStringExcludeAndToStringBuilder {
13+
@java.lang.SuppressWarnings("all")
14+
@lombok.Generated
15+
private String a;
16+
@java.lang.SuppressWarnings("all")
17+
@lombok.Generated
18+
private String secret;
19+
@java.lang.SuppressWarnings("all")
20+
@lombok.Generated
21+
BuilderWithToStringExcludeAndToStringBuilder() {
22+
}
23+
/**
24+
* @return {@code this}.
25+
*/
26+
@java.lang.SuppressWarnings("all")
27+
@lombok.Generated
28+
public BuilderWithToStringExcludeAndToString.BuilderWithToStringExcludeAndToStringBuilder a(final String a) {
29+
this.a = a;
30+
return this;
31+
}
32+
/**
33+
* @return {@code this}.
34+
*/
35+
@java.lang.SuppressWarnings("all")
36+
@lombok.Generated
37+
public BuilderWithToStringExcludeAndToString.BuilderWithToStringExcludeAndToStringBuilder secret(final String secret) {
38+
this.secret = secret;
39+
return this;
40+
}
41+
@java.lang.SuppressWarnings("all")
42+
@lombok.Generated
43+
public BuilderWithToStringExcludeAndToString build() {
44+
return new BuilderWithToStringExcludeAndToString(this.a, this.secret);
45+
}
46+
@java.lang.Override
47+
@java.lang.SuppressWarnings("all")
48+
@lombok.Generated
49+
public java.lang.String toString() {
50+
return "BuilderWithToStringExcludeAndToString.BuilderWithToStringExcludeAndToStringBuilder(a=" + this.a + ")";
51+
}
52+
}
53+
@java.lang.SuppressWarnings("all")
54+
@lombok.Generated
55+
public static BuilderWithToStringExcludeAndToString.BuilderWithToStringExcludeAndToStringBuilder builder() {
56+
return new BuilderWithToStringExcludeAndToString.BuilderWithToStringExcludeAndToStringBuilder();
57+
}
58+
@java.lang.Override
59+
@java.lang.SuppressWarnings("all")
60+
@lombok.Generated
61+
public java.lang.String toString() {
62+
return "BuilderWithToStringExcludeAndToString(a=" + this.a + ")";
63+
}
64+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
public class BuilderWithToStringExcludeOld {
2+
private String a;
3+
private String secret;
4+
@java.lang.SuppressWarnings("all")
5+
@lombok.Generated
6+
BuilderWithToStringExcludeOld(final String a, final String secret) {
7+
this.a = a;
8+
this.secret = secret;
9+
}
10+
@java.lang.SuppressWarnings("all")
11+
@lombok.Generated
12+
public static class BuilderWithToStringExcludeOldBuilder {
13+
@java.lang.SuppressWarnings("all")
14+
@lombok.Generated
15+
private String a;
16+
@java.lang.SuppressWarnings("all")
17+
@lombok.Generated
18+
private String secret;
19+
@java.lang.SuppressWarnings("all")
20+
@lombok.Generated
21+
BuilderWithToStringExcludeOldBuilder() {
22+
}
23+
/**
24+
* @return {@code this}.
25+
*/
26+
@java.lang.SuppressWarnings("all")
27+
@lombok.Generated
28+
public BuilderWithToStringExcludeOld.BuilderWithToStringExcludeOldBuilder a(final String a) {
29+
this.a = a;
30+
return this;
31+
}
32+
/**
33+
* @return {@code this}.
34+
*/
35+
@java.lang.SuppressWarnings("all")
36+
@lombok.Generated
37+
public BuilderWithToStringExcludeOld.BuilderWithToStringExcludeOldBuilder secret(final String secret) {
38+
this.secret = secret;
39+
return this;
40+
}
41+
@java.lang.SuppressWarnings("all")
42+
@lombok.Generated
43+
public BuilderWithToStringExcludeOld build() {
44+
return new BuilderWithToStringExcludeOld(this.a, this.secret);
45+
}
46+
@java.lang.Override
47+
@java.lang.SuppressWarnings("all")
48+
@lombok.Generated
49+
public java.lang.String toString() {
50+
return "BuilderWithToStringExcludeOld.BuilderWithToStringExcludeOldBuilder(a=" + this.a + ")";
51+
}
52+
}
53+
@java.lang.SuppressWarnings("all")
54+
@lombok.Generated
55+
public static BuilderWithToStringExcludeOld.BuilderWithToStringExcludeOldBuilder builder() {
56+
return new BuilderWithToStringExcludeOld.BuilderWithToStringExcludeOldBuilder();
57+
}
58+
@java.lang.Override
59+
@java.lang.SuppressWarnings("all")
60+
@lombok.Generated
61+
public java.lang.String toString() {
62+
return "BuilderWithToStringExcludeOld(a=" + this.a + ")";
63+
}
64+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import lombok.Builder;
2+
import lombok.ToString;
3+
import lombok.ToString.Exclude;
4+
public @Builder class BuilderWithToStringExclude {
5+
public static @java.lang.SuppressWarnings("all") @lombok.Generated class BuilderWithToStringExcludeBuilder {
6+
private @java.lang.SuppressWarnings("all") @lombok.Generated String a;
7+
private @java.lang.SuppressWarnings("all") @lombok.Generated String secret;
8+
@java.lang.SuppressWarnings("all") @lombok.Generated BuilderWithToStringExcludeBuilder() {
9+
super();
10+
}
11+
/**
12+
* @return {@code this}.
13+
*/
14+
public @java.lang.SuppressWarnings("all") @lombok.Generated BuilderWithToStringExclude.BuilderWithToStringExcludeBuilder a(final String a) {
15+
this.a = a;
16+
return this;
17+
}
18+
/**
19+
* @return {@code this}.
20+
*/
21+
public @java.lang.SuppressWarnings("all") @lombok.Generated BuilderWithToStringExclude.BuilderWithToStringExcludeBuilder secret(final String secret) {
22+
this.secret = secret;
23+
return this;
24+
}
25+
public @java.lang.SuppressWarnings("all") @lombok.Generated BuilderWithToStringExclude build() {
26+
return new BuilderWithToStringExclude(this.a, this.secret);
27+
}
28+
public @java.lang.Override @java.lang.SuppressWarnings("all") @lombok.Generated java.lang.String toString() {
29+
return (("BuilderWithToStringExclude.BuilderWithToStringExcludeBuilder(a=" + this.a) + ")");
30+
}
31+
}
32+
private String a;
33+
private @ToString.Exclude String secret;
34+
@java.lang.SuppressWarnings("all") @lombok.Generated BuilderWithToStringExclude(final String a, final String secret) {
35+
super();
36+
this.a = a;
37+
this.secret = secret;
38+
}
39+
public static @java.lang.SuppressWarnings("all") @lombok.Generated BuilderWithToStringExclude.BuilderWithToStringExcludeBuilder builder() {
40+
return new BuilderWithToStringExclude.BuilderWithToStringExcludeBuilder();
41+
}
42+
}

0 commit comments

Comments
 (0)