Skip to content

Commit

Permalink
Check for explicit empty "of" and "exclude" annotation values for @to…
Browse files Browse the repository at this point in the history
  • Loading branch information
mplushnikov committed Jan 19, 2017
1 parent 1d8f525 commit 125b247
Show file tree
Hide file tree
Showing 24 changed files with 228 additions and 15 deletions.
Expand Up @@ -141,8 +141,19 @@ private String calcNewPropertyValue(Collection<String> allProperties, String fie
} }


protected Collection<PsiField> filterFields(@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, boolean filterTransient) { protected Collection<PsiField> filterFields(@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, boolean filterTransient) {
final Collection<String> excludeProperty = makeSet(PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "exclude", String.class)); final boolean explicitOf = PsiAnnotationUtil.hasDeclaredProperty(psiAnnotation, "of");
final Collection<String> ofProperty = makeSet(PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "of", String.class)); final boolean explicitExclude = PsiAnnotationUtil.hasDeclaredProperty(psiAnnotation, "exclude");

//Having both exclude and of generates a warning; the exclude parameter will be ignored in that case.
final Collection<String> ofProperty;
final Collection<String> excludeProperty;
if (!explicitOf) {
excludeProperty = makeSet(PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "exclude", String.class));
ofProperty = Collections.emptyList();
} else {
ofProperty = makeSet(PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "of", String.class));
excludeProperty = Collections.emptyList();
}


final Collection<PsiField> psiFields = PsiClassUtil.collectClassFieldsIntern(psiClass); final Collection<PsiField> psiFields = PsiClassUtil.collectClassFieldsIntern(psiClass);


Expand All @@ -153,10 +164,13 @@ protected Collection<PsiField> filterFields(@NotNull PsiClass psiClass, @NotNull
continue; continue;
} }
final String fieldName = classField.getName(); final String fieldName = classField.getName();
if (null == fieldName || excludeProperty.contains(fieldName)) { if (null == fieldName) {
continue;
}
if (explicitExclude && excludeProperty.contains(fieldName)) {
continue; continue;
} }
if (!ofProperty.isEmpty() && !ofProperty.contains(fieldName)) { if (explicitOf && !ofProperty.contains(fieldName)) {
continue; continue;
} }


