Skip to content

Commit

Permalink
fixed #406 added delombok support for @UtilityClass
Browse files Browse the repository at this point in the history
  • Loading branch information
mplushnikov committed Apr 13, 2019
1 parent 8761a95 commit 9c3c4fd
Show file tree
Hide file tree
Showing 14 changed files with 168 additions and 17 deletions.
1 change: 1 addition & 0 deletions parts/pluginChanges.html
@@ -1,6 +1,7 @@
<ul>
<li>0.25
<ol>
<li>Fixed #406: Added delombok support for @UtilityClass</li>
<li>Fixed #522: Added configuration option to disable annotation processing warning</li>
<li>Fixed #580: '@ConstructorProperties' in Delomboked code</li>
<li>Fixed #613: NullPointerException on AccessLevel enum when IDE window open</li>
Expand Down
Expand Up @@ -98,21 +98,11 @@ private void processFile(Project project, VirtualFile file) {
}

protected void process(@NotNull final Project project, @NotNull final PsiJavaFile psiJavaFile) {
executeCommand(project, new Runnable() {
@Override
public void run() {
getHandler().invoke(project, psiJavaFile);
}
});
executeCommand(project, () -> getHandler().invoke(project, psiJavaFile));
}

protected void process(@NotNull final Project project, @NotNull final PsiFile psiFile, @NotNull final PsiClass psiClass) {
executeCommand(project, new Runnable() {
@Override
public void run() {
getHandler().invoke(project, psiFile, psiClass);
}
});
executeCommand(project, () -> getHandler().invoke(project, psiFile, psiClass));
}

