Merge branch 'builder-class-name-conflict'

This commit is contained in:
Reinier Zwitserloot committed 2026-08-21 03:13:56 +02:00
commit befe77d211
17 files changed
+242 -11

No files matched your search

+1
View File
@@ -59,6 +59,7 @@ Rostislav Krasny <45571812+rosti-il@users.noreply.github.com>
Samuel Pereira <samuel.p.araujo@gmail.com>
Sasha Koning <askoning@gmail.com>
Szymon Pacanowski <spacanowski@gmail.com>
Taeeun Kim <snowykte0426@naver.com>
Taiki Sugawara <buzz.taiki@gmail.com>
Takuya Murakami <tmurakam@tmurakam.org>
Thomas Darimont <thomas.darimont@gmail.com>
@@ -114,6 +114,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'};
static final AbstractMethodDeclaration[] EMPTY_METHODS = {};
static final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
static final String BUILDER_CLASS_NAME_ANNOTATION_CONFLICT = "builderClassName cannot be \"%s\" when using @%s; use @%s or choose another builder class name.";
private static final boolean toBoolean(Object expr, boolean defaultValue) {
if (expr == null) return defaultValue;
@@ -122,6 +123,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return ((Boolean) expr).booleanValue();
}
static boolean checkBuilderClassNameAnnotationConflict(String annotationName, String qualifiedAnnotationName, String builderClassName, Annotation ast, EclipseNode annotationNode) {
char[][] typeName = ast.type == null ? null : ast.type.getTypeName();
if (annotationName.equals(builderClassName) && (typeName == null || typeName.length == 1)) {
annotationNode.addError(String.format(BUILDER_CLASS_NAME_ANNOTATION_CONFLICT, builderClassName, annotationName, qualifiedAnnotationName));
return false;
}
return true;
}
static class BuilderJob {
CheckerFrameworkVersion checkerFramework;
EclipseNode parentType;
@@ -308,6 +318,9 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
job.parentType = parent;
TypeDeclaration td = (TypeDeclaration) parent.get();
job.setBuilderClassName(job.replaceBuilderClassName(td.name));
if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
if (!checkBuilderClassNameAnnotationConflict("Builder", "lombok.Builder", job.builderClassName, ast, annotationNode)) return;
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
@@ -365,8 +378,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
buildMethodReturnType = job.createBuilderParentTypeReference();
buildMethodThrownExceptions = null;
nameOfBuilderMethod = null;
job.setBuilderClassName(job.replaceBuilderClassName(td.name));
if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (parent.get() instanceof ConstructorDeclaration) {
job.checkReturnValue = true;
ConstructorDeclaration cd = (ConstructorDeclaration) parent.get();
@@ -478,6 +489,9 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return;
}
if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
if (!checkBuilderClassNameAnnotationConflict("Builder", "lombok.Builder", job.builderClassName, ast, annotationNode)) return;
if (fillParametersFrom != null) {
for (EclipseNode param : fillParametersFrom.down()) {
if (param.getKind() != Kind.ARGUMENT) continue;
@@ -187,6 +187,12 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
job.parentType = parent;
TypeDeclaration td = (TypeDeclaration) parent.get();
job.builderAbstractClassName = job.builderClassName = job.replaceBuilderClassName(td.name);
job.builderAbstractClassNameArr = job.builderClassNameArr = job.builderAbstractClassName.toCharArray();
job.builderImplClassName = job.builderAbstractClassName + "Impl";
job.builderImplClassNameArr = job.builderImplClassName.toCharArray();
if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
if (!checkBuilderClassNameAnnotationConflict("SuperBuilder", "lombok.SuperBuilder", job.builderClassName, ast, annotationNode)) return;
// Gather all fields of the class that should be set by the builder.
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
@@ -309,11 +315,6 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
superclassBuilderClass = new ParameterizedQualifiedTypeReference(tokens, typeArgsForTokens, 0, poss);
}
job.builderAbstractClassName = job.builderClassName = job.replaceBuilderClassName(td.name);
job.builderAbstractClassNameArr = job.builderClassNameArr = job.builderAbstractClassName.toCharArray();
job.builderImplClassName = job.builderAbstractClassName + "Impl";
job.builderImplClassNameArr = job.builderImplClassName.toCharArray();
// If there is no superclass, superclassBuilderClassExpression is still == null at this point.
// You can use it to check whether to inherit or not.
@@ -96,6 +96,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
static final String VALUE_PREFIX = "$value";
static final String BUILDER_TEMP_VAR = "builder";
static final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
static final String BUILDER_CLASS_NAME_ANNOTATION_CONFLICT = "builderClassName cannot be \"%s\" when using @%s; use @%s or choose another builder class name.";
private static final boolean toBoolean(Object expr, boolean defaultValue) {
if (expr == null) return defaultValue;
@@ -103,6 +104,14 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return ((Boolean) expr).booleanValue();
}
static boolean checkBuilderClassNameAnnotationConflict(String annotationName, String qualifiedAnnotationName, String builderClassName, JCAnnotation ast, JavacNode annotationNode) {
if (annotationName.equals(builderClassName) && !(ast.annotationType instanceof JCFieldAccess)) {
annotationNode.addError(String.format(BUILDER_CLASS_NAME_ANNOTATION_CONFLICT, builderClassName, annotationName, qualifiedAnnotationName));
return false;
}
return true;
}
static class BuilderJob {
CheckerFrameworkVersion checkerFramework;
JavacNode parentType;
@@ -251,6 +260,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
job.parentType = parent;
job.checkReturnValue = true;
JCClassDecl td = (JCClassDecl) parent.get();
job.builderClassName = job.replaceBuilderClassName(td.name);
if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
if (!checkBuilderClassNameAnnotationConflict("Builder", "lombok.Builder", job.builderClassName, ast, annotationNode)) return;
ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>();
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
@@ -308,8 +320,6 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
job.typeParams = job.builderTypeParams = td.typarams;
buildMethodThrownExceptions = List.nil();
nameOfBuilderMethod = null;
job.builderClassName = job.replaceBuilderClassName(td.name);
if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (fillParametersFrom != null && fillParametersFrom.getName().toString().equals("<init>")) {
JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get();
if (!jmd.typarams.isEmpty()) {
@@ -420,6 +430,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return;
}
if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
if (!checkBuilderClassNameAnnotationConflict("Builder", "lombok.Builder", job.builderClassName, ast, annotationNode)) return;
if (fillParametersFrom != null) {
for (JavacNode param : fillParametersFrom.down()) {
if (param.getKind() != Kind.ARGUMENT) continue;
@@ -169,6 +169,9 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
job.parentType = parent;
JCClassDecl td = (JCClassDecl) parent.get();
job.builderClassName = job.replaceBuilderClassName(td.name);
if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
if (!checkBuilderClassNameAnnotationConflict("SuperBuilder", "lombok.SuperBuilder", job.builderClassName, ast, annotationNode)) return;
// Gather all fields of the class that should be set by the builder.
ArrayList<JavacNode> nonFinalNonDefaultedFields = null;
@@ -217,8 +220,6 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
job.typeParams = job.builderTypeParams = td.typarams;
job.builderClassName = job.replaceBuilderClassName(td.name);
if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
// <C, B> are the generics for our builder.
String classGenericName = "C";
@@ -0,0 +1,44 @@
class BuilderClassNameCollisionQualified<T> {
private java.util.function.Function<T, String> mapper;
@java.lang.SuppressWarnings("all")
@lombok.Generated
BuilderClassNameCollisionQualified(final java.util.function.Function<T, String> mapper) {
this.mapper = mapper;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public static class Builder<T> {
@java.lang.SuppressWarnings("all")
@lombok.Generated
private java.util.function.Function<T, String> mapper;
@java.lang.SuppressWarnings("all")
@lombok.Generated
Builder() {
}
/**
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public BuilderClassNameCollisionQualified.Builder<T> mapper(final java.util.function.Function<T, String> mapper) {
this.mapper = mapper;
return this;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public BuilderClassNameCollisionQualified<T> build() {
return new BuilderClassNameCollisionQualified<T>(this.mapper);
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public java.lang.String toString() {
return "BuilderClassNameCollisionQualified.Builder(mapper=" + this.mapper + ")";
}
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public static <T> BuilderClassNameCollisionQualified.Builder<T> builder() {
return new BuilderClassNameCollisionQualified.Builder<T>();
}
}
@@ -0,0 +1,61 @@
class SuperBuilderClassNameCollisionQualified<T> {
T value;
@java.lang.SuppressWarnings("all")
@lombok.Generated
public static abstract class SuperBuilder<T, C extends SuperBuilderClassNameCollisionQualified<T>, B extends SuperBuilderClassNameCollisionQualified.SuperBuilder<T, C, B>> {
@java.lang.SuppressWarnings("all")
@lombok.Generated
private T value;
/**
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B value(final T value) {
this.value = value;
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
protected abstract B self();
@java.lang.SuppressWarnings("all")
@lombok.Generated
public abstract C build();
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public java.lang.String toString() {
return "SuperBuilderClassNameCollisionQualified.SuperBuilder(value=" + this.value + ")";
}
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static final class SuperBuilderImpl<T> extends SuperBuilderClassNameCollisionQualified.SuperBuilder<T, SuperBuilderClassNameCollisionQualified<T>, SuperBuilderClassNameCollisionQualified.SuperBuilderImpl<T>> {
@java.lang.SuppressWarnings("all")
@lombok.Generated
private SuperBuilderImpl() {
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
protected SuperBuilderClassNameCollisionQualified.SuperBuilderImpl<T> self() {
return this;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public SuperBuilderClassNameCollisionQualified<T> build() {
return new SuperBuilderClassNameCollisionQualified<T>(this);
}
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
protected SuperBuilderClassNameCollisionQualified(final SuperBuilderClassNameCollisionQualified.SuperBuilder<T, ?, ?> b) {
this.value = b.value;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public static <T> SuperBuilderClassNameCollisionQualified.SuperBuilder<T, ?, ?> builder() {
return new SuperBuilderClassNameCollisionQualified.SuperBuilderImpl<T>();
}
}
@@ -0,0 +1,29 @@
@lombok.Builder(builderClassName = "Builder") class BuilderClassNameCollisionQualified<T> {
public static @java.lang.SuppressWarnings("all") @lombok.Generated class Builder<T> {
private @java.lang.SuppressWarnings("all") @lombok.Generated java.util.function.Function<T, String> mapper;
@java.lang.SuppressWarnings("all") @lombok.Generated Builder() {
super();
}
/**
* @return {@code this}.
*/
public @java.lang.SuppressWarnings("all") @lombok.Generated BuilderClassNameCollisionQualified.Builder<T> mapper(final java.util.function.Function<T, String> mapper) {
this.mapper = mapper;
return this;
}
public @java.lang.SuppressWarnings("all") @lombok.Generated BuilderClassNameCollisionQualified<T> build() {
return new BuilderClassNameCollisionQualified<T>(this.mapper);
}
public @java.lang.Override @java.lang.SuppressWarnings("all") @lombok.Generated java.lang.String toString() {
return (("BuilderClassNameCollisionQualified.Builder(mapper=" + this.mapper) + ")");
}
}
private java.util.function.Function<T, String> mapper;
@java.lang.SuppressWarnings("all") @lombok.Generated BuilderClassNameCollisionQualified(final java.util.function.Function<T, String> mapper) {
super();
this.mapper = mapper;
}
public static @java.lang.SuppressWarnings("all") @lombok.Generated <T>BuilderClassNameCollisionQualified.Builder<T> builder() {
return new BuilderClassNameCollisionQualified.Builder<T>();
}
}
@@ -0,0 +1,39 @@
@lombok.SuperBuilder class SuperBuilderClassNameCollisionQualified<T> {
public static abstract @java.lang.SuppressWarnings("all") @lombok.Generated class SuperBuilder<T, C extends SuperBuilderClassNameCollisionQualified<T>, B extends SuperBuilderClassNameCollisionQualified.SuperBuilder<T, C, B>> {
private @java.lang.SuppressWarnings("all") @lombok.Generated T value;
public SuperBuilder() {
super();
}
/**
* @return {@code this}.
*/
public @java.lang.SuppressWarnings("all") @lombok.Generated B value(final T value) {
this.value = value;
return self();
}
protected abstract @java.lang.SuppressWarnings("all") @lombok.Generated B self();
public abstract @java.lang.SuppressWarnings("all") @lombok.Generated C build();
public @java.lang.Override @java.lang.SuppressWarnings("all") @lombok.Generated java.lang.String toString() {
return (("SuperBuilderClassNameCollisionQualified.SuperBuilder(value=" + this.value) + ")");
}
}
private static final @java.lang.SuppressWarnings("all") @lombok.Generated class SuperBuilderImpl<T> extends SuperBuilderClassNameCollisionQualified.SuperBuilder<T, SuperBuilderClassNameCollisionQualified<T>, SuperBuilderClassNameCollisionQualified.SuperBuilderImpl<T>> {
private SuperBuilderImpl() {
super();
}
protected @java.lang.Override @java.lang.SuppressWarnings("all") @lombok.Generated SuperBuilderClassNameCollisionQualified.SuperBuilderImpl<T> self() {
return this;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") @lombok.Generated SuperBuilderClassNameCollisionQualified<T> build() {
return new SuperBuilderClassNameCollisionQualified<T>(this);
}
}
T value;
protected @java.lang.SuppressWarnings("all") @lombok.Generated SuperBuilderClassNameCollisionQualified(final SuperBuilderClassNameCollisionQualified.SuperBuilder<T, ?, ?> b) {
super();
this.value = b.value;
}
public static @java.lang.SuppressWarnings("all") @lombok.Generated <T>SuperBuilderClassNameCollisionQualified.SuperBuilder<T, ?, ?> builder() {
return new SuperBuilderClassNameCollisionQualified.SuperBuilderImpl<T>();
}
}
@@ -0,0 +1,7 @@
//skip compare content
import lombok.Builder;
@Builder(builderClassName = "Builder")
class BuilderClassNameCollision<T> {
T value;
}
@@ -0,0 +1,4 @@
@lombok.Builder(builderClassName = "Builder")
class BuilderClassNameCollisionQualified<T> {
private java.util.function.Function<T, String> mapper;
}
@@ -0,0 +1,8 @@
//skip compare content
//CONF: lombok.builder.className = SuperBuilder
import lombok.SuperBuilder;
@SuperBuilder
class SuperBuilderClassNameCollision {
int value;
}
@@ -0,0 +1,5 @@
//CONF: lombok.builder.className = SuperBuilder
@lombok.SuperBuilder
class SuperBuilderClassNameCollisionQualified<T> {
T value;
}
@@ -0,0 +1 @@
4 builderClassName cannot be "Builder" when using @Builder; use @lombok.Builder or choose another builder class name.
@@ -0,0 +1 @@
5 builderClassName cannot be "SuperBuilder" when using @SuperBuilder; use @lombok.SuperBuilder or choose another builder class name.
@@ -0,0 +1 @@
4 builderClassName cannot be "Builder" when using @Builder; use @lombok.Builder or choose another builder class name.
@@ -0,0 +1 @@
5 builderClassName cannot be "SuperBuilder" when using @SuperBuilder; use @lombok.SuperBuilder or choose another builder class name.