Skip to content

Commit

Permalink
calculated correct generic type for toBuilder
Browse files Browse the repository at this point in the history
#134
(TODO: clean up and refactor code)
  • Loading branch information
mplushnikov committed Aug 27, 2017
1 parent 5e82632 commit 2916a68
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 21 deletions.
Expand Up @@ -2,11 +2,13 @@


import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiCodeBlock; import com.intellij.psi.PsiCodeBlock;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiField; import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiModifier;
Expand All @@ -18,6 +20,7 @@
import com.intellij.psi.PsiTypeParameter; import com.intellij.psi.PsiTypeParameter;
import com.intellij.psi.PsiTypeParameterListOwner; import com.intellij.psi.PsiTypeParameterListOwner;
import com.intellij.psi.PsiVariable; import com.intellij.psi.PsiVariable;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiTypesUtil;
import de.plushnikov.intellij.plugin.problem.ProblemBuilder; import de.plushnikov.intellij.plugin.problem.ProblemBuilder;
import de.plushnikov.intellij.plugin.processor.ShouldGenerateFullCodeBlock; import de.plushnikov.intellij.plugin.processor.ShouldGenerateFullCodeBlock;
Expand Down Expand Up @@ -305,20 +308,55 @@ public void createBuilderMethodIfNecessary(@NotNull Collection<? super PsiElemen


public void createToBuilderMethodIfNecessary(@NotNull Collection<? super PsiElement> target, @NotNull PsiClass containingClass, @Nullable PsiMethod psiMethod, @NotNull PsiClass builderPsiClass, @NotNull PsiAnnotation psiAnnotation) { public void createToBuilderMethodIfNecessary(@NotNull Collection<? super PsiElement> target, @NotNull PsiClass containingClass, @Nullable PsiMethod psiMethod, @NotNull PsiClass builderPsiClass, @NotNull PsiAnnotation psiAnnotation) {
if (PsiAnnotationUtil.getBooleanAnnotationValue(psiAnnotation, TO_BUILDER_ANNOTATION_KEY, false)) { if (PsiAnnotationUtil.getBooleanAnnotationValue(psiAnnotation, TO_BUILDER_ANNOTATION_KEY, false)) {
final PsiType psiTypeWithGenerics = PsiClassUtil.getTypeWithGenerics(builderPsiClass);
final PsiType psiTypeWithGenerics;
if (null != psiMethod) {
psiTypeWithGenerics = calculateResultType(psiMethod, builderPsiClass, containingClass);
} else {
psiTypeWithGenerics = PsiClassUtil.getTypeWithGenerics(builderPsiClass);
}


final LombokLightMethodBuilder method = new LombokLightMethodBuilder(containingClass.getManager(), TO_BUILDER_METHOD_NAME) final LombokLightMethodBuilder method = new LombokLightMethodBuilder(containingClass.getManager(), TO_BUILDER_METHOD_NAME)
.withMethodReturnType(psiTypeWithGenerics) .withMethodReturnType(psiTypeWithGenerics)
.withContainingClass(containingClass) .withContainingClass(containingClass)
.withNavigationElement(psiAnnotation) .withNavigationElement(psiAnnotation)
.withModifier(PsiModifier.PUBLIC); .withModifier(PsiModifier.PUBLIC);
addTypeParameters(builderPsiClass, psiMethod, method);


method.withBody(createToBuilderMethodCodeBlock(containingClass, psiMethod, psiTypeWithGenerics)); method.withBody(createToBuilderMethodCodeBlock(containingClass, psiMethod, psiTypeWithGenerics));
target.add(method); target.add(method);
} }
} }


private PsiType calculateResultType(@NotNull PsiMethod psiMethod, PsiClass builderPsiClass, PsiClass psiClass) {
final Collection<PsiParameter> builderParameters = getBuilderParameters(psiMethod, Collections.<PsiField>emptySet());

final Collection<PsiType> types = new ArrayList<>();
for (PsiVariable psiVariable : builderParameters) {

final PsiAnnotation obtainViaAnnotation = PsiAnnotationSearchUtil.findAnnotation(psiVariable, BUILDER_OBTAIN_VIA_ANNOTATION);
if (null != obtainViaAnnotation) {
final String viaFieldName = PsiAnnotationUtil.getStringAnnotationValue(obtainViaAnnotation, BUILDER_OBTAIN_VIA_FIELD);

final PsiField fieldByName = psiClass.findFieldByName(viaFieldName, false);
if (fieldByName != null) {
psiVariable = fieldByName;
}
}


final PsiType psiVariableType = psiVariable.getType();

if (psiVariableType instanceof PsiClassReferenceType) {
final PsiClass resolvedPsiVariableClass = ((PsiClassReferenceType) psiVariableType).resolve();
if (resolvedPsiVariableClass instanceof PsiTypeParameter) {
types.add(psiVariableType);
}
}
}
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject());
return factory.createType(builderPsiClass, types.toArray(new PsiType[types.size()]));
}

