mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-13 15:52:01 +07:00
[lombok] IDEA-354696 Fixed @SuperBuilder: 'toBuilder()' is already defined, if method is already defined in class
GitOrigin-RevId: 4a30ac0f71361b6d3f18be2654579ba574bc791d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
54a9138d9b
commit
f98149cc70
@@ -217,7 +217,7 @@ public class BuilderHandler {
|
||||
|
||||
public boolean validate(@NotNull PsiMethod psiMethod, @NotNull PsiAnnotation psiAnnotation, @NotNull ProblemSink problemSink) {
|
||||
final PsiClass psiClass = psiMethod.getContainingClass();
|
||||
boolean result = null!=psiClass && validateAnnotationOnRightType(psiClass, problemSink);
|
||||
boolean result = null != psiClass && validateAnnotationOnRightType(psiClass, problemSink);
|
||||
if (result) {
|
||||
final String builderClassName = getBuilderClassName(psiClass, psiAnnotation, psiMethod);
|
||||
|
||||
@@ -383,7 +383,7 @@ public class BuilderHandler {
|
||||
}
|
||||
|
||||
String relevantReturnType = psiClass.getName();
|
||||
if(psiClass instanceof PsiAnonymousClass psiAnonymousClass) {
|
||||
if (psiClass instanceof PsiAnonymousClass psiAnonymousClass) {
|
||||
relevantReturnType = psiAnonymousClass.getBaseClassType().getClassName();
|
||||
}
|
||||
|
||||
@@ -391,7 +391,8 @@ public class BuilderHandler {
|
||||
final PsiType psiMethodReturnType = psiMethod.getReturnType();
|
||||
if (psiMethodReturnType instanceof PsiClassType psiClassType) {
|
||||
relevantReturnType = psiClassType.getClassName();
|
||||
}else if (null != psiMethodReturnType) {
|
||||
}
|
||||
else if (null != psiMethodReturnType) {
|
||||
relevantReturnType = PsiNameHelper.getShortClassName(psiMethodReturnType.getPresentableText());
|
||||
}
|
||||
}
|
||||
@@ -406,7 +407,14 @@ public class BuilderHandler {
|
||||
return replace(builderClassNamePattern, "*", capitalize(StringUtil.notNullize(returnTypeName)));
|
||||
}
|
||||
|
||||
boolean hasMethod(@NotNull PsiClass psiClass, @NotNull String builderMethodName) {
|
||||
static boolean hasMethod(@NotNull PsiClass psiClass, @NotNull String builderMethodName, int paramCount) {
|
||||
final Collection<PsiMethod> existingMethods = PsiClassUtil.collectClassMethodsIntern(psiClass);
|
||||
return existingMethods.stream()
|
||||
.filter(method -> method.getParameterList().getParametersCount() == paramCount)
|
||||
.map(PsiMethod::getName).anyMatch(builderMethodName::equals);
|
||||
}
|
||||
|
||||
static boolean hasStaticMethod(@NotNull PsiClass psiClass, @NotNull String builderMethodName) {
|
||||
final Collection<PsiMethod> existingMethods = PsiClassUtil.collectClassStaticMethodsIntern(psiClass);
|
||||
return existingMethods.stream().map(PsiMethod::getName).anyMatch(builderMethodName::equals);
|
||||
}
|
||||
@@ -443,7 +451,7 @@ public class BuilderHandler {
|
||||
@NotNull PsiClass builderPsiClass,
|
||||
@NotNull PsiAnnotation psiAnnotation) {
|
||||
final String builderMethodName = getBuilderMethodName(psiAnnotation);
|
||||
if (!builderMethodName.isEmpty() && !hasMethod(containingClass, builderMethodName)) {
|
||||
if (!builderMethodName.isEmpty() && !hasStaticMethod(containingClass, builderMethodName)) {
|
||||
final PsiType psiTypeWithGenerics = PsiClassUtil.getTypeWithGenerics(builderPsiClass);
|
||||
|
||||
final String blockText = String.format("return new %s();", psiTypeWithGenerics.getCanonicalText(false));
|
||||
@@ -559,7 +567,8 @@ public class BuilderHandler {
|
||||
final PsiSubstitutor builderSubstitutor = getBuilderSubstitutor(psiClass, builderClass);
|
||||
final String accessVisibility = getBuilderInnerAccessVisibility(psiAnnotation);
|
||||
final String setterPrefix = getSetterPrefix(psiAnnotation);
|
||||
final LombokNullAnnotationLibrary nullAnnotationLibrary = ConfigDiscovery.getInstance().getAddNullAnnotationLombokConfigProperty(psiClass);
|
||||
final LombokNullAnnotationLibrary nullAnnotationLibrary =
|
||||
ConfigDiscovery.getInstance().getAddNullAnnotationLombokConfigProperty(psiClass);
|
||||
|
||||
return createBuilderInfos(psiClass, psiClassMethod)
|
||||
.map(info -> info.withSubstitutor(builderSubstitutor))
|
||||
|
||||
@@ -145,7 +145,7 @@ public class SuperBuilderHandler extends BuilderHandler {
|
||||
@NotNull PsiAnnotation psiAnnotation,
|
||||
@NotNull PsiClassType psiTypeBaseWithGenerics) {
|
||||
final String builderMethodName = getBuilderMethodName(psiAnnotation);
|
||||
if (builderMethodName.isEmpty() || hasMethod(containingClass, builderMethodName)) {
|
||||
if (builderMethodName.isEmpty() || hasStaticMethod(containingClass, builderMethodName)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ public class SuperBuilderHandler extends BuilderHandler {
|
||||
@NotNull PsiClass builderImplClass,
|
||||
@NotNull PsiAnnotation psiAnnotation,
|
||||
@NotNull PsiClassType psiTypeBaseWithGenerics) {
|
||||
if (!shouldGenerateToBuilderMethods(psiAnnotation)) {
|
||||
if (!shouldGenerateToBuilderMethods(psiAnnotation) || hasMethod(containingClass, TO_BUILDER_METHOD_NAME, 0)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,10 @@ public class SuperBuilderTest extends AbstractLombokParsingTestCase {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
public void testSuperbuilder$SuperBuilderToBuilderOverride() {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
//TODO Implement AnnotatedTypes handling/delombok
|
||||
// public void testSuperbuilder$SuperBuilderSingularAnnotatedTypes() {
|
||||
// doTest(true);
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
|
||||
class Base {
|
||||
private String string;
|
||||
|
||||
protected Base(BaseBuilder<?, ?> b) {
|
||||
this.string = b.string;
|
||||
}
|
||||
|
||||
public static BaseBuilder<?, ?> builder() {
|
||||
return new Base.BaseBuilderImpl();
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return this.string;
|
||||
}
|
||||
|
||||
public BaseBuilder<?, ?> toBuilder() {
|
||||
return new Base.BaseBuilderImpl().$fillValuesFrom(this);
|
||||
}
|
||||
|
||||
public static abstract class BaseBuilder<C extends Base, B extends BaseBuilder<C, B>> {
|
||||
private String string;
|
||||
|
||||
private static void $fillValuesFromInstanceIntoBuilder(Base instance, BaseBuilder<?, ?> b) {
|
||||
b.string(instance.string);
|
||||
}
|
||||
|
||||
public B string(String string) {
|
||||
this.string = string;
|
||||
return self();
|
||||
}
|
||||
|
||||
protected B $fillValuesFrom(C instance) {
|
||||
Base.BaseBuilder.$fillValuesFromInstanceIntoBuilder(instance, this);
|
||||
return self();
|
||||
}
|
||||
|
||||
protected abstract B self();
|
||||
|
||||
public abstract C build();
|
||||
|
||||
public String toString() {
|
||||
return "Base.BaseBuilder(string=" + this.string + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private static final class BaseBuilderImpl extends BaseBuilder<Base, BaseBuilderImpl> {
|
||||
private BaseBuilderImpl() {
|
||||
}
|
||||
|
||||
protected BaseBuilderImpl self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Base build() {
|
||||
return new Base(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Sub extends Base {
|
||||
private int number;
|
||||
|
||||
protected Sub(SubBuilder<?, ?> builder) {
|
||||
super(builder);
|
||||
}
|
||||
|
||||
public static SubBuilder<?, ?> builder() {
|
||||
return new Sub.SubBuilderImpl();
|
||||
}
|
||||
|
||||
public SubBuilder<?, ?> toBuilder() {
|
||||
// custom code should go here
|
||||
return new SubBuilderImpl().$fillValuesFrom(this);
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return this.number;
|
||||
}
|
||||
|
||||
public static abstract class SubBuilder<C extends Sub, B extends SubBuilder<C, B>> extends BaseBuilder<C, B> {
|
||||
private int number;
|
||||
|
||||
private static void $fillValuesFromInstanceIntoBuilder(Sub instance, SubBuilder<?, ?> b) {
|
||||
b.number(instance.number);
|
||||
}
|
||||
|
||||
public B number(int number) {
|
||||
this.number = number;
|
||||
return self();
|
||||
}
|
||||
|
||||
protected B $fillValuesFrom(C instance) {
|
||||
super.$fillValuesFrom(instance);
|
||||
Sub.SubBuilder.$fillValuesFromInstanceIntoBuilder(instance, this);
|
||||
return self();
|
||||
}
|
||||
|
||||
protected abstract B self();
|
||||
|
||||
public abstract C build();
|
||||
|
||||
public String toString() {
|
||||
return "Sub.SubBuilder(super=" + super.toString() + ", number=" + this.number + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SubBuilderImpl extends SubBuilder<Sub, SubBuilderImpl> {
|
||||
private SubBuilderImpl() {
|
||||
}
|
||||
|
||||
protected SubBuilderImpl self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Sub build() {
|
||||
return new Sub(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
@Getter
|
||||
@SuperBuilder(toBuilder = true)
|
||||
class Base {
|
||||
private String string;
|
||||
}
|
||||
|
||||
|
||||
@Getter
|
||||
@SuperBuilder(toBuilder = true)
|
||||
class Sub extends Base {
|
||||
private int number;
|
||||
|
||||
protected Sub(SubBuilder<?, ?> builder) {
|
||||
super(builder);
|
||||
}
|
||||
|
||||
public SubBuilder<?, ?> toBuilder() {
|
||||
// custom code should go here
|
||||
return new SubBuilderImpl().$fillValuesFrom(this);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user