Expand Down
Expand Up @@ -142,7 +142,7 @@ protected Collection<PsiMethod> createEqualAndHashCode(@NotNull PsiClass psiClas


Collection<PsiMethod> result = new ArrayList<PsiMethod>(3); Collection<PsiMethod> result = new ArrayList<PsiMethod>(3);
result.add(createEqualsMethod(psiClass, psiAnnotation, shouldGenerateCanEqual)); result.add(createEqualsMethod(psiClass, psiAnnotation, shouldGenerateCanEqual));
result.add(createHashCodeMethod(psiClass, psiAnnotation, shouldGenerateCanEqual)); result.add(createHashCodeMethod(psiClass, psiAnnotation));


final Collection<PsiMethod> classMethods = PsiClassUtil.collectClassMethodsIntern(psiClass); final Collection<PsiMethod> classMethods = PsiClassUtil.collectClassMethodsIntern(psiClass);
if (shouldGenerateCanEqual && !PsiMethodUtil.hasMethodByName(classMethods, CAN_EQUAL_METHOD_NAME)) { if (shouldGenerateCanEqual && !PsiMethodUtil.hasMethodByName(classMethods, CAN_EQUAL_METHOD_NAME)) {
Expand Down Expand Up @@ -193,7 +193,7 @@ private PsiCodeBlock createEqualsCodeBlock(@NotNull PsiClass psiClass, @NotNull
} }


@NotNull @NotNull
private PsiMethod createHashCodeMethod(@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, boolean hasCanEqualMethod) { private PsiMethod createHashCodeMethod(@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation) {
final PsiManager psiManager = psiClass.getManager(); final PsiManager psiManager = psiClass.getManager();


return new LombokLightMethodBuilder(psiManager, HASH_CODE_METHOD_NAME) return new LombokLightMethodBuilder(psiManager, HASH_CODE_METHOD_NAME)
Expand Down
Expand Up @@ -72,6 +72,10 @@ public static <T> Collection<T> getAnnotationValues(@NotNull PsiAnnotation psiAn
return result; return result;
} }


public static boolean hasDeclaredProperty(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameter) {
return null != psiAnnotation.findDeclaredAttributeValue(parameter);
}

public static boolean getBooleanAnnotationValue(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameter, boolean defaultValue) { public static boolean getBooleanAnnotationValue(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameter, boolean defaultValue) {
PsiAnnotationMemberValue attrValue = psiAnnotation.findAttributeValue(parameter); PsiAnnotationMemberValue attrValue = psiAnnotation.findAttributeValue(parameter);
final Boolean result = null != attrValue ? resolveElementValue(attrValue, Boolean.class) : null; final Boolean result = null != attrValue ? resolveElementValue(attrValue, Boolean.class) : null;
Expand Down Expand Up @@ -123,9 +127,12 @@ private static <T> T resolveElementValue(@NotNull PsiElement psiElement, @NotNul


@Nullable @Nullable
public static Boolean getDeclaredBooleanAnnotationValue(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameter) { public static Boolean getDeclaredBooleanAnnotationValue(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameter) {
final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(psiAnnotation.getProject());
PsiAnnotationMemberValue attributeValue = psiAnnotation.findDeclaredAttributeValue(parameter); PsiAnnotationMemberValue attributeValue = psiAnnotation.findDeclaredAttributeValue(parameter);
Object constValue = javaPsiFacade.getConstantEvaluationHelper().computeConstantExpression(attributeValue); Object constValue = null;
if (null != attributeValue) {
final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(psiAnnotation.getProject());
constValue = javaPsiFacade.getConstantEvaluationHelper().computeConstantExpression(attributeValue);
}
return constValue instanceof Boolean ? (Boolean) constValue : null; return constValue instanceof Boolean ? (Boolean) constValue : null;
} }


Expand Down
1 change: 1 addition & 0 deletions src/main/resources/META-INF/plugin.xml
Expand Up @@ -264,6 +264,7 @@
<ol> <ol>
<li>Fixed #290: Getter and FieldDefaults with parameter AccessLevel in Enum shows "cannot access"</li> <li>Fixed #290: Getter and FieldDefaults with parameter AccessLevel in Enum shows "cannot access"</li>
<li>Fixed #337: Component name collision: 'UpdateComponent'</li> <li>Fixed #337: Component name collision: 'UpdateComponent'</li>
<li>Fixed #342: @EqualsAndHashCode/@ToString should treat explicit "of = {}" differently</li>
</ol> </ol>
</li> </li>
<li>0.14 <li>0.14
Expand Down
Expand Up @@ -7,15 +7,23 @@
*/ */
public class EqualsAndHashCodeTest extends AbstractLombokParsingTestCase { public class EqualsAndHashCodeTest extends AbstractLombokParsingTestCase {


public void testEqualsAndHashCode() throws Exception { public void testEqualsandhashcode$EqualsAndHashCode() throws Exception {
doTest(); doTest();
} }


public void testEqualsAndHashCodeWithExistingMethods() throws Exception { public void testEqualsandhashcode$EqualsAndHashCodeWithExistingMethods() throws Exception {
doTest(); doTest();
} }


public void testEqualsAndHashCodeWithSomeExistingMethods() throws Exception { public void testEqualsandhashcode$EqualsAndHashCodeWithSomeExistingMethods() throws Exception {
doTest(); doTest();
} }
}
public void testEqualsandhashcode$EqualsAndHashCodeExplicitEmptyOf() throws Exception {
doTest();
}

public void testEqualsandhashcode$EqualsAndHashCodeExplicitOfAndExclude() throws Exception {
doTest();
}
}
Expand Up @@ -9,11 +9,19 @@
*/ */
public class ToStringTest extends AbstractLombokParsingTestCase { public class ToStringTest extends AbstractLombokParsingTestCase {


public void testToStringInner() throws IOException { public void testTostring$ToStringInner() throws IOException {
doTest(); doTest();
} }


public void testToStringPlain() throws IOException { public void testTostring$ToStringPlain() throws IOException {
doTest(); doTest();
} }
}
public void testTostring$ToStringExplicitEmptyOf() throws Exception {
doTest();
}

public void testTostring$ToStringExplicitOfAndExclude() throws Exception {
doTest();
}
}
File renamed without changes.
@@ -0,0 +1,58 @@
class EqualsAndHashCode {
int x;
boolean[] y;
Object[] z;
String a;
String b;

@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCode)) return false;
final EqualsAndHashCode other = (EqualsAndHashCode) o;
if (!other.canEqual((java.lang.Object) this)) return false;
return true;
}

@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof EqualsAndHashCode;
}

@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
int result = 1;
return result;
}
}

final class EqualsAndHashCode2 {
int x;
long y;
float f;
double d;
boolean b;

@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCode2)) return false;
final EqualsAndHashCode2 other = (EqualsAndHashCode2) o;
return true;
}