@NotNull @NotNull
private PsiCodeBlock createBuilderMethodCodeBlock(@NotNull PsiClass containingClass, @NotNull PsiType psiTypeWithGenerics) { private PsiCodeBlock createBuilderMethodCodeBlock(@NotNull PsiClass containingClass, @NotNull PsiType psiTypeWithGenerics) {
final String blockText; final String blockText;
Expand Down Expand Up @@ -347,10 +385,6 @@ private PsiCodeBlock createToBuilderMethodCodeBlock(@NotNull PsiClass psiClass,


final StringBuilder methodCalls = new StringBuilder(); final StringBuilder methodCalls = new StringBuilder();
for (PsiVariable psiVariable : builderVariables) { for (PsiVariable psiVariable : builderVariables) {
//TODO
// psiVariable.getType()
// JavaPsiFacade.getElementFactory(project).createType(genericClass, psiTypes)

methodCalls.append('.'); methodCalls.append('.');
methodCalls.append(accessorsInfo.removePrefix(psiVariable.getName())); methodCalls.append(accessorsInfo.removePrefix(psiVariable.getName()));
methodCalls.append('('); methodCalls.append('(');
Expand Down
@@ -1,6 +1,6 @@
package de.plushnikov.builder; package de.plushnikov.builder;


import lombok.Builder; import lombok.experimental.Builder;


@Builder @Builder
public class BuilderExperimentalExample { public class BuilderExperimentalExample {
Expand Down
@@ -1,6 +1,6 @@
package de.plushnikov.builder.tobuilder; package de.plushnikov.builder.tobuilder;


import java.util.Arrays; import java.util.Collections;


@lombok.Builder(toBuilder = true) @lombok.Builder(toBuilder = true)
@lombok.experimental.Accessors(prefix = "m") @lombok.experimental.Accessors(prefix = "m")
Expand All @@ -18,16 +18,16 @@ public static <K> K rrr(BuilderWithToBuilderOnClass<K> x) {
} }


public static void main(String[] args) { public static void main(String[] args) {
BuilderWithToBuilderOnClass<String> bean = new BuilderWithToBuilderOnClass<String>("mOneParam", "mTwoParam", "fooParam", Arrays.asList("barsParam1")); BuilderWithToBuilderOnClass<String> bean = new BuilderWithToBuilderOnClass<String>("mOneParam", "mTwoParam", "fooParam", Collections.singletonList("barsParam1"));
bean.mOne = "mOne"; bean.mOne = "mOne";
bean.mTwo = "mTwo"; bean.mTwo = "mTwo";
bean.foo = "foo"; bean.foo = "foo";


BuilderWithToBuilderOnClass.BuilderWithToBuilderOnClassBuilder x = bean.toBuilder(); BuilderWithToBuilderOnClass.BuilderWithToBuilderOnClassBuilder<String> x = bean.toBuilder();
System.out.println(x); System.out.println(x);


x.one("builderOne"); x.one("builderOne");
x.bar("builderBar"); x.bar("builderBar");
System.out.println(x); System.out.println(x);
} }
} }
Expand Up @@ -19,7 +19,7 @@ public static void main(String[] args) {
bean.mTwo = "mTwo"; bean.mTwo = "mTwo";
bean.foo = "foo"; bean.foo = "foo";


BuilderWithToBuilderOnConstructor.BuilderWithToBuilderOnConstructorBuilder x = bean.toBuilder(); BuilderWithToBuilderOnConstructor.BuilderWithToBuilderOnConstructorBuilder<String> x = bean.toBuilder();
System.out.println(x); System.out.println(x);


x.mOne("builderOne"); x.mOne("builderOne");
Expand Down
Expand Up @@ -21,7 +21,7 @@ public static void main(String[] args) {
bean.bar = "bar"; bean.bar = "bar";
bean.foo = "foo"; bean.foo = "foo";


BuilderWithToBuilderOnMethod.BuilderWithToBuilderOnMethodBuilder x = bean.toBuilder(); BuilderWithToBuilderOnMethod.BuilderWithToBuilderOnMethodBuilder<String> x = bean.toBuilder();
System.out.println(x); System.out.println(x);


x.mOne("builderOne"); x.mOne("builderOne");
Expand Down
@@ -1,6 +1,6 @@
package de.plushnikov.builder.tobuilder; package de.plushnikov.builder.tobuilder;


import java.util.Arrays; import java.util.Collections;


@lombok.Builder(toBuilder = true) @lombok.Builder(toBuilder = true)
public class SimpleBuilderWithToBuilderOnClass { public class SimpleBuilderWithToBuilderOnClass {
Expand All @@ -17,7 +17,7 @@ public static String rrr(SimpleBuilderWithToBuilderOnClass x) {
} }


public static void main(String[] args) { public static void main(String[] args) {
SimpleBuilderWithToBuilderOnClass bean = new SimpleBuilderWithToBuilderOnClass("mOneParam", "mTwoParam", "fooParam", Arrays.asList("barsParam1")); SimpleBuilderWithToBuilderOnClass bean = new SimpleBuilderWithToBuilderOnClass("mOneParam", "mTwoParam", "fooParam", Collections.singletonList("barsParam1"));
bean.one = "one"; bean.one = "one";
bean.two = "two"; bean.two = "two";
bean.foo = "foo"; bean.foo = "foo";
Expand All @@ -29,4 +29,4 @@ public static void main(String[] args) {
x.bar("builderBar"); x.bar("builderBar");
System.out.println(x); System.out.println(x);
} }
} }
8 changes: 4 additions & 4 deletions testData/after/builder/BuilderWithToBuilder.java
Expand Up @@ -93,15 +93,15 @@ public BuilderWithToBuilderBuilder<T> clearBars() {
public BuilderWithToBuilder<T> build() { public BuilderWithToBuilder<T> build() {
java.util.List<T> bars; java.util.List<T> bars;
switch (this.bars == null ? 0 : this.bars.size()) { switch (this.bars == null ? 0 : this.bars.size()) {
case 0: case 0:
bars = java.util.Collections.emptyList(); bars = java.util.Collections.emptyList();
break; break;


case 1: case 1:
bars = java.util.Collections.singletonList(this.bars.get(0)); bars = java.util.Collections.singletonList(this.bars.get(0));
break; break;


default: default:
bars = java.util.Collections.unmodifiableList(new java.util.ArrayList<T>(this.bars)); bars = java.util.Collections.unmodifiableList(new java.util.ArrayList<T>(this.bars));
} }
return new BuilderWithToBuilder<T>(one, two, foo, bars); return new BuilderWithToBuilder<T>(one, two, foo, bars);
Expand Down Expand Up @@ -241,7 +241,7 @@ public StaticWithToBuilderBuilder<Z> bar(final Z bar) {


@java.lang.SuppressWarnings("all") @java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok") @javax.annotation.Generated("lombok")
public StaticWithToBuilder build() { public StaticWithToBuilder<Z, String> build() {
return StaticWithToBuilder.<Z>test(mOne, bar); return StaticWithToBuilder.<Z>test(mOne, bar);
} }


Expand Down
2 changes: 1 addition & 1 deletion testData/after/builder/BuilderWithToBuilderOnMethod.java
Expand Up @@ -43,7 +43,7 @@ public BuilderWithToBuilderOnMethodBuilder<Z> bar(final Z bar) {


@java.lang.SuppressWarnings("all") @java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok") @javax.annotation.Generated("lombok")
public BuilderWithToBuilderOnMethod build() { public BuilderWithToBuilderOnMethod<Z, String> build() {
return BuilderWithToBuilderOnMethod.<Z>test(one, bar); return BuilderWithToBuilderOnMethod.<Z>test(one, bar);
} }


Expand Down

0 comments on commit 2916a68

Please sign in to comment.