Skip to content

Commit

Permalink
Added support for @builder on classes with partial Builder implementa…
Browse files Browse the repository at this point in the history
…tion #33
  • Loading branch information
Michail Plushnikov committed Feb 22, 2015
1 parent a75b04f commit 8847144
Show file tree
Hide file tree
Showing 22 changed files with 337 additions and 101 deletions.
@@ -1,9 +1,9 @@
package de.plushnikov.intellij.plugin.action.delombok;

import de.plushnikov.intellij.plugin.processor.clazz.BuilderClassProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.BuilderExperimentalClassProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.BuilderExperimentalProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.BuilderProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.builder.BuilderClassProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.builder.BuilderExperimentalClassProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.builder.BuilderExperimentalProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.builder.BuilderProcessor;
import de.plushnikov.intellij.plugin.processor.method.BuilderClassMethodProcessor;
import de.plushnikov.intellij.plugin.processor.method.BuilderExperimentalClassMethodProcessor;
import de.plushnikov.intellij.plugin.processor.method.BuilderExperimentalMethodProcessor;
Expand Down
@@ -1,14 +1,14 @@
package de.plushnikov.intellij.plugin.action.delombok;

import de.plushnikov.intellij.plugin.processor.clazz.BuilderClassProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.BuilderProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.DataProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.EqualsAndHashCodeProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.GetterProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.SetterProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.ToStringProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.ValueProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.WitherProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.builder.BuilderClassProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.builder.BuilderProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.constructor.AllArgsConstructorProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.constructor.NoArgsConstructorProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.constructor.RequiredArgsConstructorProcessor;
Expand Down
Expand Up @@ -95,11 +95,12 @@ public Collection<PsiMethod> createToStringMethod(@NotNull PsiClass psiClass, @N
}

final Collection<PsiField> psiFields = filterFields(psiClass, psiAnnotation, false);
return createToStringMethod(psiClass, psiFields, psiAnnotation);
final PsiMethod stringMethod = createToStringMethod(psiClass, psiFields, psiAnnotation);
return Collections.singletonList(stringMethod);
}