@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
int result = 1;
return result;
}
}
@@ -0,0 +1,37 @@
class EqualsAndHashCode {
int x;
boolean[] y;
Object[] z;
String a;
String b;

@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCode)) return false;
final EqualsAndHashCode other = (EqualsAndHashCode) o;
if (!other.canEqual((java.lang.Object) this)) return false;
if (this.x != other.x) return false;
if (!java.util.Arrays.deepEquals(this.z, other.z)) return false;
return true;
}

@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof EqualsAndHashCode;
}

@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.x;
result = result * PRIME + java.util.Arrays.deepHashCode(this.z);
return result;
}
}
23 changes: 23 additions & 0 deletions testData/after/tostring/ToStringExplicitEmptyOf.java
@@ -0,0 +1,23 @@
class ToStringExplicitEmptyOf1 {
int x;
String name;

@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public java.lang.String toString() {
return "ToStringExplicitEmptyOf1()";
}
}

class ToStringExplicitEmptyOf2 {
int x;
String name;

@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public java.lang.String toString() {
return "ToStringExplicitEmptyOf2()";
}
}
13 changes: 13 additions & 0 deletions testData/after/tostring/ToStringExplicitOfAndExclude.java
@@ -0,0 +1,13 @@
class ToStringExplicitOfAndExclude {
int x;
float y;
long z;
String name;

@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public java.lang.String toString() {
return "ToStringExplicitOfAndExclude(x=" + this.x + ", z=" + this.z + ")";
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,17 @@
@lombok.EqualsAndHashCode(of={})
class EqualsAndHashCode {
int x;
boolean[] y;
Object[] z;
String a;
String b;
}

@lombok.EqualsAndHashCode(of="")
final class EqualsAndHashCode2 {
int x;
long y;
float f;
double d;
boolean b;
}
@@ -0,0 +1,9 @@
@lombok.EqualsAndHashCode(of = {"x", "z"}, exclude = {"x", "y"})
class EqualsAndHashCode {
int x;
boolean[] y;
Object[] z;
String a;
String b;
}

11 changes: 11 additions & 0 deletions testData/before/tostring/ToStringExplicitEmptyOf.java
@@ -0,0 +1,11 @@
@lombok.ToString(of = {})
class ToStringExplicitEmptyOf1 {
int x;
String name;
}

@lombok.ToString(of = "")
class ToStringExplicitEmptyOf2 {
int x;
String name;
}
7 changes: 7 additions & 0 deletions testData/before/tostring/ToStringExplicitOfAndExclude.java
@@ -0,0 +1,7 @@
@lombok.ToString(of = {"x", "z"}, exclude = "x")
class ToStringExplicitOfAndExclude {
int x;
float y;
long z;
String name;
}
File renamed without changes.
File renamed without changes.

0 comments on commit 125b247

Please sign in to comment.