From ef5fbc0b251c951a55da9b27e3b52bd26b3694bf Mon Sep 17 00:00:00 2001 From: Michail Plushnikov Date: Sat, 23 Jan 2016 16:24:51 +0100 Subject: [PATCH] Added support for @Tolerate for @Getter and @Setter Issue # 175 --- .../processor/clazz/GetterProcessor.java | 1 + .../processor/clazz/SetterProcessor.java | 1 + .../processor/field/GetterFieldProcessor.java | 1 + .../processor/field/SetterFieldProcessor.java | 1 + .../intellij/plugin/util/PsiClassUtil.java | 2 +- .../src/main/resources/META-INF/plugin.xml | 1 + .../messages/lombokBundle.properties | 1 + .../src/test/data/after/TolerateTest.java | 32 ++++ .../src/test/data/before/TolerateTest.java | 26 ++++ .../lombok/LombokParsingTestCase.java | 140 +++++++++++------- .../plushnikov/lombok/tests/BuilderTest.java | 1 - .../plushnikov/lombok/tests/TolerateTest.java | 15 ++ 12 files changed, 169 insertions(+), 53 deletions(-) create mode 100644 lombok-plugin/src/test/data/after/TolerateTest.java create mode 100644 lombok-plugin/src/test/data/before/TolerateTest.java create mode 100644 lombok-plugin/src/test/java/de/plushnikov/lombok/tests/TolerateTest.java diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/GetterProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/GetterProcessor.java index 8bbe89702..4eed235b9 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/GetterProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/GetterProcessor.java @@ -85,6 +85,7 @@ protected Collection filterGetterFields(@NotNull PsiClass psiClass) { final Collection getterFields = new ArrayList(); final Collection classMethods = PsiClassUtil.collectClassMethodsIntern(psiClass); + filterToleratedElements(classMethods); for (PsiField psiField : psiClass.getFields()) { boolean createGetter = true; diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/SetterProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/SetterProcessor.java index b36c9f69d..d347d9eb5 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/SetterProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/SetterProcessor.java @@ -85,6 +85,7 @@ public Collection createFieldSetters(@NotNull PsiClass psiClass, @Not @NotNull protected Collection filterSetterFields(@NotNull PsiClass psiClass) { final Collection classMethods = PsiClassUtil.collectClassMethodsIntern(psiClass); + filterToleratedElements(classMethods); final Collection setterFields = new ArrayList(); for (PsiField psiField : psiClass.getFields()) { diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/GetterFieldProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/GetterFieldProcessor.java index b6112b99a..d9e2c7ef0 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/GetterFieldProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/GetterFieldProcessor.java @@ -97,6 +97,7 @@ protected boolean validateExistingMethods(@NotNull PsiField psiField, @NotNull P final AccessorsInfo accessorsInfo = AccessorsInfo.build(psiField); final Collection methodNames = LombokUtils.toAllGetterNames(accessorsInfo, psiField.getName(), isBoolean); final Collection classMethods = PsiClassUtil.collectClassMethodsIntern(psiClass); + filterToleratedElements(classMethods); for (String methodName : methodNames) { if (PsiMethodUtil.hasSimilarMethod(classMethods, methodName, 0)) { diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/SetterFieldProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/SetterFieldProcessor.java index dc2f599de..63f7eb430 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/SetterFieldProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/SetterFieldProcessor.java @@ -87,6 +87,7 @@ protected boolean validateExistingMethods(@NotNull PsiField psiField, @NotNull P final PsiClass psiClass = psiField.getContainingClass(); if (null != psiClass) { final Collection classMethods = PsiClassUtil.collectClassMethodsIntern(psiClass); + filterToleratedElements(classMethods); final boolean isBoolean = PsiType.BOOLEAN.equals(psiField.getType()); final Collection methodNames = getAllSetterNames(psiField, isBoolean); diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/util/PsiClassUtil.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/util/PsiClassUtil.java index dc8425cdf..d22a21e9e 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/util/PsiClassUtil.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/util/PsiClassUtil.java @@ -36,7 +36,7 @@ public class PsiClassUtil { @NotNull public static Collection collectClassMethodsIntern(@NotNull PsiClass psiClass) { if (psiClass instanceof PsiExtensibleClass) { - return ((PsiExtensibleClass) psiClass).getOwnMethods(); + return new ArrayList(((PsiExtensibleClass) psiClass).getOwnMethods()); } else { return filterPsiElements(psiClass, PsiMethod.class); } diff --git a/lombok-plugin/src/main/resources/META-INF/plugin.xml b/lombok-plugin/src/main/resources/META-INF/plugin.xml index 1eba8d677..8de3b00ea 100644 --- a/lombok-plugin/src/main/resources/META-INF/plugin.xml +++ b/lombok-plugin/src/main/resources/META-INF/plugin.xml @@ -212,6 +212,7 @@
  • Fixed #156: Exception in @Singular handling
  • Fixed #165: Can't correctly resolve multiple @Builder methods in same class having partial implementations
  • Fixed #172: "Lombok needs a default constructor in the base class" error in enum
  • +
  • Fixed #175: Added support for @Tolerate for @Getter and @Setter
  • 0.9.7 diff --git a/lombok-plugin/src/main/resources/messages/lombokBundle.properties b/lombok-plugin/src/main/resources/messages/lombokBundle.properties index 1b400ab84..349216431 100644 --- a/lombok-plugin/src/main/resources/messages/lombokBundle.properties +++ b/lombok-plugin/src/main/resources/messages/lombokBundle.properties @@ -5,6 +5,7 @@ daemon.donate.content=\ - Fixed (#156): Exception in @Singular handling
    \ - Fixed (#165): Can't correctly resolve multiple @Builder methods in same class having partial implementations
    \ - Fixed (#172): "Lombok needs a default constructor in the base class" error in enum
    \ +- Fixed (#175): Added support for @Tolerate for @Getter and @Setter
    \
    \ If you find my plugin helpful, donate me using \ PayPal \ No newline at end of file diff --git a/lombok-plugin/src/test/data/after/TolerateTest.java b/lombok-plugin/src/test/data/after/TolerateTest.java new file mode 100644 index 000000000..37e732584 --- /dev/null +++ b/lombok-plugin/src/test/data/after/TolerateTest.java @@ -0,0 +1,32 @@ +import java.util.regex.Pattern; +class Tolerate { + private Pattern pattern; + public @lombok.experimental.Tolerate void setPattern(String pattern) { + setPattern(Pattern.compile(pattern)); + } + public @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") void setPattern(final Pattern pattern) { + this.pattern = pattern; + } + public @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") Pattern getPattern() { + return this.pattern; + } +} +class Tolerate2 { + private final Pattern pattern; + public Tolerate2 withPattern(String pattern) { + return withPattern(Pattern.compile(pattern)); + } + public Tolerate2 withPattern(String nameGlob, String extensionGlob) { + return withPattern(nameGlob.replace("*", ".*") + "\\." + extensionGlob.replace("*", ".*")); + } + + public @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") Pattern getPattern() { + return this.pattern; + } + public @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") Tolerate2 withPattern(final Pattern pattern) { + return this.pattern == pattern ? this : new Tolerate2(pattern); + } + public @java.beans.ConstructorProperties({"pattern"}) @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") Tolerate2(final Pattern pattern) { + this.pattern = pattern; + } +} diff --git a/lombok-plugin/src/test/data/before/TolerateTest.java b/lombok-plugin/src/test/data/before/TolerateTest.java new file mode 100644 index 000000000..f68e2db29 --- /dev/null +++ b/lombok-plugin/src/test/data/before/TolerateTest.java @@ -0,0 +1,26 @@ +import java.util.regex.Pattern; + +@lombok.Setter +@lombok.Getter +class Tolerate { + private Pattern pattern; + + @lombok.experimental.Tolerate public void setPattern(String pattern) { + setPattern(Pattern.compile(pattern)); + } +} + +@lombok.Getter +@lombok.experimental.Wither +@lombok.AllArgsConstructor +class Tolerate2 { + private final Pattern pattern; + + @lombok.experimental.Tolerate public Tolerate2 withPattern(String pattern) { + return withPattern(Pattern.compile(pattern)); + } + + public Tolerate2 withPattern(String nameGlob, String extensionGlob) { + return withPattern(nameGlob.replace("*", ".*") + "\\." + extensionGlob.replace("*", ".*")); + } +} diff --git a/lombok-plugin/src/test/java/de/plushnikov/lombok/LombokParsingTestCase.java b/lombok-plugin/src/test/java/de/plushnikov/lombok/LombokParsingTestCase.java index fba47c6a8..6b5fd3cb1 100644 --- a/lombok-plugin/src/test/java/de/plushnikov/lombok/LombokParsingTestCase.java +++ b/lombok-plugin/src/test/java/de/plushnikov/lombok/LombokParsingTestCase.java @@ -21,9 +21,12 @@ import com.intellij.psi.PsiParameterList; import com.intellij.psi.PsiReferenceList; import com.intellij.psi.PsiType; +import com.intellij.util.containers.SortedList; import org.apache.log4j.Logger; +import org.jetbrains.annotations.NotNull; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -173,54 +176,89 @@ private void compareModifiers(PsiModifierList beforeModifierList, PsiModifierLis } } - private void compareMethods(PsiClass beforeClass, PsiClass afterClass) { PsiMethod[] beforeMethods = beforeClass.getMethods(); PsiMethod[] afterMethods = afterClass.getMethods(); - LOG.info("Before methods for class " + beforeClass.getName() + ": " + Arrays.toString(beforeMethods)); - LOG.info("After methods for class " + afterClass.getName() + ": " + Arrays.toString(afterMethods)); - - assertEquals("Method counts are different for Class: " + beforeClass.getName(), afterMethods.length, beforeMethods.length); + assertEquals("Methods are different for Class: " + beforeClass.getName(), + Arrays.toString(toList(afterMethods)), Arrays.toString(toList(beforeMethods))); for (PsiMethod afterMethod : afterMethods) { - boolean compared = false; - final PsiModifierList afterModifierList = afterMethod.getModifierList(); - for (PsiMethod beforeMethod : beforeMethods) { - if (afterMethod.getName().equals(beforeMethod.getName()) && - afterMethod.getParameterList().getParametersCount() == beforeMethod.getParameterList().getParametersCount()) { - PsiModifierList beforeModifierList = beforeMethod.getModifierList(); - - compareModifiers(beforeModifierList, afterModifierList); - compareType(beforeMethod.getReturnType(), afterMethod.getReturnType(), afterMethod); - compareParams(beforeMethod.getParameterList(), afterMethod.getParameterList()); - compareThrows(beforeMethod.getThrowsList(), afterMethod.getThrowsList(), afterMethod); - - if (shouldCompareCodeBlocks()) { - final PsiCodeBlock beforeMethodBody = beforeMethod.getBody(); - final PsiCodeBlock afterMethodBody = afterMethod.getBody(); - if (null != beforeMethodBody && null != afterMethodBody) { - - boolean codeBlocksAreEqual = beforeMethodBody.textMatches(afterMethodBody); - if (!codeBlocksAreEqual) { - String text1 = beforeMethodBody.getText().replaceAll("\\s+", ""); - String text2 = afterMethodBody.getText().replaceAll("\\s+", ""); - assertEquals("Methods not equal, Method: (" + afterMethod.getName() + ") Class:" + afterClass.getName(), text2, text1); - } - } else { - if (null != afterMethodBody) { - fail("MethodCodeBlocks is null: Method: (" + beforeMethod.getName() + ") Class:" + beforeClass.getName()); - } - } - } - compared = true; + final Collection matchedMethods = filterMethods(beforeMethods, afterMethod); + if (matchedMethods.isEmpty()) { + fail("Method names are not equal, Method: (" + afterMethod.getName() + ") not found in class : " + beforeClass.getName()); + } + + for (PsiMethod beforeMethod : matchedMethods) { + compareMethod(beforeClass, afterClass, afterMethod, beforeMethod); + } + } + } + + private void compareMethod(PsiClass beforeClass, PsiClass afterClass, PsiMethod afterMethod, PsiMethod beforeMethod) { + final PsiModifierList afterModifierList = afterMethod.getModifierList(); + PsiModifierList beforeModifierList = beforeMethod.getModifierList(); + + compareModifiers(beforeModifierList, afterModifierList); + compareType(beforeMethod.getReturnType(), afterMethod.getReturnType(), afterMethod); + compareParams(beforeMethod.getParameterList(), afterMethod.getParameterList()); + compareThrows(beforeMethod.getThrowsList(), afterMethod.getThrowsList(), afterMethod); + + if (shouldCompareCodeBlocks()) { + final PsiCodeBlock beforeMethodBody = beforeMethod.getBody(); + final PsiCodeBlock afterMethodBody = afterMethod.getBody(); + if (null != beforeMethodBody && null != afterMethodBody) { + + boolean codeBlocksAreEqual = beforeMethodBody.textMatches(afterMethodBody); + if (!codeBlocksAreEqual) { + String text1 = beforeMethodBody.getText().replaceAll("\\s+", ""); + String text2 = afterMethodBody.getText().replaceAll("\\s+", ""); + assertEquals("Methods not equal, Method: (" + afterMethod.getName() + ") Class:" + afterClass.getName(), text2, text1); + } + } else { + if (null != afterMethodBody) { + fail("MethodCodeBlocks is null: Method: (" + beforeMethod.getName() + ") Class:" + beforeClass.getName()); } } - assertTrue("Method names are not equal, Method: (" + afterMethod.getName() + ") not found in class : " + beforeClass.getName(), compared); } } + private Collection filterMethods(PsiMethod[] beforeMethods, PsiMethod compareMethod) { + Collection result = new ArrayList(); + for (PsiMethod psiMethod : beforeMethods) { + final PsiParameterList compareMethodParameterList = compareMethod.getParameterList(); + final PsiParameterList psiMethodParameterList = psiMethod.getParameterList(); + if (compareMethod.getName().equals(psiMethod.getName()) && + compareMethodParameterList.getParametersCount() == psiMethodParameterList.getParametersCount()) { + final Collection typesOfCompareMethod = mapToTypeString(compareMethodParameterList); + final Collection typesOfPsiMethod = mapToTypeString(psiMethodParameterList); + if (typesOfCompareMethod.equals(typesOfPsiMethod)) { + result.add(psiMethod); + } + } + } + return result; + } + + @NotNull + private Collection mapToTypeString(PsiParameterList compareMethodParameterList) { + Collection result = new ArrayList(); + final PsiParameter[] compareMethodParameterListParameters = compareMethodParameterList.getParameters(); + for (PsiParameter compareMethodParameterListParameter : compareMethodParameterListParameters) { + result.add(stripJavaLang(compareMethodParameterListParameter.getType().getCanonicalText())); + } + return result; + } + + private String[] toList(PsiMethod[] beforeMethods) { + SortedList result = new SortedList(String.CASE_INSENSITIVE_ORDER); + for (PsiMethod method : beforeMethods) { + result.add(method.getName()); + } + return result.toArray(new String[result.size()]); + } + private void compareThrows(PsiReferenceList beforeThrows, PsiReferenceList afterThrows, PsiMethod psiMethod) { PsiClassType[] beforeTypes = beforeThrows.getReferencedTypes(); PsiClassType[] afterTypes = afterThrows.getReferencedTypes(); @@ -238,33 +276,33 @@ private void compareThrows(PsiReferenceList beforeThrows, PsiReferenceList after } } - private void compareConstructors(PsiClass intellij, PsiClass theirs) { - PsiMethod[] intellijConstructors = intellij.getConstructors(); - PsiMethod[] theirsConstructors = theirs.getConstructors(); + private void compareConstructors(PsiClass beforeClass, PsiClass afterClass) { + PsiMethod[] beforeConstructors = beforeClass.getConstructors(); + PsiMethod[] afterConstructors = afterClass.getConstructors(); - LOG.debug("IntelliJ constructors for class " + intellij.getName() + ": " + Arrays.toString(intellijConstructors)); - LOG.debug("Theirs constructors for class " + theirs.getName() + ": " + Arrays.toString(theirsConstructors)); + LOG.debug("IntelliJ constructors for class " + beforeClass.getName() + ": " + Arrays.toString(beforeConstructors)); + LOG.debug("Theirs constructors for class " + afterClass.getName() + ": " + Arrays.toString(afterConstructors)); - assertEquals("Constructor counts are different for Class: " + intellij.getName(), theirsConstructors.length, intellijConstructors.length); + assertEquals("Constructor counts are different for Class: " + beforeClass.getName(), afterConstructors.length, beforeConstructors.length); - for (PsiMethod theirsConstructor : theirsConstructors) { + for (PsiMethod afterConstructor : afterConstructors) { boolean compared = false; - final PsiModifierList theirsFieldModifierList = theirsConstructor.getModifierList(); - for (PsiMethod intellijConstructor : intellijConstructors) { - if (theirsConstructor.getName().equals(intellijConstructor.getName()) && - theirsConstructor.getParameterList().getParametersCount() == intellijConstructor.getParameterList().getParametersCount()) { - PsiModifierList intellijConstructorModifierList = intellijConstructor.getModifierList(); + final PsiModifierList theirsFieldModifierList = afterConstructor.getModifierList(); + for (PsiMethod beforeConstructor : beforeConstructors) { + if (afterConstructor.getName().equals(beforeConstructor.getName()) && + afterConstructor.getParameterList().getParametersCount() == beforeConstructor.getParameterList().getParametersCount()) { + PsiModifierList intellijConstructorModifierList = beforeConstructor.getModifierList(); compareModifiers(intellijConstructorModifierList, theirsFieldModifierList); - compareType(intellijConstructor.getReturnType(), theirsConstructor.getReturnType(), theirsConstructor); - compareParams(intellijConstructor.getParameterList(), theirsConstructor.getParameterList()); + compareType(beforeConstructor.getReturnType(), afterConstructor.getReturnType(), afterConstructor); + compareParams(beforeConstructor.getParameterList(), afterConstructor.getParameterList()); compared = true; break; } } - assertTrue("Constructor names are not equal, Method: (" + theirsConstructor.getName() + ") not found in class : " + intellij.getName(), compared); + assertTrue("Constructor names are not equal, Method: (" + afterConstructor.getName() + ") not found in class : " + beforeClass.getName(), compared); } } diff --git a/lombok-plugin/src/test/java/de/plushnikov/lombok/tests/BuilderTest.java b/lombok-plugin/src/test/java/de/plushnikov/lombok/tests/BuilderTest.java index ca2d83048..c153dc52c 100644 --- a/lombok-plugin/src/test/java/de/plushnikov/lombok/tests/BuilderTest.java +++ b/lombok-plugin/src/test/java/de/plushnikov/lombok/tests/BuilderTest.java @@ -52,7 +52,6 @@ public void testBuilderAndAllArgsConstructor() throws IOException { doTest(); } - // TODO fixme public void testBuilderMethodException() throws IOException { doTest(); } diff --git a/lombok-plugin/src/test/java/de/plushnikov/lombok/tests/TolerateTest.java b/lombok-plugin/src/test/java/de/plushnikov/lombok/tests/TolerateTest.java new file mode 100644 index 000000000..987e5c50a --- /dev/null +++ b/lombok-plugin/src/test/java/de/plushnikov/lombok/tests/TolerateTest.java @@ -0,0 +1,15 @@ +package de.plushnikov.lombok.tests; + +import de.plushnikov.lombok.LombokParsingTestCase; + +import java.io.IOException; + +/** + * Unit tests for IntelliJPlugin for Lombok, based on lombok test classes + */ +public class TolerateTest extends LombokParsingTestCase { + + public void testTolerateTest() throws IOException { + doTest(); + } +} \ No newline at end of file