private void executeCommand(final Project project, final Runnable action) {
Expand Down
Expand Up @@ -5,6 +5,7 @@
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.UtilityClassProcessor;
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;
Expand Down Expand Up @@ -67,6 +68,8 @@ protected DelombokHandler createHandler() {
findExtension(FieldNameConstantsProcessor.class),
findExtension(FieldNameConstantsPredefinedInnerClassFieldProcessor.class),

findExtension(UtilityClassProcessor.class),

findExtension(BuilderPreDefinedInnerClassFieldProcessor.class),
findExtension(BuilderPreDefinedInnerClassMethodProcessor.class),
findExtension(BuilderClassProcessor.class),
Expand Down
Expand Up @@ -6,8 +6,10 @@
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import de.plushnikov.intellij.plugin.extension.LombokProcessorExtensionPoint;
import de.plushnikov.intellij.plugin.processor.AbstractProcessor;
import de.plushnikov.intellij.plugin.processor.clazz.fieldnameconstants.FieldNameConstantsPredefinedInnerClassFieldProcessor;
import de.plushnikov.intellij.plugin.processor.modifier.ModifierProcessor;
import de.plushnikov.intellij.plugin.psi.LombokLightClassBuilder;
import de.plushnikov.intellij.plugin.settings.ProjectSettings;
import de.plushnikov.intellij.plugin.util.PsiClassUtil;
Expand All @@ -20,6 +22,8 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;

public class DelombokHandler {
private final boolean processInnerClasses;
Expand Down Expand Up @@ -51,6 +55,8 @@ public void invoke(@NotNull Project project, @NotNull PsiJavaFile psiFile) {
private void invoke(Project project, PsiClass psiClass, boolean processInnerClasses) {
Collection<PsiAnnotation> processedAnnotations = new HashSet<>();

processModifierList(psiClass);

// get all inner classes before first lombok processing
final PsiClass[] allInnerClasses = psiClass.getAllInnerClasses();

Expand Down Expand Up @@ -93,6 +99,32 @@ private Collection<PsiAnnotation> processClass(@NotNull Project project, @NotNul
return psiAnnotations;
}

private void processModifierList(@NotNull PsiClass psiClass) {
rebuildModifierList(psiClass);
PsiClassUtil.collectClassFieldsIntern(psiClass).forEach(this::rebuildModifierList);
PsiClassUtil.collectClassMethodsIntern(psiClass).forEach(this::rebuildModifierList);
PsiClassUtil.collectClassStaticMethodsIntern(psiClass).forEach(this::rebuildModifierList);
}

private void rebuildModifierList(@NotNull PsiModifierListOwner modifierListOwner) {
final PsiModifierList modifierList = modifierListOwner.getModifierList();
if (null != modifierList) {
final Set<String> lombokModifiers = new HashSet<>();
getLombokModifierProcessors().forEach(modifierProcessor -> {
if (modifierProcessor.isSupported(modifierList)) {
modifierProcessor.transformModifiers(modifierList, lombokModifiers);
lombokModifiers.forEach(modifier -> modifierList.setModifierProperty(modifier, true));
lombokModifiers.clear();
}
});
}
}

@NotNull
private Stream<ModifierProcessor> getLombokModifierProcessors() {
return Stream.of(LombokProcessorExtensionPoint.EP_NAME_MODIFIER_PROCESSOR.getExtensions());
}

private void rebuildElementsBeforeExistingFields(Project project, PsiClass psiClass, List<? super PsiElement> psiElements) {
//add generated elements in generated/declaration order, but before existing Fields
if (!psiElements.isEmpty()) {
Expand Down
@@ -0,0 +1,12 @@
package de.plushnikov.intellij.plugin.action.delombok;

import de.plushnikov.intellij.plugin.processor.clazz.UtilityClassProcessor;
import de.plushnikov.intellij.plugin.util.ExtensionsUtil;
import org.jetbrains.annotations.NotNull;

public class DelombokUtilityClassAction extends AbstractDelombokAction {
@NotNull
protected DelombokHandler createHandler() {
return new DelombokHandler(true, ExtensionsUtil.findExtension(UtilityClassProcessor.class));
}
}
Expand Up @@ -58,7 +58,7 @@ public static boolean validateOnRightType(PsiClass psiClass, ProblemBuilder buil
if (psiClassUp.getContext() instanceof PsiFile) {
return true;
}
Boolean isStatic = isStatic(psiClassUp.getModifierList());
boolean isStatic = isStatic(psiClassUp.getModifierList());
if (isStatic || checkWrongType(psiClassUp)) {
contextUp = contextUp.getContext();
} else {
Expand Down
Expand Up @@ -32,7 +32,7 @@ public boolean isSupported(@NotNull PsiModifierList modifierList) {
}
}

if (!isElementFieldMethodOrInnerClass(modifierListParent)) {
if (!isElementFieldOrMethodOrInnerClass(modifierListParent)) {
return false;
}

Expand All @@ -55,12 +55,13 @@ public void transformModifiers(@NotNull PsiModifierList modifierList, @NotNull f
}

// STATIC
if (isElementFieldMethodOrInnerClass(parent)) {
if (isElementFieldOrMethodOrInnerClass(parent)) {
modifiers.add(PsiModifier.STATIC);
}
}

private boolean isElementFieldMethodOrInnerClass(PsiElement element) {
return element instanceof PsiField || element instanceof PsiMethod || (element instanceof PsiClass && element.getParent() instanceof PsiClass);
private boolean isElementFieldOrMethodOrInnerClass(PsiElement element) {
return element instanceof PsiField || element instanceof PsiMethod ||
(element instanceof PsiClass && element.getParent() instanceof PsiClass && !((PsiClass) element.getParent()).isInterface());
}
}
4 changes: 4 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Expand Up @@ -212,6 +212,10 @@
<action id="delombokFieldNameCostants" class="de.plushnikov.intellij.plugin.action.delombok.DelombokFieldNameConstantsAction"
text="@FieldNameConstants" description="Action to replace lombok @FieldNameConstants annotation with vanilla java fields">
</action>
<action id="delombokUtilityClass" class="de.plushnikov.intellij.plugin.action.delombok.DelombokUtilityClassAction"
text="@UtilityClass"
description="Action to replace lombok @UtilityClass annotation with vanilla java fields">
</action>

<add-to-group group-id="RefactoringMenu" anchor="last"/>
</group>
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/messages/lombokBundle.properties
Expand Up @@ -22,6 +22,7 @@ daemon.donate.title=Lombok support plugin updated to v{0}
daemon.donate.content=<br/>\
Helpful? <b><a href="https://www.paypal.me/mplushnikov">Donate with PayPal</a></b><br/><br/>\
Fixes:<br/>\
- Fixed (<a href="https://github.com/mplushnikov/lombok-intellij-plugin/issues/406">#406</a>): Added delombok support for @UtilityClass<br>\
- Fixed (<a href="https://github.com/mplushnikov/lombok-intellij-plugin/issues/522">#522</a>): Added configuration option to disable annotation processing warning<br>\
- Fixed (<a href="https://github.com/mplushnikov/lombok-intellij-plugin/issues/580">#580</a>): `@ConstructorProperties` in Delomboked code<br>\
- Fixed (<a href="https://github.com/mplushnikov/lombok-intellij-plugin/issues/613">#613</a>): NullPointerException on AccessLevel enum when IDE window open<br>\
Expand Down
@@ -0,0 +1,24 @@
package de.plushnikov.intellij.plugin.action.delombok;

import com.intellij.openapi.actionSystem.AnAction;
import de.plushnikov.intellij.plugin.action.LombokLightActionTestCase;

public class DelombokUtilityClassActionTest extends LombokLightActionTestCase {

protected AnAction getAction() {
return new DelombokUtilityClassAction();
}

@Override
protected String getBasePath() {
return super.getBasePath() + "/action/delombok/utilityclass";
}

public void testUtilityClass() throws Exception {
doTest();
}

public void testUtilityInner() throws Exception {
doTest();
}
}
16 changes: 16 additions & 0 deletions testData/action/delombok/utilityclass/afterUtilityClass.java
@@ -0,0 +1,16 @@
final class UtilityClass {
private static long someField = System.currentTimeMillis();

private UtilityClass() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}

static void someMethod() {
System.out.println();
}

protected static class InnerClass {

private String innerInnerMember;
}
}
31 changes: 31 additions & 0 deletions testData/action/delombok/utilityclass/afterUtilityInner.java
@@ -0,0 +1,31 @@
class UtilityInner {

static class InnerInner {
static final class InnerInnerInner {
static int member;

private InnerInnerInner() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
}
}
enum UtilityInsideEnum {
FOO, BAR;
static final class InsideEnum {
static int member;

private InsideEnum() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
}
}
interface UtilityInsideInterface {
final class InsideInterface {
static int member;

private InsideInterface() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
}
}
}
12 changes: 12 additions & 0 deletions testData/action/delombok/utilityclass/beforeUtilityClass.java
@@ -0,0 +1,12 @@
@lombok.experimental.UtilityClass
class UtilityClass {
private long someField = System.currentTimeMillis();

void someMethod() {
System.out.println();
}

protected class InnerClass {
private String innerInnerMember;
}
}
24 changes: 24 additions & 0 deletions testData/action/delombok/utilityclass/beforeUtilityInner.java
@@ -0,0 +1,24 @@
class UtilityInner {
static class InnerInner {
@lombok.experimental.UtilityClass
class InnerInnerInner {
int member;
}
}

enum UtilityInsideEnum {
FOO, BAR;

@lombok.experimental.UtilityClass
class InsideEnum {
int member;
}
}

interface UtilityInsideInterface {
@lombok.experimental.UtilityClass
class InsideInterface {
int member;
}
}
}

0 comments on commit 9c3c4fd

Please sign in to comment.