@NotNull
public Collection<PsiMethod> createToStringMethod(@NotNull PsiClass psiClass, @NotNull Collection<PsiField> psiFields, @NotNull PsiAnnotation psiAnnotation) {
public PsiMethod createToStringMethod(@NotNull PsiClass psiClass, @NotNull Collection<PsiField> psiFields, @NotNull PsiAnnotation psiAnnotation) {
final PsiManager psiManager = psiClass.getManager();
LombokLightMethodBuilder method = new LombokLightMethodBuilder(psiManager, METHOD_NAME)
.withMethodReturnType(PsiType.getJavaLangString(psiManager, GlobalSearchScope.allScope(psiClass.getProject())))
Expand All @@ -112,8 +113,7 @@ public Collection<PsiMethod> createToStringMethod(@NotNull PsiClass psiClass, @N
method.withBody(PsiMethodUtil.createCodeBlockFromText(blockText, psiClass));

UserMapKeys.addReadUsageFor(psiFields);

return Collections.<PsiMethod>singletonList(method);
return method;
}

private String createParamString(@NotNull PsiClass psiClass, @NotNull Collection<PsiField> psiFields, @NotNull PsiAnnotation psiAnnotation) {
Expand Down
@@ -0,0 +1,65 @@
package de.plushnikov.intellij.plugin.processor.clazz.builder;

import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
import de.plushnikov.intellij.plugin.problem.ProblemBuilder;
import de.plushnikov.intellij.plugin.problem.ProblemEmptyBuilder;
import de.plushnikov.intellij.plugin.processor.clazz.AbstractClassProcessor;
import de.plushnikov.intellij.plugin.processor.handler.BuilderHandler;
import de.plushnikov.intellij.plugin.psi.LombokLightClass;
import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil;
import de.plushnikov.intellij.plugin.util.PsiClassUtil;
import org.jetbrains.annotations.NotNull;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public abstract class AbstractBuilderPreDefinedInnerClassProcessor extends AbstractClassProcessor {
protected final BuilderHandler builderHandler = new BuilderHandler();

public AbstractBuilderPreDefinedInnerClassProcessor(Class<? extends Annotation> supportedAnnotationClass, Class<? extends PsiElement> supportedClass) {
super(supportedAnnotationClass, supportedClass);
}

@NotNull
@Override
public List<? super PsiElement> process(@NotNull PsiClass psiClass) {
List<? super PsiElement> result = Collections.emptyList();

final PsiElement parentElement = psiClass.getParent();
if (parentElement instanceof PsiClass && !(parentElement instanceof LombokLightClass)) {
final PsiClass psiParentClass = (PsiClass) parentElement;
PsiAnnotation psiAnnotation = PsiAnnotationUtil.findAnnotation(psiParentClass, getSupportedAnnotation());
if (null != psiAnnotation) {
final PsiType psiBuilderType = PsiClassUtil.getTypeWithGenerics(psiParentClass);
final String builderClassName = builderHandler.getBuilderClassName(psiParentClass, psiAnnotation, psiBuilderType);

// apply only to inner BuilderClass
if (builderClassName.equals(psiClass.getName())) {
if (validate(psiAnnotation, psiClass, ProblemEmptyBuilder.getInstance())) {
result = new ArrayList<PsiElement>();
generatePsiElements(psiParentClass, psiClass, psiAnnotation, result);
}
}
}
}

return result;
}

protected abstract void generatePsiElements(@NotNull PsiClass psiParentClass, @NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, @NotNull List<? super PsiElement> target);

@Override
protected boolean validate(@NotNull PsiAnnotation psiAnnotation, @NotNull PsiClass psiClass, @NotNull ProblemBuilder builder) {
return true;
}

@Override
protected void generatePsiElements(@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, @NotNull List<? super PsiElement> target) {
//do nothing
}
}
@@ -1,9 +1,10 @@
package de.plushnikov.intellij.plugin.processor.clazz;
package de.plushnikov.intellij.plugin.processor.clazz.builder;

import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import de.plushnikov.intellij.plugin.problem.ProblemBuilder;
import de.plushnikov.intellij.plugin.processor.clazz.AbstractClassProcessor;
import de.plushnikov.intellij.plugin.processor.handler.BuilderHandler;
import lombok.Builder;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -32,10 +33,12 @@ protected BuilderClassProcessor(@NotNull Class<? extends Annotation> builderClas

@Override
protected boolean validate(@NotNull PsiAnnotation psiAnnotation, @NotNull PsiClass psiClass, @NotNull ProblemBuilder builder) {
return builderHandler.validate(psiAnnotation, psiClass, true, builder);
return builderHandler.validate(psiClass, psiAnnotation, builder);
}

protected void generatePsiElements(@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, @NotNull List<? super PsiElement> target) {
target.add(builderHandler.createBuilderClass(psiClass, psiAnnotation));
if (builderHandler.existInnerClass(psiClass, psiAnnotation)) {
target.add(builderHandler.createBuilderClass(psiClass, psiAnnotation));
}
}
}
@@ -1,4 +1,4 @@
package de.plushnikov.intellij.plugin.processor.clazz;
package de.plushnikov.intellij.plugin.processor.clazz.builder;

import lombok.experimental.Builder;

Expand Down
@@ -0,0 +1,10 @@
package de.plushnikov.intellij.plugin.processor.clazz.builder;

import lombok.experimental.Builder;

public class BuilderExperimentalPreDefinedInnerClassFieldProcessor extends BuilderPreDefinedInnerClassFieldProcessor {
@SuppressWarnings("deprecation")
public BuilderExperimentalPreDefinedInnerClassFieldProcessor() {
super(Builder.class);
}
}
@@ -0,0 +1,10 @@
package de.plushnikov.intellij.plugin.processor.clazz.builder;

import lombok.experimental.Builder;

public class BuilderExperimentalPreDefinedInnerClassMethodProcessor extends BuilderPreDefinedInnerClassMethodProcessor {
@SuppressWarnings("deprecation")
public BuilderExperimentalPreDefinedInnerClassMethodProcessor() {
super(Builder.class);
}
}
@@ -1,4 +1,4 @@
package de.plushnikov.intellij.plugin.processor.clazz;
package de.plushnikov.intellij.plugin.processor.clazz.builder;

import lombok.experimental.Builder;

Expand Down
@@ -0,0 +1,36 @@
package de.plushnikov.intellij.plugin.processor.clazz.builder;

import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import de.plushnikov.intellij.plugin.processor.handler.BuilderHandler;
import de.plushnikov.intellij.plugin.util.PsiClassUtil;
import lombok.Builder;
import org.jetbrains.annotations.NotNull;

import java.lang.annotation.Annotation;
import java.util.List;

/**
* Creates methods for a builder inner class if it is predefined.
*
* @author Michail Plushnikov
*/
public class BuilderPreDefinedInnerClassFieldProcessor extends AbstractBuilderPreDefinedInnerClassProcessor {

private final BuilderHandler builderHandler = new BuilderHandler();

public BuilderPreDefinedInnerClassFieldProcessor() {
this(Builder.class);
}

protected BuilderPreDefinedInnerClassFieldProcessor(@NotNull Class<? extends Annotation> builderClass) {
super(builderClass, PsiField.class);
}

@Override
protected void generatePsiElements(@NotNull PsiClass psiParentClass, @NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, @NotNull List<? super PsiElement> target) {
target.addAll(builderHandler.createFields(psiParentClass, PsiClassUtil.collectClassFieldsIntern(psiClass)));
}
}
@@ -0,0 +1,39 @@
package de.plushnikov.intellij.plugin.processor.clazz.builder;

import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import de.plushnikov.intellij.plugin.util.PsiClassUtil;
import lombok.Builder;
import org.jetbrains.annotations.NotNull;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.List;

/**
* Creates methods for a builder inner class if it is predefined.
*
* @author Michail Plushnikov
*/
public class BuilderPreDefinedInnerClassMethodProcessor extends AbstractBuilderPreDefinedInnerClassProcessor {

public BuilderPreDefinedInnerClassMethodProcessor() {
this(Builder.class);
}

protected BuilderPreDefinedInnerClassMethodProcessor(@NotNull Class<? extends Annotation> builderClass) {
super(builderClass, PsiMethod.class);
}

protected void generatePsiElements(@NotNull PsiClass psiParentClass, @NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, @NotNull List<? super PsiElement> target) {
final Collection<PsiField> tmpFields = builderHandler.createFields(psiParentClass);
final PsiType psiBuilderType = PsiClassUtil.getTypeWithGenerics(psiParentClass);
target.addAll(builderHandler.createConstructors(psiClass, psiAnnotation));
target.addAll(builderHandler.createMethods(psiClass, tmpFields, psiAnnotation, psiBuilderType, psiClass));
}

}
@@ -1,4 +1,4 @@
package de.plushnikov.intellij.plugin.processor.clazz;
package de.plushnikov.intellij.plugin.processor.clazz.builder;

import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
Expand All @@ -7,6 +7,7 @@
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiType;
import de.plushnikov.intellij.plugin.problem.ProblemBuilder;
import de.plushnikov.intellij.plugin.processor.clazz.AbstractClassProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.constructor.AllArgsConstructorProcessor;
import de.plushnikov.intellij.plugin.processor.handler.BuilderHandler;
import de.plushnikov.intellij.plugin.util.PsiClassUtil;
Expand Down Expand Up @@ -39,7 +40,7 @@ protected BuilderProcessor(@NotNull Class<? extends Annotation> builderClass) {

@Override
protected boolean validate(@NotNull PsiAnnotation psiAnnotation, @NotNull PsiClass psiClass, @NotNull ProblemBuilder builder) {
return builderHandler.validate(psiAnnotation, psiClass, false, builder);
return builderHandler.validate(psiClass, psiAnnotation, builder);
}

protected void generatePsiElements(@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, @NotNull List<? super PsiElement> target) {
Expand Down

0 comments on commit 8847144

Please sign in to comment.