From af7770eac47d5eaae5bdb3e3fd12def2f54ea879 Mon Sep 17 00:00:00 2001 From: Michail Plushnikov Date: Sat, 20 Oct 2018 15:07:48 +0200 Subject: [PATCH] added support for ToString.Include.rank functionality #504 updated TestData --- parts/pluginChanges.html | 3 +- .../EqualsAndHashCodeToStringHandler.java | 53 +++++++++++++++---- .../plugin/util/PsiAnnotationUtil.java | 23 +++----- .../messages/lombokBundle.properties | 2 +- .../processor/EqualsAndHashCodeTest.java | 4 ++ .../plugin/processor/ToStringTest.java | 4 ++ .../afterEqualsAndHashCodeExclude.java | 10 ++-- .../afterEqualsAndHashCodeNoGetters.java | 10 ++-- .../afterEqualsAndHashCodeOf.java | 10 ++-- .../afterEqualsAndHashCodeSimple.java | 10 ++-- .../EqualsAndHashCodeExplicitInclude.java | 22 ++++++++ .../tostring/ToStringExplicitInclude.java | 8 +++ .../EqualsAndHashCodeExplicitInclude.java | 4 ++ .../tostring/ToStringExplicitInclude.java | 4 ++ 14 files changed, 116 insertions(+), 51 deletions(-) create mode 100644 testData/after/equalsandhashcode/EqualsAndHashCodeExplicitInclude.java create mode 100644 testData/after/tostring/ToStringExplicitInclude.java create mode 100644 testData/before/equalsandhashcode/EqualsAndHashCodeExplicitInclude.java create mode 100644 testData/before/tostring/ToStringExplicitInclude.java diff --git a/parts/pluginChanges.html b/parts/pluginChanges.html index 467b42fffb..ebb5a2f71d 100644 --- a/parts/pluginChanges.html +++ b/parts/pluginChanges.html @@ -2,7 +2,7 @@
  • 0.22
    1. Performance improvements #516: Editor UI freezes when editing a particular class
    2. -
    3. Fixed #504: Added Support for Delombok of @EqualsAndHashcode/ToString.Exclude/Include
    4. +
    5. Fixed #504: Added Support for Delombok of @EqualsAndHashcode and @ToString Exclude/Include annotations
  • 0.21 @@ -26,7 +26,6 @@
    1. Fixed #475: Added support for @FieldNameConstants
    2. Fixed #488: Added support for @Flogger annotation
    3. - LombokConfigSyntaxHighlighterFactory
    4. Fixed #490: Added support for lombok.noArgsConstructor.extraPrivate
    5. Fixed #473: Warning about Wither requiring AllArgsConstructor, although Builder provides one
    6. Fixed #382: Added support for @XXX(onMethod_, onParam_, onConstructor_) for JDK8
    7. diff --git a/src/main/java/de/plushnikov/intellij/plugin/processor/handler/EqualsAndHashCodeToStringHandler.java b/src/main/java/de/plushnikov/intellij/plugin/processor/handler/EqualsAndHashCodeToStringHandler.java index 2a672a33d5..7d264ad74e 100644 --- a/src/main/java/de/plushnikov/intellij/plugin/processor/handler/EqualsAndHashCodeToStringHandler.java +++ b/src/main/java/de/plushnikov/intellij/plugin/processor/handler/EqualsAndHashCodeToStringHandler.java @@ -23,34 +23,45 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; public class EqualsAndHashCodeToStringHandler { - public static class MemberInfo { + + private static final String TO_STRING_RANK_ANNOTATION_PARAMETER = "rank"; + + public static class MemberInfo implements Comparable { private final PsiField psiField; private final PsiMethod psiMethod; private final String memberName; private final boolean defaultInclude; + private final int rankValue; MemberInfo(PsiField psiField) { this(psiField, psiField.getName(), false); } - MemberInfo(PsiField psiField, String memberName) { - this(psiField, memberName, false); + MemberInfo(PsiField psiField, String memberName, int rankValue) { + this(psiField, memberName, false, rankValue); } MemberInfo(PsiField psiField, String memberName, boolean defaultInclude) { + this(psiField, memberName, defaultInclude, 0); + } + + private MemberInfo(PsiField psiField, String memberName, boolean defaultInclude, int rankValue) { this.psiField = psiField; this.psiMethod = null; this.memberName = memberName; this.defaultInclude = defaultInclude; + this.rankValue = rankValue; } - MemberInfo(PsiMethod psiMethod, String memberName) { + MemberInfo(PsiMethod psiMethod, String memberName, int rankValue) { this.psiField = null; this.psiMethod = psiMethod; this.memberName = memberName; this.defaultInclude = false; + this.rankValue = rankValue; } public PsiField getField() { @@ -78,6 +89,11 @@ private boolean matchDefaultIncludedFieldName(String fieldName) { } return false; } + + @Override + public int compareTo(@NotNull MemberInfo other) { + return Integer.compare(other.rankValue, rankValue); + } } public Collection filterFields(@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, boolean filterTransient, String includeAnnotationProperty) { @@ -102,7 +118,7 @@ public Collection filterFields(@NotNull PsiClass psiClass, @NotNull final Collection psiMembers = PsiClassUtil.collectClassMemberIntern(psiClass); final Collection fieldNames2BeReplaced = new ArrayList<>(); - final Collection result = new ArrayList<>(psiMembers.size()); + final List result = new ArrayList<>(psiMembers.size()); for (PsiMember psiMember : psiMembers) { final PsiAnnotation includeAnnotation = PsiAnnotationSearchUtil.findAnnotation(psiMember, annotationIncludeFQN); @@ -144,22 +160,24 @@ public Collection filterFields(@NotNull PsiClass psiClass, @NotNull } result.add(new MemberInfo(psiField, fieldName, true)); } else { - final String annotationValue = PsiAnnotationUtil.getStringAnnotationValue(includeAnnotation, includeAnnotationProperty); + final String includeNameValue = PsiAnnotationUtil.getStringAnnotationValue(includeAnnotation, includeAnnotationProperty); final String newMemberName; - if (StringUtil.isEmptyOrSpaces(annotationValue)) { + if (StringUtil.isEmptyOrSpaces(includeNameValue)) { newMemberName = psiMember.getName(); } else { - newMemberName = annotationValue; + newMemberName = includeNameValue; } if ((psiMember instanceof PsiMethod)) { final PsiMethod psiMethod = (PsiMethod) psiMember; if (0 == psiMethod.getParameterList().getParametersCount()) { fieldNames2BeReplaced.add(newMemberName); - result.add(new MemberInfo(psiMethod, psiMethod.getName())); + int memberRank = calcMemberRank(includeAnnotation); + result.add(new MemberInfo(psiMethod, psiMethod.getName(), memberRank)); } } else { - result.add(new MemberInfo((PsiField) psiMember, newMemberName)); + int memberRank = calcMemberRank(includeAnnotation); + result.add(new MemberInfo((PsiField) psiMember, newMemberName, memberRank)); } } } @@ -169,9 +187,21 @@ public Collection filterFields(@NotNull PsiClass psiClass, @NotNull result.removeIf(memberInfo -> memberInfo.matchDefaultIncludedFieldName(fieldName)); } + result.sort(MemberInfo::compareTo); return result; } + private int calcMemberRank(@NotNull PsiAnnotation includeAnnotation) { + final String includeRankValue = PsiAnnotationUtil.getStringAnnotationValue(includeAnnotation, TO_STRING_RANK_ANNOTATION_PARAMETER); + if (!StringUtil.isEmptyOrSpaces(includeRankValue)) { + try { + return Integer.parseInt(includeRankValue); + } catch (NumberFormatException ignore) { + } + } + return 0; + } + public String getMemberAccessorName(@NotNull MemberInfo memberInfo, boolean doNotUseGetters, @NotNull PsiClass psiClass) { final String memberAccessor; if (null == memberInfo.getMethod()) { @@ -204,7 +234,8 @@ private String buildAttributeNameString(boolean doNotUseGetters, @NotNull PsiFie private Collection makeSet(@NotNull Collection exclude) { if (exclude.isEmpty()) { return Collections.emptySet(); + } else { + return new HashSet<>(exclude); } - return new HashSet<>(exclude); } } diff --git a/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationUtil.java b/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationUtil.java index 078308ab40..96049e4683 100644 --- a/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationUtil.java +++ b/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationUtil.java @@ -1,23 +1,7 @@ package de.plushnikov.intellij.plugin.util; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiAnnotationMemberValue; -import com.intellij.psi.PsiArrayInitializerMemberValue; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiClassObjectAccessExpression; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementFactory; -import com.intellij.psi.PsiEnumConstant; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiLiteralExpression; -import com.intellij.psi.PsiModifierList; -import com.intellij.psi.PsiModifierListOwner; -import com.intellij.psi.PsiReferenceExpression; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiTypeElement; -import com.intellij.psi.PsiVariable; +import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -121,6 +105,11 @@ private static T resolveElementValue(@NotNull PsiElement psiElement, @NotNul if (asClass.isAssignableFrom(PsiAnnotation.class)) { value = (T) psiElement; } + } else if (psiElement instanceof PsiPrefixExpression) { + if (asClass.isAssignableFrom(String.class)) { + String expressionText = psiElement.getText(); + value = (T) expressionText; + } } return value; } diff --git a/src/main/resources/messages/lombokBundle.properties b/src/main/resources/messages/lombokBundle.properties index a42cb25747..f831283243 100644 --- a/src/main/resources/messages/lombokBundle.properties +++ b/src/main/resources/messages/lombokBundle.properties @@ -23,7 +23,7 @@ daemon.donate.content=
      \ Helpful? Donate with PayPal

      \ Fixes:
      \ - Performance improvements (#516): Editor UI freezes when editing a particular class
      \ -- Fixed (#504): Added Support for Delombok of @EqualsAndHashcode/ToString.Exclude/Include
      \ +- Fixed (#504): Added Support for Delombok of @EqualsAndHashcode. and @ToString.Exclude/Include annotations
      \
      \ If you find my plugin helpful, donate me using
      \ PayPal\ diff --git a/src/test/java/de/plushnikov/intellij/plugin/processor/EqualsAndHashCodeTest.java b/src/test/java/de/plushnikov/intellij/plugin/processor/EqualsAndHashCodeTest.java index ed86780b74..f9dcddf970 100644 --- a/src/test/java/de/plushnikov/intellij/plugin/processor/EqualsAndHashCodeTest.java +++ b/src/test/java/de/plushnikov/intellij/plugin/processor/EqualsAndHashCodeTest.java @@ -23,6 +23,10 @@ public class EqualsAndHashCodeTest extends AbstractLombokParsingTestCase { doTest(true); } + public void testEqualsandhashcode$EqualsAndHashCodeExplicitInclude() { + doTest(true); + } + public void testEqualsandhashcode$EqualsAndHashCodeNestedShadow() { doTest(true); } diff --git a/src/test/java/de/plushnikov/intellij/plugin/processor/ToStringTest.java b/src/test/java/de/plushnikov/intellij/plugin/processor/ToStringTest.java index 2cfda700cc..671f95c2b9 100644 --- a/src/test/java/de/plushnikov/intellij/plugin/processor/ToStringTest.java +++ b/src/test/java/de/plushnikov/intellij/plugin/processor/ToStringTest.java @@ -19,6 +19,10 @@ public class ToStringTest extends AbstractLombokParsingTestCase { doTest(true); } + public void testTostring$ToStringExplicitInclude() { + doTest(true); + } + public void testTostring$ToStringInner() { doTest(true); } diff --git a/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeExclude.java b/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeExclude.java index c659af72a9..adfef4d77f 100644 --- a/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeExclude.java +++ b/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeExclude.java @@ -35,7 +35,7 @@ String getA() { return a; } - public boolean equals(Object o) { + public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof EqualsAndHashCodeSimpleExclude)) return false; final EqualsAndHashCodeSimpleExclude other = (EqualsAndHashCodeSimpleExclude) o; @@ -51,6 +51,10 @@ public boolean equals(Object o) { return true; } + protected boolean canEqual(final Object other) { + return other instanceof EqualsAndHashCodeSimpleExclude; + } + public int hashCode() { final int PRIME = 59; int result = 1; @@ -64,8 +68,4 @@ public int hashCode() { result = result * PRIME + ($a == null ? 43 : $a.hashCode()); return result; } - - protected boolean canEqual(Object other) { - return other instanceof EqualsAndHashCodeSimpleExclude; - } } diff --git a/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeNoGetters.java b/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeNoGetters.java index 7732beb926..ddf327d63a 100644 --- a/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeNoGetters.java +++ b/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeNoGetters.java @@ -35,7 +35,7 @@ String getA() { return a; } - public boolean equals(Object o) { + public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof EqualsAndHashCodeNoGetters)) return false; final EqualsAndHashCodeNoGetters other = (EqualsAndHashCodeNoGetters) o; @@ -52,6 +52,10 @@ public boolean equals(Object o) { return true; } + protected boolean canEqual(final Object other) { + return other instanceof EqualsAndHashCodeNoGetters; + } + public int hashCode() { final int PRIME = 59; int result = 1; @@ -66,8 +70,4 @@ public int hashCode() { result = result * PRIME + ($a == null ? 43 : $a.hashCode()); return result; } - - protected boolean canEqual(Object other) { - return other instanceof EqualsAndHashCodeNoGetters; - } } diff --git a/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeOf.java b/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeOf.java index 3667ba3650..5ddfb18170 100644 --- a/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeOf.java +++ b/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeOf.java @@ -35,7 +35,7 @@ String getA() { return a; } - public boolean equals(Object o) { + public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof EqualsAndHashCodeSimpleOf)) return false; final EqualsAndHashCodeSimpleOf other = (EqualsAndHashCodeSimpleOf) o; @@ -44,14 +44,14 @@ public boolean equals(Object o) { return true; } + protected boolean canEqual(final Object other) { + return other instanceof EqualsAndHashCodeSimpleOf; + } + public int hashCode() { final int PRIME = 59; int result = 1; result = result * PRIME + this.getX(); return result; } - - protected boolean canEqual(Object other) { - return other instanceof EqualsAndHashCodeSimpleOf; - } } diff --git a/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeSimple.java b/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeSimple.java index bf3ee0cb66..87f757e052 100644 --- a/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeSimple.java +++ b/testData/action/delombok/equalsandhashcode/afterEqualsAndHashCodeSimple.java @@ -35,7 +35,7 @@ String getA() { return a; } - public boolean equals(Object o) { + public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof EqualsAndHashCodeSimple)) return false; final EqualsAndHashCodeSimple other = (EqualsAndHashCodeSimple) o; @@ -52,6 +52,10 @@ public boolean equals(Object o) { return true; } + protected boolean canEqual(final Object other) { + return other instanceof EqualsAndHashCodeSimple; + } + public int hashCode() { final int PRIME = 59; int result = 1; @@ -66,8 +70,4 @@ public int hashCode() { result = result * PRIME + ($a == null ? 43 : $a.hashCode()); return result; } - - protected boolean canEqual(Object other) { - return other instanceof EqualsAndHashCodeSimple; - } } diff --git a/testData/after/equalsandhashcode/EqualsAndHashCodeExplicitInclude.java b/testData/after/equalsandhashcode/EqualsAndHashCodeExplicitInclude.java new file mode 100644 index 0000000000..5d2c42cc6d --- /dev/null +++ b/testData/after/equalsandhashcode/EqualsAndHashCodeExplicitInclude.java @@ -0,0 +1,22 @@ +class EqualsAndHashCodeExplicitInclude { + int x; + @Override + @SuppressWarnings("all") + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof EqualsAndHashCodeExplicitInclude)) return false; + final EqualsAndHashCodeExplicitInclude other = (EqualsAndHashCodeExplicitInclude) o; + if (!other.canEqual((Object) this)) return false; + return true; + } + @SuppressWarnings("all") + protected boolean canEqual(final Object other) { + return other instanceof EqualsAndHashCodeExplicitInclude; + } + @Override + @SuppressWarnings("all") + public int hashCode() { + int result = 1; + return result; + } +} diff --git a/testData/after/tostring/ToStringExplicitInclude.java b/testData/after/tostring/ToStringExplicitInclude.java new file mode 100644 index 0000000000..7c92b3d570 --- /dev/null +++ b/testData/after/tostring/ToStringExplicitInclude.java @@ -0,0 +1,8 @@ +class ToStringExplicitInclude { + int x; + @Override + @SuppressWarnings("all") + public String toString() { + return "ToStringExplicitInclude()"; + } +} diff --git a/testData/before/equalsandhashcode/EqualsAndHashCodeExplicitInclude.java b/testData/before/equalsandhashcode/EqualsAndHashCodeExplicitInclude.java new file mode 100644 index 0000000000..06b77f14ff --- /dev/null +++ b/testData/before/equalsandhashcode/EqualsAndHashCodeExplicitInclude.java @@ -0,0 +1,4 @@ +@lombok.EqualsAndHashCode(onlyExplicitlyIncluded = true) +class EqualsAndHashCodeExplicitInclude { + int x; +} diff --git a/testData/before/tostring/ToStringExplicitInclude.java b/testData/before/tostring/ToStringExplicitInclude.java new file mode 100644 index 0000000000..31687bc61f --- /dev/null +++ b/testData/before/tostring/ToStringExplicitInclude.java @@ -0,0 +1,4 @@ +@lombok.ToString(onlyExplicitlyIncluded = true) +class ToStringExplicitInclude { + int x; +}