mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-13 12:15:00 +00:00
[new-style include/exclude] added new-style include/exclude support to EqualsAndHashCode.
This commit is contained in:
1 parent
323cc5267e
commit
649a7b72bf
15 files changed
+383
-225
No files matched your search
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2018 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -37,6 +37,8 @@ public @interface EqualsAndHashCode {
|
||||
/**
|
||||
* Any fields listed here will not be taken into account in the generated {@code equals} and {@code hashCode} implementations.
|
||||
* Mutually exclusive with {@link #of()}.
|
||||
* <p>
|
||||
* Will soon be marked {@code @Deprecated}; use the {@code @EqualsAndHashCode.Exclude} annotation instead.
|
||||
*
|
||||
* @return A list of fields to exclude.
|
||||
*/
|
||||
@@ -47,6 +49,8 @@ public @interface EqualsAndHashCode {
|
||||
* Normally, all non-static, non-transient fields are used for identity.
|
||||
* <p>
|
||||
* Mutually exclusive with {@link #exclude()}.
|
||||
* <p>
|
||||
* Will soon be marked {@code @Deprecated}; use the {@code @EqualsAndHashCode.Include} annotation together with {@code @EqualsAndHashCode(onlyExplicitlyIncluded = true)}.
|
||||
*
|
||||
* @return A list of fields to use (<em>default</em>: all of them).
|
||||
*/
|
||||
@@ -89,4 +93,27 @@ public @interface EqualsAndHashCode {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({})
|
||||
@interface AnyAnnotation {}
|
||||
|
||||
/**
|
||||
* Only include fields and methods explicitly marked with {@code @EqualsAndHashCode.Include}.
|
||||
* Normally, all (non-static, non-transient) fields are included by default.
|
||||
*/
|
||||
boolean onlyExplicitlyIncluded() default false;
|
||||
|
||||
/**
|
||||
* If present, do not include this field in the generated {@code equals} and {@code hashCode} methods.
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Exclude {}
|
||||
|
||||
/**
|
||||
* Configure the behaviour of how this member is treated in the {@code equals} and {@code hashCode} implementation; if on a method, include the method's return value as part of calculating hashCode/equality.
|
||||
*/
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Include {
|
||||
/** Defaults to the method name of the annotated member. If on a method and the name equals the name of a default-included field, this member takes its place. */
|
||||
String replaces() default "";
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2018 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -58,7 +58,7 @@ public @interface ToString {
|
||||
* <p>
|
||||
* Mutually exclusive with {@link #exclude()}.
|
||||
* <p>
|
||||
* Will soon be marked {@code @Deprecated}; use the {@code @ToString.Only} annotation instead.
|
||||
* Will soon be marked {@code @Deprecated}; use the {@code @ToString.Include} annotation together with {@code @ToString(onlyExplicitlyIncluded = true)}.
|
||||
*
|
||||
* @return A list of fields to use (<em>default</em>: all of them).
|
||||
*/
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -159,6 +160,62 @@ public class AnnotationValues<A extends Annotation> {
|
||||
|
||||
private A cachedInstance = null;
|
||||
|
||||
public List<String> getAsStringList(String methodName) {
|
||||
AnnotationValue v = values.get(methodName);
|
||||
|
||||
if (v == null) {
|
||||
String[] s = getDefaultIf(methodName, String[].class, new String[0]);
|
||||
return Collections.unmodifiableList(Arrays.asList(s));
|
||||
}
|
||||
|
||||
List<String> out = new ArrayList<String>(v.valueGuesses.size());
|
||||
int idx = 0;
|
||||
for (Object guess : v.valueGuesses) {
|
||||
Object result = guess == null ? null : guessToType(guess, String.class, v, idx);
|
||||
if (result == null) {
|
||||
if (v.valueGuesses.size() == 1) {
|
||||
String[] s = getDefaultIf(methodName, String[].class, new String[0]);
|
||||
return Collections.unmodifiableList(Arrays.asList(s));
|
||||
}
|
||||
throw new AnnotationValueDecodeFail(v,
|
||||
"I can't make sense of this annotation value. Try using a fully qualified literal.", idx);
|
||||
}
|
||||
out.add((String) result);
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(out);
|
||||
}
|
||||
|
||||
public String getAsString(String methodName) {
|
||||
AnnotationValue v = values.get(methodName);
|
||||
if (v == null || v.valueGuesses.size() != 1) {
|
||||
return getDefaultIf(methodName, String.class, "");
|
||||
}
|
||||
|
||||
Object guess = guessToType(v.valueGuesses.get(0), String.class, v, 0);
|
||||
if (guess instanceof String) return (String) guess;
|
||||
return getDefaultIf(methodName, String.class, "");
|
||||
}
|
||||
|
||||
public boolean getAsBoolean(String methodName) {
|
||||
AnnotationValue v = values.get(methodName);
|
||||
if (v == null || v.valueGuesses.size() != 1) {
|
||||
return getDefaultIf(methodName, Boolean.class, false);
|
||||
}
|
||||
|
||||
Object guess = guessToType(v.valueGuesses.get(0), Boolean.class, v, 0);
|
||||
if (guess instanceof Boolean) return ((Boolean) guess).booleanValue();
|
||||
return getDefaultIf(methodName, Boolean.class, false);
|
||||
}
|
||||
|
||||
public <T> T getDefaultIf(String methodName, Class<T> type, T defaultValue) {
|
||||
try {
|
||||
return type.cast(type.getMethod(methodName).getDefaultValue());
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an actual annotation instance. You can use this to query any annotation methods, except for
|
||||
* those annotation methods with class literals, as those can most likely not be turned into Class objects.
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
*/
|
||||
package lombok.core.handlers;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import lombok.ToString.Include;
|
||||
import lombok.core.AST;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues;
|
||||
@@ -61,23 +61,23 @@ public class InclusionExclusionUtils {
|
||||
public static void checkForBogusFieldNames(LombokNode<?, ?, ?> type, AnnotationValues<?> annotation, List<String> excludes, List<String> includes) {
|
||||
if (excludes != null && !excludes.isEmpty()) {
|
||||
for (int i : createListOfNonExistentFields(excludes, type, true, false)) {
|
||||
annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i);
|
||||
if (annotation != null) annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i);
|
||||
}
|
||||
}
|
||||
|
||||
if (includes != null && !includes.isEmpty()) {
|
||||
for (int i : createListOfNonExistentFields(includes, type, false, false)) {
|
||||
annotation.setWarning("of", "This field does not exist.", i);
|
||||
if (annotation != null) annotation.setWarning("of", "This field does not exist.", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ToStringMember<L> {
|
||||
public static class Included<L, I extends Annotation> {
|
||||
private final L node;
|
||||
private final ToString.Include inc;
|
||||
private final I inc;
|
||||
private final boolean defaultInclude;
|
||||
|
||||
public ToStringMember(L node, ToString.Include inc, boolean defaultInclude) {
|
||||
public Included(L node, I inc, boolean defaultInclude) {
|
||||
this.node = node;
|
||||
this.inc = inc;
|
||||
this.defaultInclude = defaultInclude;
|
||||
@@ -87,7 +87,7 @@ public class InclusionExclusionUtils {
|
||||
return node;
|
||||
}
|
||||
|
||||
public ToString.Include getInc() {
|
||||
public I getInc() {
|
||||
return inc;
|
||||
}
|
||||
|
||||
@@ -96,34 +96,45 @@ public class InclusionExclusionUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static <A extends AST<A, L, N>, L extends LombokNode<A, L, N>, N> List<ToStringMember<L>> handleToStringMarking(LombokNode<A, L, N> typeNode, AnnotationValues<ToString> annotation, LombokNode<A, L, N> annotationNode) {
|
||||
ToString ann = annotation == null ? null : annotation.getInstance();
|
||||
List<String> oldExcludes = (ann != null && annotation.isExplicit("exclude")) ? Arrays.asList(ann.exclude()) : null;
|
||||
List<String> oldIncludes = (ann != null && annotation.isExplicit("of")) ? Arrays.asList(ann.of()) : null;
|
||||
private static String innerAnnName(Class<? extends Annotation> type) {
|
||||
String name = type.getSimpleName();
|
||||
Class<?> c = type.getEnclosingClass();
|
||||
while (c != null) {
|
||||
name = c.getSimpleName() + "." + name;
|
||||
c = c.getEnclosingClass();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static <A extends AST<A, L, N>, L extends LombokNode<A, L, N>, N, I extends Annotation> List<Included<L, I>> handleIncludeExcludeMarking(Class<I> inclType, String replaceName, Class<? extends Annotation> exclType, LombokNode<A, L, N> typeNode, AnnotationValues<?> annotation, LombokNode<A, L, N> annotationNode) {
|
||||
List<String> oldExcludes = (annotation != null && annotation.isExplicit("exclude")) ? annotation.getAsStringList("exclude") : null;
|
||||
List<String> oldIncludes = (annotation != null && annotation.isExplicit("of")) ? annotation.getAsStringList("of") : null;
|
||||
|
||||
boolean onlyExplicitlyIncluded = ann != null && ann.onlyExplicitlyIncluded();
|
||||
boolean onlyExplicitlyIncluded = annotation != null ? annotation.getAsBoolean("onlyExplicitlyIncluded") : false;
|
||||
boolean memberAnnotationMode = onlyExplicitlyIncluded;
|
||||
List<ToStringMember<L>> members = new ArrayList<ToStringMember<L>>();
|
||||
List<Included<L, I>> members = new ArrayList<Included<L, I>>();
|
||||
List<String> namesToAutoExclude = new ArrayList<String>();
|
||||
|
||||
if (typeNode == null || typeNode.getKind() != Kind.TYPE) return null;
|
||||
|
||||
checkForBogusFieldNames(typeNode, annotation, oldExcludes, oldIncludes);
|
||||
String inclTypeName = innerAnnName(inclType);
|
||||
String exclTypeName = innerAnnName(exclType);
|
||||
|
||||
if (oldExcludes != null && oldIncludes != null) {
|
||||
oldExcludes = null;
|
||||
annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored.");
|
||||
if (annotation != null) annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored.");
|
||||
}
|
||||
|
||||
for (L child : typeNode.down()) {
|
||||
boolean markExclude = child.getKind() == Kind.FIELD && child.hasAnnotation(ToString.Exclude.class);
|
||||
AnnotationValues<ToString.Include> markInclude = null;
|
||||
if (child.getKind() == Kind.FIELD || child.getKind() == Kind.METHOD) markInclude = child.findAnnotation(ToString.Include.class);
|
||||
boolean markExclude = child.getKind() == Kind.FIELD && child.hasAnnotation(exclType);
|
||||
AnnotationValues<I> markInclude = null;
|
||||
if (child.getKind() == Kind.FIELD || child.getKind() == Kind.METHOD) markInclude = child.findAnnotation(inclType);
|
||||
|
||||
if (markExclude || markInclude != null) memberAnnotationMode = true;
|
||||
|
||||
if (markInclude != null && markExclude) {
|
||||
child.addError("@ToString.Exclude and @ToString.Include are mutually exclusive; the @Include annotation will be ignored");
|
||||
child.addError("@" + exclTypeName + " and @" + inclTypeName + " are mutually exclusive; the @Include annotation will be ignored");
|
||||
markInclude = null;
|
||||
}
|
||||
|
||||
@@ -143,36 +154,36 @@ public class InclusionExclusionUtils {
|
||||
if (oldExcludes != null && oldExcludes.contains(name)) continue;
|
||||
|
||||
if (markInclude != null) {
|
||||
Include inc = markInclude.getInstance();
|
||||
I inc = markInclude.getInstance();
|
||||
if (child.getKind() == Kind.METHOD) {
|
||||
if (child.countMethodParameters() > 0) {
|
||||
child.addError("Methods included for @ToString must have no arguments; it will not be included");
|
||||
child.addError("Methods included with @" + inclTypeName + " must have no arguments; it will not be included");
|
||||
continue;
|
||||
}
|
||||
String n = inc.name();
|
||||
String n = replaceName != null ? markInclude.getAsString(replaceName) : "";
|
||||
if (n.isEmpty()) n = name;
|
||||
namesToAutoExclude.add(n);
|
||||
}
|
||||
members.add(new ToStringMember<L>(child, inc, false));
|
||||
members.add(new Included<L, I>(child, inc, false));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (onlyExplicitlyIncluded) continue;
|
||||
if (oldIncludes != null) {
|
||||
if (child.getKind() == Kind.FIELD && oldIncludes.contains(name)) members.add(new ToStringMember<L>(child, null, false));
|
||||
if (child.getKind() == Kind.FIELD && oldIncludes.contains(name)) members.add(new Included<L, I>(child, null, false));
|
||||
continue;
|
||||
}
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
if (child.isStatic()) continue;
|
||||
if (name.startsWith("$")) continue;
|
||||
if (child.isEnumMember()) continue;
|
||||
members.add(new ToStringMember<L>(child, null, true));
|
||||
members.add(new Included<L, I>(child, null, true));
|
||||
}
|
||||
|
||||
/* delete default-included fields with the same name as an explicit inclusion */ {
|
||||
Iterator<ToStringMember<L>> it = members.iterator();
|
||||
Iterator<Included<L, I>> it = members.iterator();
|
||||
while (it.hasNext()) {
|
||||
ToStringMember<L> m = it.next();
|
||||
Included<L, I> m = it.next();
|
||||
if (m.isDefaultInclude() && namesToAutoExclude.contains(m.getNode().getName())) it.remove();
|
||||
}
|
||||
}
|
||||
@@ -185,8 +196,14 @@ public class InclusionExclusionUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
Collections.sort(members, new Comparator<ToStringMember<L>>() {
|
||||
@Override public int compare(ToStringMember<L> a, ToStringMember<L> b) {
|
||||
return members;
|
||||
}
|
||||
|
||||
public static <A extends AST<A, L, N>, L extends LombokNode<A, L, N>, N> List<Included<L, ToString.Include>> handleToStringMarking(LombokNode<A, L, N> typeNode, AnnotationValues<ToString> annotation, LombokNode<A, L, N> annotationNode) {
|
||||
List<Included<L, ToString.Include>> members = handleIncludeExcludeMarking(ToString.Include.class, "name", ToString.Exclude.class, typeNode, annotation, annotationNode);
|
||||
|
||||
Collections.sort(members, new Comparator<Included<L, ToString.Include>>() {
|
||||
@Override public int compare(Included<L, ToString.Include> a, Included<L, ToString.Include> b) {
|
||||
int ra = a.getInc() == null ? 0 : a.getInc().rank();
|
||||
int rb = b.getInc() == null ? 0 : b.getInc().rank();
|
||||
if (ra < rb) return +1;
|
||||
@@ -203,4 +220,8 @@ public class InclusionExclusionUtils {
|
||||
});
|
||||
return members;
|
||||
}
|
||||
|
||||
public static <A extends AST<A, L, N>, L extends LombokNode<A, L, N>, N> List<Included<L, EqualsAndHashCode.Include>> handleEqualsAndHashCodeMarking(LombokNode<A, L, N> typeNode, AnnotationValues<EqualsAndHashCode> annotation, LombokNode<A, L, N> annotationNode) {
|
||||
return handleIncludeExcludeMarking(EqualsAndHashCode.Include.class, "replaces", EqualsAndHashCode.Exclude.class, typeNode, annotation, annotationNode);
|
||||
}
|
||||
}
|
||||
@@ -1041,6 +1041,20 @@ public class EclipseHandlerUtil {
|
||||
return call;
|
||||
}
|
||||
|
||||
static Expression createMethodAccessor(EclipseNode method, ASTNode source, char[] receiver) {
|
||||
int pS = source == null ? 0 : source.sourceStart, pE = source == null ? 0 : source.sourceEnd;
|
||||
long p = (long) pS << 32 | pE;
|
||||
|
||||
MethodDeclaration methodDecl = (MethodDeclaration) method.get();
|
||||
MessageSend call = new MessageSend();
|
||||
setGeneratedBy(call, source);
|
||||
call.sourceStart = pS; call.statementEnd = call.sourceEnd = pE;
|
||||
call.receiver = new SingleNameReference(receiver, p);
|
||||
setGeneratedBy(call.receiver, source);
|
||||
call.selector = methodDecl.selector;
|
||||
return call;
|
||||
}
|
||||
|
||||
/** Serves as return value for the methods that check for the existence of fields and methods. */
|
||||
public enum MemberExistsResult {
|
||||
NOT_EXISTS, EXISTS_BY_LOMBOK, EXISTS_BY_USER;
|
||||
|
||||
@@ -74,9 +74,10 @@ import lombok.Builder;
|
||||
import lombok.Builder.ObtainVia;
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.Singular;
|
||||
import lombok.ToString;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.handlers.HandlerUtil;
|
||||
import lombok.core.handlers.InclusionExclusionUtils.ToStringMember;
|
||||
import lombok.core.handlers.InclusionExclusionUtils.Included;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.HandlerPriority;
|
||||
import lombok.eclipse.Eclipse;
|
||||
@@ -450,10 +451,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
|
||||
if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
|
||||
List<ToStringMember<EclipseNode>> fieldNodes = new ArrayList<ToStringMember<EclipseNode>>();
|
||||
List<Included<EclipseNode, ToString.Include>> fieldNodes = new ArrayList<Included<EclipseNode, ToString.Include>>();
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
for (EclipseNode f : bfd.createdFields) {
|
||||
fieldNodes.add(new ToStringMember<EclipseNode>(f, null, true));
|
||||
fieldNodes.add(new Included<EclipseNode, ToString.Include>(f, null, true));
|
||||
}
|
||||
}
|
||||
MethodDeclaration md = HandleToString.createToString(builderType, fieldNodes, true, false, ast, FieldAccess.ALWAYS_FIELD);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2015 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2018 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -38,6 +38,8 @@ import lombok.ConfigurationKeys;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.handlers.HandlerUtil;
|
||||
import lombok.core.handlers.InclusionExclusionUtils;
|
||||
import lombok.core.handlers.InclusionExclusionUtils.Included;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.configuration.CallSuperType;
|
||||
import lombok.eclipse.Eclipse;
|
||||
@@ -56,7 +58,6 @@ import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Expression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
|
||||
@@ -98,17 +99,23 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
public static final Set<String> BUILT_IN_TYPES = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
|
||||
"byte", "short", "int", "long", "char", "boolean", "double", "float")));
|
||||
|
||||
public void checkForBogusFieldNames(EclipseNode type, AnnotationValues<EqualsAndHashCode> annotation) {
|
||||
if (annotation.isExplicit("exclude")) {
|
||||
for (int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().exclude()), type, true, true)) {
|
||||
annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i);
|
||||
}
|
||||
}
|
||||
if (annotation.isExplicit("of")) {
|
||||
for (int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().of()), type, false, false)) {
|
||||
annotation.setWarning("of", "This field does not exist.", i);
|
||||
}
|
||||
}
|
||||
@Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
handleFlagUsage(annotationNode, ConfigurationKeys.EQUALS_AND_HASH_CODE_FLAG_USAGE, "@EqualsAndHashCode");
|
||||
|
||||
EqualsAndHashCode ann = annotation.getInstance();
|
||||
List<Included<EclipseNode, EqualsAndHashCode.Include>> members = InclusionExclusionUtils.handleEqualsAndHashCodeMarking(annotationNode.up(), annotation, annotationNode);
|
||||
if (members == null) return;
|
||||
|
||||
List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam", annotationNode);
|
||||
|
||||
Boolean callSuper = ann.callSuper();
|
||||
if (!annotation.isExplicit("callSuper")) callSuper = null;
|
||||
|
||||
Boolean doNotUseGettersConfiguration = annotationNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
|
||||
boolean doNotUseGetters = annotation.isExplicit("doNotUseGetters") || doNotUseGettersConfiguration == null ? ann.doNotUseGetters() : doNotUseGettersConfiguration;
|
||||
FieldAccess fieldAccess = doNotUseGetters ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
|
||||
|
||||
generateMethods(annotationNode.up(), annotationNode, members, callSuper, true, fieldAccess, onParam);
|
||||
}
|
||||
|
||||
public void generateEqualsAndHashCodeForType(EclipseNode typeNode, EclipseNode errorNode) {
|
||||
@@ -117,43 +124,16 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
return;
|
||||
}
|
||||
|
||||
List<Included<EclipseNode, EqualsAndHashCode.Include>> members = InclusionExclusionUtils.handleEqualsAndHashCodeMarking(typeNode, null, null);
|
||||
|
||||
Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
|
||||
FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
|
||||
|
||||
generateMethods(typeNode, errorNode, null, null, null, false, access, new ArrayList<Annotation>());
|
||||
generateMethods(typeNode, errorNode, members, null, false, access, new ArrayList<Annotation>());
|
||||
}
|
||||
|
||||
@Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
handleFlagUsage(annotationNode, ConfigurationKeys.EQUALS_AND_HASH_CODE_FLAG_USAGE, "@EqualsAndHashCode");
|
||||
|
||||
EqualsAndHashCode ann = annotation.getInstance();
|
||||
List<String> excludes = Arrays.asList(ann.exclude());
|
||||
List<String> includes = Arrays.asList(ann.of());
|
||||
EclipseNode typeNode = annotationNode.up();
|
||||
|
||||
List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam", annotationNode);
|
||||
checkForBogusFieldNames(typeNode, annotation);
|
||||
|
||||
Boolean callSuper = ann.callSuper();
|
||||
if (!annotation.isExplicit("callSuper")) callSuper = null;
|
||||
if (!annotation.isExplicit("exclude")) excludes = null;
|
||||
if (!annotation.isExplicit("of")) includes = null;
|
||||
|
||||
if (excludes != null && includes != null) {
|
||||
excludes = null;
|
||||
annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored.");
|
||||
}
|
||||
|
||||
Boolean doNotUseGettersConfiguration = annotationNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
|
||||
boolean doNotUseGetters = annotation.isExplicit("doNotUseGetters") || doNotUseGettersConfiguration == null ? ann.doNotUseGetters() : doNotUseGettersConfiguration;
|
||||
FieldAccess fieldAccess = doNotUseGetters ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
|
||||
|
||||
generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true, fieldAccess, onParam);
|
||||
}
|
||||
|
||||
public void generateMethods(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes, List<String> includes,
|
||||
Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List<Annotation> onParam) {
|
||||
assert excludes == null || includes == null;
|
||||
public void generateMethods(EclipseNode typeNode, EclipseNode errorNode, List<Included<EclipseNode, EqualsAndHashCode.Include>> members,
|
||||
Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List<Annotation> onParam) {
|
||||
|
||||
TypeDeclaration typeDecl = null;
|
||||
|
||||
@@ -171,7 +151,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
|
||||
if (callSuper == null) {
|
||||
try {
|
||||
callSuper = ((Boolean)EqualsAndHashCode.class.getMethod("callSuper").getDefaultValue()).booleanValue();
|
||||
callSuper = ((Boolean) EqualsAndHashCode.class.getMethod("callSuper").getDefaultValue()).booleanValue();
|
||||
} catch (Exception ignore) {
|
||||
throw new InternalError("Lombok bug - this cannot happen - can't find callSuper field in EqualsAndHashCode annotation.");
|
||||
}
|
||||
@@ -208,27 +188,6 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
}
|
||||
}
|
||||
|
||||
List<EclipseNode> nodesForEquality = new ArrayList<EclipseNode>();
|
||||
if (includes != null) {
|
||||
for (EclipseNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
|
||||
if (includes.contains(new String(fieldDecl.name))) nodesForEquality.add(child);
|
||||
}
|
||||
} else {
|
||||
for (EclipseNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
|
||||
if (!filterField(fieldDecl)) continue;
|
||||
|
||||
//Skip transient fields.
|
||||
if ((fieldDecl.modifiers & ClassFileConstants.AccTransient) != 0) continue;
|
||||
//Skip excluded fields.
|
||||
if (excludes != null && excludes.contains(new String(fieldDecl.name))) continue;
|
||||
nodesForEquality.add(child);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isFinal = (typeDecl.modifiers & ClassFileConstants.AccFinal) != 0;
|
||||
boolean needsCanEqual = !isFinal || !isDirectDescendantOfObject;
|
||||
MemberExistsResult equalsExists = methodExists("equals", typeNode, 1);
|
||||
@@ -257,7 +216,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
//fallthrough
|
||||
}
|
||||
|
||||
MethodDeclaration equalsMethod = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get(), fieldAccess, needsCanEqual, onParam);
|
||||
MethodDeclaration equalsMethod = createEquals(typeNode, members, callSuper, errorNode.get(), fieldAccess, needsCanEqual, onParam);
|
||||
equalsMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
|
||||
injectMethod(typeNode, equalsMethod);
|
||||
|
||||
@@ -267,17 +226,16 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
injectMethod(typeNode, canEqualMethod);
|
||||
}
|
||||
|
||||
MethodDeclaration hashCodeMethod = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get(), fieldAccess);
|
||||
MethodDeclaration hashCodeMethod = createHashCode(typeNode, members, callSuper, errorNode.get(), fieldAccess);
|
||||
hashCodeMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
|
||||
injectMethod(typeNode, hashCodeMethod);
|
||||
}
|
||||
|
||||
public MethodDeclaration createHashCode(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, FieldAccess fieldAccess) {
|
||||
public MethodDeclaration createHashCode(EclipseNode type, Collection<Included<EclipseNode, EqualsAndHashCode.Include>> members, boolean callSuper, ASTNode source, FieldAccess fieldAccess) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
|
||||
MethodDeclaration method = new MethodDeclaration(
|
||||
((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
MethodDeclaration method = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
setGeneratedBy(method, source);
|
||||
|
||||
method.modifiers = toEclipseModifier(AccessLevel.PUBLIC);
|
||||
@@ -294,10 +252,10 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
|
||||
List<Statement> statements = new ArrayList<Statement>();
|
||||
|
||||
final boolean isEmpty = fields.isEmpty();
|
||||
final boolean isEmpty = members.isEmpty();
|
||||
|
||||
/* final int PRIME = X; */ {
|
||||
/* Without fields, PRIME isn't used, and that would trigger a 'local variable not used' warning. */
|
||||
/* Without members, PRIME isn't used, as that would trigger a 'local variable not used' warning. */
|
||||
if (!isEmpty) {
|
||||
LocalDeclaration primeDecl = new LocalDeclaration(PRIME, pS, pE);
|
||||
setGeneratedBy(primeDecl, source);
|
||||
@@ -310,7 +268,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
}
|
||||
}
|
||||
|
||||
/*int result = ... */{
|
||||
/* int result = ... */ {
|
||||
LocalDeclaration resultDecl = new LocalDeclaration(RESULT, pS, pE);
|
||||
setGeneratedBy(resultDecl, source);
|
||||
final Expression init;
|
||||
@@ -334,11 +292,14 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
statements.add(resultDecl);
|
||||
}
|
||||
|
||||
for (EclipseNode field : fields) {
|
||||
TypeReference fType = getFieldType(field, fieldAccess);
|
||||
char[] dollarFieldName = ("$" + field.getName()).toCharArray();
|
||||
for (Included<EclipseNode, EqualsAndHashCode.Include> member : members) {
|
||||
EclipseNode memberNode = member.getNode();
|
||||
boolean isMethod = memberNode.getKind() == Kind.METHOD;
|
||||
|
||||
TypeReference fType = getFieldType(memberNode, fieldAccess);
|
||||
char[] dollarFieldName = ((isMethod ? "$$" : "$") + memberNode.getName()).toCharArray();
|
||||
char[] token = fType.getLastToken();
|
||||
Expression fieldAccessor = createFieldAccessor(field, fieldAccess, source);
|
||||
Expression fieldAccessor = isMethod ? createMethodAccessor(memberNode, source) : createFieldAccessor(memberNode, fieldAccess, source);
|
||||
if (fType.dimensions() == 0 && token != null) {
|
||||
if (Arrays.equals(TypeConstants.BOOLEAN, token)) {
|
||||
/* booleanField ? X : Y */
|
||||
@@ -534,12 +495,11 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
return arr == null ? 0 : arr.length;
|
||||
}
|
||||
|
||||
public MethodDeclaration createEquals(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, FieldAccess fieldAccess, boolean needsCanEqual, List<Annotation> onParam) {
|
||||
public MethodDeclaration createEquals(EclipseNode type, Collection<Included<EclipseNode, EqualsAndHashCode.Include>> members, boolean callSuper, ASTNode source, FieldAccess fieldAccess, boolean needsCanEqual, List<Annotation> onParam) {
|
||||
int pS = source.sourceStart; int pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
|
||||
MethodDeclaration method = new MethodDeclaration(
|
||||
((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
MethodDeclaration method = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
setGeneratedBy(method, source);
|
||||
method.modifiers = toEclipseModifier(AccessLevel.PUBLIC);
|
||||
method.returnType = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
|
||||
@@ -606,7 +566,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
char[] otherName = "other".toCharArray();
|
||||
|
||||
/* Outer.Inner.MyType<?> other = (Outer.Inner.MyType<?>) o; */ {
|
||||
if (!fields.isEmpty() || needsCanEqual) {
|
||||
if (!members.isEmpty() || needsCanEqual) {
|
||||
LocalDeclaration other = new LocalDeclaration(otherName, pS, pE);
|
||||
other.modifiers |= ClassFileConstants.AccFinal;
|
||||
setGeneratedBy(other, source);
|
||||
@@ -675,11 +635,14 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
statements.add(ifSuperEquals);
|
||||
}
|
||||
|
||||
for (EclipseNode field : fields) {
|
||||
TypeReference fType = getFieldType(field, fieldAccess);
|
||||
for (Included<EclipseNode, EqualsAndHashCode.Include> member : members) {
|
||||
EclipseNode memberNode = member.getNode();
|
||||
boolean isMethod = memberNode.getKind() == Kind.METHOD;
|
||||
|
||||
TypeReference fType = getFieldType(memberNode, fieldAccess);
|
||||
char[] token = fType.getLastToken();
|
||||
Expression thisFieldAccessor = createFieldAccessor(field, fieldAccess, source);
|
||||
Expression otherFieldAccessor = createFieldAccessor(field, fieldAccess, source, otherName);
|
||||
Expression thisFieldAccessor = isMethod ? createMethodAccessor(memberNode, source) : createFieldAccessor(memberNode, fieldAccess, source);
|
||||
Expression otherFieldAccessor = isMethod ? createMethodAccessor(memberNode, source, otherName) : createFieldAccessor(memberNode, fieldAccess, source, otherName);
|
||||
|
||||
if (fType.dimensions() == 0 && token != null) {
|
||||
if (Arrays.equals(TypeConstants.FLOAT, token)) {
|
||||
@@ -700,8 +663,8 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
/* final java.lang.Object this$fieldName = this.fieldName; */
|
||||
/* final java.lang.Object other$fieldName = other.fieldName; */
|
||||
/* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false; */
|
||||
char[] thisDollarFieldName = ("this$" + field.getName()).toCharArray();
|
||||
char[] otherDollarFieldName = ("other$" + field.getName()).toCharArray();
|
||||
char[] thisDollarFieldName = ("this" + (isMethod ? "$$" : "$") + memberNode.getName()).toCharArray();
|
||||
char[] otherDollarFieldName = ("other" + (isMethod ? "$$" : "$") + memberNode.getName()).toCharArray();
|
||||
|
||||
statements.add(createLocalDeclaration(source, thisDollarFieldName, generateQualifiedTypeRef(source, TypeConstants.JAVA_LANG_OBJECT), thisFieldAccessor));
|
||||
statements.add(createLocalDeclaration(source, otherDollarFieldName, generateQualifiedTypeRef(source, TypeConstants.JAVA_LANG_OBJECT), otherFieldAccessor));
|
||||
@@ -714,7 +677,6 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
setGeneratedBy(other1, source);
|
||||
SingleNameReference other2 = new SingleNameReference(otherDollarFieldName, p);
|
||||
setGeneratedBy(other2, source);
|
||||
|
||||
|
||||
NullLiteral nullLiteral = new NullLiteral(pS, pE);
|
||||
setGeneratedBy(nullLiteral, source);
|
||||
@@ -777,7 +739,6 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
public MethodDeclaration createCanEqual(EclipseNode type, ASTNode source, List<Annotation> onParam) {
|
||||
/* protected boolean canEqual(final java.lang.Object other) {
|
||||
* return other instanceof Outer.Inner.MyType;
|
||||
@@ -788,8 +749,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
|
||||
char[] otherName = "other".toCharArray();
|
||||
|
||||
MethodDeclaration method = new MethodDeclaration(
|
||||
((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
MethodDeclaration method = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
setGeneratedBy(method, source);
|
||||
method.modifiers = toEclipseModifier(AccessLevel.PROTECTED);
|
||||
method.returnType = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
|
||||
|
||||
@@ -37,7 +37,7 @@ import lombok.ToString;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.handlers.InclusionExclusionUtils;
|
||||
import lombok.core.handlers.InclusionExclusionUtils.ToStringMember;
|
||||
import lombok.core.handlers.InclusionExclusionUtils.Included;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
@@ -73,7 +73,7 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
|
||||
handleFlagUsage(annotationNode, ConfigurationKeys.TO_STRING_FLAG_USAGE, "@ToString");
|
||||
|
||||
ToString ann = annotation.getInstance();
|
||||
List<ToStringMember<EclipseNode>> members = InclusionExclusionUtils.handleToStringMarking(annotationNode.up(), annotation, annotationNode);
|
||||
List<Included<EclipseNode, ToString.Include>> members = InclusionExclusionUtils.handleToStringMarking(annotationNode.up(), annotation, annotationNode);
|
||||
if (members == null) return;
|
||||
|
||||
Boolean callSuper = ann.callSuper();
|
||||
@@ -105,11 +105,11 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
|
||||
Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
|
||||
FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
|
||||
|
||||
List<ToStringMember<EclipseNode>> members = InclusionExclusionUtils.handleToStringMarking(typeNode, null, null);
|
||||
List<Included<EclipseNode, ToString.Include>> members = InclusionExclusionUtils.handleToStringMarking(typeNode, null, null);
|
||||
generateToString(typeNode, errorNode, members, includeFieldNames, null, false, access);
|
||||
}
|
||||
|
||||
public void generateToString(EclipseNode typeNode, EclipseNode errorNode, List<ToStringMember<EclipseNode>> members,
|
||||
public void generateToString(EclipseNode typeNode, EclipseNode errorNode, List<Included<EclipseNode, ToString.Include>> members,
|
||||
boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) {
|
||||
|
||||
TypeDeclaration typeDecl = null;
|
||||
@@ -145,7 +145,7 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
|
||||
}
|
||||
}
|
||||
|
||||
public static MethodDeclaration createToString(EclipseNode type, Collection<ToStringMember<EclipseNode>> members,
|
||||
public static MethodDeclaration createToString(EclipseNode type, Collection<Included<EclipseNode, ToString.Include>> members,
|
||||
boolean includeNames, boolean callSuper, ASTNode source, FieldAccess fieldAccess) {
|
||||
|
||||
String typeName = getTypeName(type);
|
||||
@@ -163,7 +163,7 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
|
||||
} else if (members.isEmpty()) {
|
||||
prefix = (typeName + "()").toCharArray();
|
||||
} else if (includeNames) {
|
||||
ToStringMember<EclipseNode> firstMember = members.iterator().next();
|
||||
Included<EclipseNode, ToString.Include> firstMember = members.iterator().next();
|
||||
String name = firstMember.getInc() == null ? "" : firstMember.getInc().name();
|
||||
if (name.isEmpty()) name = firstMember.getNode().getName();
|
||||
prefix = (typeName + "(" + name + "=").toCharArray();
|
||||
@@ -187,7 +187,7 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
|
||||
first = false;
|
||||
}
|
||||
|
||||
for (ToStringMember<EclipseNode> member : members) {
|
||||
for (Included<EclipseNode, ToString.Include> member : members) {
|
||||
EclipseNode memberNode = member.getNode();
|
||||
|
||||
TypeReference fieldType = getFieldType(memberNode, fieldAccess);
|
||||
|
||||
@@ -54,11 +54,12 @@ import lombok.Builder;
|
||||
import lombok.Builder.ObtainVia;
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.Singular;
|
||||
import lombok.ToString;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.HandlerPriority;
|
||||
import lombok.core.handlers.HandlerUtil;
|
||||
import lombok.core.handlers.InclusionExclusionUtils.ToStringMember;
|
||||
import lombok.core.handlers.InclusionExclusionUtils.Included;
|
||||
import lombok.experimental.NonFinal;
|
||||
import lombok.javac.Javac;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
@@ -399,10 +400,10 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
}
|
||||
|
||||
if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
|
||||
java.util.List<ToStringMember<JavacNode>> fieldNodes = new ArrayList<ToStringMember<JavacNode>>();
|
||||
java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>();
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
for (JavacNode f : bfd.createdFields) {
|
||||
fieldNodes.add(new ToStringMember<JavacNode>(f, null, true));
|
||||
fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2018 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -35,6 +35,8 @@ import lombok.core.AST.Kind;
|
||||
import lombok.core.configuration.CallSuperType;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.handlers.HandlerUtil;
|
||||
import lombok.core.handlers.InclusionExclusionUtils;
|
||||
import lombok.core.handlers.InclusionExclusionUtils.Included;
|
||||
import lombok.javac.Javac;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacNode;
|
||||
@@ -73,45 +75,23 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
private static final String RESULT_NAME = "result";
|
||||
private static final String PRIME_NAME = "PRIME";
|
||||
|
||||
public void checkForBogusFieldNames(JavacNode type, AnnotationValues<EqualsAndHashCode> annotation) {
|
||||
if (annotation.isExplicit("exclude")) {
|
||||
for (int i : createListOfNonExistentFields(List.from(annotation.getInstance().exclude()), type, true, true)) {
|
||||
annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i);
|
||||
}
|
||||
}
|
||||
if (annotation.isExplicit("of")) {
|
||||
for (int i : createListOfNonExistentFields(List.from(annotation.getInstance().of()), type, false, false)) {
|
||||
annotation.setWarning("of", "This field does not exist.", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
handleFlagUsage(annotationNode, ConfigurationKeys.EQUALS_AND_HASH_CODE_FLAG_USAGE, "@EqualsAndHashCode");
|
||||
|
||||
deleteAnnotationIfNeccessary(annotationNode, EqualsAndHashCode.class);
|
||||
EqualsAndHashCode ann = annotation.getInstance();
|
||||
List<String> excludes = List.from(ann.exclude());
|
||||
List<String> includes = List.from(ann.of());
|
||||
java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members = InclusionExclusionUtils.handleEqualsAndHashCodeMarking(annotationNode.up(), annotation, annotationNode);
|
||||
JavacNode typeNode = annotationNode.up();
|
||||
List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam", annotationNode);
|
||||
checkForBogusFieldNames(typeNode, annotation);
|
||||
|
||||
Boolean callSuper = ann.callSuper();
|
||||
if (!annotation.isExplicit("callSuper")) callSuper = null;
|
||||
if (!annotation.isExplicit("exclude")) excludes = null;
|
||||
if (!annotation.isExplicit("of")) includes = null;
|
||||
|
||||
if (excludes != null && includes != null) {
|
||||
excludes = null;
|
||||
annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored.");
|
||||
}
|
||||
|
||||
Boolean doNotUseGettersConfiguration = annotationNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
|
||||
boolean doNotUseGetters = annotation.isExplicit("doNotUseGetters") || doNotUseGettersConfiguration == null ? ann.doNotUseGetters() : doNotUseGettersConfiguration;
|
||||
FieldAccess fieldAccess = doNotUseGetters ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
|
||||
|
||||
generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true, fieldAccess, onParam);
|
||||
generateMethods(typeNode, annotationNode, members, callSuper, true, fieldAccess, onParam);
|
||||
}
|
||||
|
||||
public void generateEqualsAndHashCodeForType(JavacNode typeNode, JavacNode source) {
|
||||
@@ -123,10 +103,12 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
|
||||
FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
|
||||
|
||||
generateMethods(typeNode, source, null, null, null, false, access, List.<JCAnnotation>nil());
|
||||
java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members = InclusionExclusionUtils.handleEqualsAndHashCodeMarking(typeNode, null, null);
|
||||
|
||||
generateMethods(typeNode, source, members, null, false, access, List.<JCAnnotation>nil());
|
||||
}
|
||||
|
||||
public void generateMethods(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes,
|
||||
public void generateMethods(JavacNode typeNode, JavacNode source, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members,
|
||||
Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List<JCAnnotation> onParam) {
|
||||
|
||||
boolean notAClass = true;
|
||||
@@ -180,29 +162,6 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
}
|
||||
}
|
||||
|
||||
ListBuffer<JavacNode> nodesForEquality = new ListBuffer<JavacNode>();
|
||||
if (includes != null) {
|
||||
for (JavacNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) child.get();
|
||||
if (includes.contains(fieldDecl.name.toString())) nodesForEquality.append(child);
|
||||
}
|
||||
} else {
|
||||
for (JavacNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) child.get();
|
||||
//Skip static fields.
|
||||
if ((fieldDecl.mods.flags & Flags.STATIC) != 0) continue;
|
||||
//Skip transient fields.
|
||||
if ((fieldDecl.mods.flags & Flags.TRANSIENT) != 0) continue;
|
||||
//Skip excluded fields.
|
||||
if (excludes != null && excludes.contains(fieldDecl.name.toString())) continue;
|
||||
//Skip fields that start with $
|
||||
if (fieldDecl.name.toString().startsWith("$")) continue;
|
||||
nodesForEquality.append(child);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isFinal = (((JCClassDecl) typeNode.get()).mods.flags & Flags.FINAL) != 0;
|
||||
boolean needsCanEqual = !isFinal || !isDirectDescendantOfObject;
|
||||
MemberExistsResult equalsExists = methodExists("equals", typeNode, 1);
|
||||
@@ -231,7 +190,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
//fallthrough
|
||||
}
|
||||
|
||||
JCMethodDecl equalsMethod = createEquals(typeNode, nodesForEquality.toList(), callSuper, fieldAccess, needsCanEqual, source.get(), onParam);
|
||||
JCMethodDecl equalsMethod = createEquals(typeNode, members, callSuper, fieldAccess, needsCanEqual, source.get(), onParam);
|
||||
|
||||
injectMethod(typeNode, equalsMethod);
|
||||
|
||||
@@ -240,11 +199,11 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
injectMethod(typeNode, canEqualMethod);
|
||||
}
|
||||
|
||||
JCMethodDecl hashCodeMethod = createHashCode(typeNode, nodesForEquality.toList(), callSuper, fieldAccess, source.get());
|
||||
JCMethodDecl hashCodeMethod = createHashCode(typeNode, members, callSuper, fieldAccess, source.get());
|
||||
injectMethod(typeNode, hashCodeMethod);
|
||||
}
|
||||
|
||||
public JCMethodDecl createHashCode(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, JCTree source) {
|
||||
public JCMethodDecl createHashCode(JavacNode typeNode, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members, boolean callSuper, FieldAccess fieldAccess, JCTree source) {
|
||||
JavacTreeMaker maker = typeNode.getTreeMaker();
|
||||
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
|
||||
@@ -257,7 +216,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext());
|
||||
|
||||
/* final int PRIME = X; */ {
|
||||
if (!fields.isEmpty()) {
|
||||
if (!members.isEmpty()) {
|
||||
statements.append(maker.VarDef(maker.Modifiers(finalFlag), primeName, maker.TypeIdent(CTC_INT), maker.Literal(HandlerUtil.primeForHashcode())));
|
||||
}
|
||||
}
|
||||
@@ -267,8 +226,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
if (callSuper) {
|
||||
/* ... super.hashCode(); */
|
||||
init = maker.Apply(List.<JCExpression>nil(),
|
||||
maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("hashCode")),
|
||||
List.<JCExpression>nil());
|
||||
maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("hashCode")),
|
||||
List.<JCExpression>nil());
|
||||
} else {
|
||||
/* ... 1; */
|
||||
init = maker.Literal(1);
|
||||
@@ -276,10 +235,12 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
statements.append(maker.VarDef(maker.Modifiers(0), resultName, maker.TypeIdent(CTC_INT), init));
|
||||
}
|
||||
|
||||
Name dollar = typeNode.toName("$");
|
||||
for (JavacNode fieldNode : fields) {
|
||||
JCExpression fType = getFieldType(fieldNode, fieldAccess);
|
||||
JCExpression fieldAccessor = createFieldAccessor(maker, fieldNode, fieldAccess);
|
||||
for (Included<JavacNode, EqualsAndHashCode.Include> member : members) {
|
||||
JavacNode memberNode = member.getNode();
|
||||
JCExpression fType = getFieldType(memberNode, fieldAccess);
|
||||
boolean isMethod = memberNode.getKind() == Kind.METHOD;
|
||||
|
||||
JCExpression fieldAccessor = isMethod ? createMethodAccessor(maker, memberNode) : createFieldAccessor(maker, memberNode, fieldAccess);
|
||||
if (fType instanceof JCPrimitiveTypeTree) {
|
||||
switch (((JCPrimitiveTypeTree) fType).getPrimitiveTypeKind()) {
|
||||
case BOOLEAN:
|
||||
@@ -288,7 +249,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
maker.Literal(HandlerUtil.primeForTrue()), maker.Literal(HandlerUtil.primeForFalse())))));
|
||||
break;
|
||||
case LONG: {
|
||||
Name dollarFieldName = dollar.append(((JCVariableDecl) fieldNode.get()).name);
|
||||
Name dollarFieldName = memberNode.toName((isMethod ? "$$" : "$") + memberNode.getName());
|
||||
statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, maker.TypeIdent(CTC_LONG), fieldAccessor));
|
||||
statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName))));
|
||||
}
|
||||
@@ -302,7 +263,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
break;
|
||||
case DOUBLE: {
|
||||
/* longToIntForHashCode(Double.doubleToLongBits(this.fieldName)) */
|
||||
Name dollarFieldName = dollar.append(((JCVariableDecl) fieldNode.get()).name);
|
||||
Name dollarFieldName = memberNode.toName((isMethod ? "$$" : "$") + memberNode.getName());
|
||||
JCExpression init = maker.Apply(
|
||||
List.<JCExpression>nil(),
|
||||
genJavaLangTypeRef(typeNode, "Double", "doubleToLongBits"),
|
||||
@@ -332,7 +293,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
/* final java.lang.Object $fieldName = this.fieldName; */
|
||||
/* ($fieldName == null ? NULL_PRIME : $fieldName.hashCode()) */
|
||||
|
||||
Name dollarFieldName = dollar.append(((JCVariableDecl) fieldNode.get()).name);
|
||||
Name dollarFieldName = memberNode.toName((isMethod ? "$$" : "$") + memberNode.getName());
|
||||
statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, genJavaLangTypeRef(typeNode, "Object"), fieldAccessor));
|
||||
|
||||
JCExpression hcCall = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(dollarFieldName), typeNode.toName("hashCode")),
|
||||
@@ -410,7 +371,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
return maker.TypeApply(expr, wildcards.toList());
|
||||
}
|
||||
|
||||
public JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source, List<JCAnnotation> onParam) {
|
||||
public JCMethodDecl createEquals(JavacNode typeNode, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source, List<JCAnnotation> onParam) {
|
||||
JavacTreeMaker maker = typeNode.getTreeMaker();
|
||||
|
||||
Name oName = typeNode.toName("o");
|
||||
@@ -439,7 +400,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
}
|
||||
|
||||
/* Outer.Inner.MyType<?> other = (Outer.Inner.MyType<?>) o; */ {
|
||||
if (!fields.isEmpty() || needsCanEqual) {
|
||||
if (!members.isEmpty() || needsCanEqual) {
|
||||
final JCExpression selfType1 = createTypeReference(typeNode, true), selfType2 = createTypeReference(typeNode, true);
|
||||
|
||||
statements.append(
|
||||
@@ -468,12 +429,13 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
statements.append(maker.If(superNotEqual, returnBool(maker, false), null));
|
||||
}
|
||||
|
||||
Name thisDollar = typeNode.toName("this$");
|
||||
Name otherDollar = typeNode.toName("other$");
|
||||
for (JavacNode fieldNode : fields) {
|
||||
JCExpression fType = getFieldType(fieldNode, fieldAccess);
|
||||
JCExpression thisFieldAccessor = createFieldAccessor(maker, fieldNode, fieldAccess);
|
||||
JCExpression otherFieldAccessor = createFieldAccessor(maker, fieldNode, fieldAccess, maker.Ident(otherName));
|
||||
for (Included<JavacNode, EqualsAndHashCode.Include> member : members) {
|
||||
JavacNode memberNode = member.getNode();
|
||||
boolean isMethod = memberNode.getKind() == Kind.METHOD;
|
||||
|
||||
JCExpression fType = getFieldType(memberNode, fieldAccess);
|
||||
JCExpression thisFieldAccessor = isMethod ? createMethodAccessor(maker, memberNode) : createFieldAccessor(maker, memberNode, fieldAccess);
|
||||
JCExpression otherFieldAccessor = isMethod ? createMethodAccessor(maker, memberNode, maker.Ident(otherName)) : createFieldAccessor(maker, memberNode, fieldAccess, maker.Ident(otherName));
|
||||
if (fType instanceof JCPrimitiveTypeTree) {
|
||||
switch (((JCPrimitiveTypeTree)fType).getPrimitiveTypeKind()) {
|
||||
case FLOAT:
|
||||
@@ -504,9 +466,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
/* final java.lang.Object this$fieldName = this.fieldName; */
|
||||
/* final java.lang.Object other$fieldName = other.fieldName; */
|
||||
/* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false; */
|
||||
Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
|
||||
Name thisDollarFieldName = thisDollar.append(fieldName);
|
||||
Name otherDollarFieldName = otherDollar.append(fieldName);
|
||||
Name thisDollarFieldName = memberNode.toName("this" + (isMethod ? "$$" : "$") + memberNode.getName());
|
||||
Name otherDollarFieldName = memberNode.toName("other" + (isMethod ? "$$" : "$") + memberNode.getName());
|
||||
|
||||
statements.append(maker.VarDef(maker.Modifiers(finalFlag), thisDollarFieldName, genJavaLangTypeRef(typeNode, "Object"), thisFieldAccessor));
|
||||
statements.append(maker.VarDef(maker.Modifiers(finalFlag), otherDollarFieldName, genJavaLangTypeRef(typeNode, "Object"), otherFieldAccessor));
|
||||
@@ -545,7 +506,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
|
||||
List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null));
|
||||
|
||||
JCBlock body = maker.Block(0, List.<JCStatement>of(
|
||||
maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode, false)))));
|
||||
maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode, false)))));
|
||||
|
||||
return recursiveSetGeneratedBy(maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source, typeNode.getContext());
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import lombok.ToString;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.handlers.InclusionExclusionUtils;
|
||||
import lombok.core.handlers.InclusionExclusionUtils.ToStringMember;
|
||||
import lombok.core.handlers.InclusionExclusionUtils.Included;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacNode;
|
||||
import lombok.javac.JavacTreeMaker;
|
||||
@@ -66,7 +66,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
|
||||
deleteAnnotationIfNeccessary(annotationNode, ToString.class);
|
||||
|
||||
ToString ann = annotation.getInstance();
|
||||
java.util.List<ToStringMember<JavacNode>> members = InclusionExclusionUtils.handleToStringMarking(annotationNode.up(), annotation, annotationNode);
|
||||
java.util.List<Included<JavacNode, ToString.Include>> members = InclusionExclusionUtils.handleToStringMarking(annotationNode.up(), annotation, annotationNode);
|
||||
if (members == null) return;
|
||||
|
||||
Boolean callSuper = ann.callSuper();
|
||||
@@ -98,11 +98,11 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
|
||||
Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
|
||||
FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
|
||||
|
||||
java.util.List<ToStringMember<JavacNode>> members = InclusionExclusionUtils.handleToStringMarking(typeNode, null, null);
|
||||
java.util.List<Included<JavacNode, ToString.Include>> members = InclusionExclusionUtils.handleToStringMarking(typeNode, null, null);
|
||||
generateToString(typeNode, errorNode, members, includeFieldNames, null, false, access);
|
||||
}
|
||||
|
||||
public void generateToString(JavacNode typeNode, JavacNode source, java.util.List<ToStringMember<JavacNode>> members,
|
||||
public void generateToString(JavacNode typeNode, JavacNode source, java.util.List<Included<JavacNode, ToString.Include>> members,
|
||||
boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) {
|
||||
|
||||
boolean notAClass = true;
|
||||
@@ -138,7 +138,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
|
||||
}
|
||||
}
|
||||
|
||||
static JCMethodDecl createToString(JavacNode typeNode, Collection<ToStringMember<JavacNode>> members,
|
||||
static JCMethodDecl createToString(JavacNode typeNode, Collection<Included<JavacNode, ToString.Include>> members,
|
||||
boolean includeNames, boolean callSuper, FieldAccess fieldAccess, JCTree source) {
|
||||
|
||||
JavacTreeMaker maker = typeNode.getTreeMaker();
|
||||
@@ -158,7 +158,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
|
||||
} else if (members.isEmpty()) {
|
||||
prefix = typeName + "()";
|
||||
} else if (includeNames) {
|
||||
ToStringMember<JavacNode> firstMember = members.iterator().next();
|
||||
Included<JavacNode, ToString.Include> firstMember = members.iterator().next();
|
||||
String name = firstMember.getInc() == null ? "" : firstMember.getInc().name();
|
||||
if (name.isEmpty()) name = firstMember.getNode().getName();
|
||||
prefix = typeName + "(" + name + "=";
|
||||
@@ -176,7 +176,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
|
||||
first = false;
|
||||
}
|
||||
|
||||
for (ToStringMember<JavacNode> member : members) {
|
||||
for (Included<JavacNode, ToString.Include> member : members) {
|
||||
JCExpression expr;
|
||||
|
||||
JCExpression memberAccessor;
|
||||
|
||||
@@ -948,18 +948,19 @@ public class JavacHandlerUtil {
|
||||
}
|
||||
|
||||
static JCExpression createMethodAccessor(JavacTreeMaker maker, JavacNode method) {
|
||||
JCExpression receiver;
|
||||
return createMethodAccessor(maker, method, null);
|
||||
}
|
||||
|
||||
static JCExpression createMethodAccessor(JavacTreeMaker maker, JavacNode method, JCExpression receiver) {
|
||||
JCMethodDecl methodDecl = (JCMethodDecl) method.get();
|
||||
|
||||
if ((methodDecl.mods.flags & Flags.STATIC) == 0) {
|
||||
if (receiver == null && (methodDecl.mods.flags & Flags.STATIC) == 0) {
|
||||
receiver = maker.Ident(method.toName("this"));
|
||||
} else {
|
||||
} else if (receiver == null) {
|
||||
JavacNode containerNode = method.up();
|
||||
if (containerNode != null && containerNode.get() instanceof JCClassDecl) {
|
||||
JCClassDecl container = (JCClassDecl) method.up().get();
|
||||
receiver = maker.Ident(container.name);
|
||||
} else {
|
||||
receiver = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
public class EqualsAndHashCodeNewStyle {
|
||||
int b;
|
||||
double c;
|
||||
int f;
|
||||
int d;
|
||||
int f() {
|
||||
return 0;
|
||||
}
|
||||
int g;
|
||||
long i() {
|
||||
return 0;
|
||||
}
|
||||
int j;
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public boolean equals(final java.lang.Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof EqualsAndHashCodeNewStyle)) return false;
|
||||
final EqualsAndHashCodeNewStyle other = (EqualsAndHashCodeNewStyle) o;
|
||||
if (!other.canEqual((java.lang.Object) this)) return false;
|
||||
if (this.b != other.b) return false;
|
||||
if (java.lang.Double.compare(this.c, other.c) != 0) return false;
|
||||
if (this.d != other.d) return false;
|
||||
if (this.f() != other.f()) return false;
|
||||
if (this.i() != other.i()) return false;
|
||||
return true;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected boolean canEqual(final java.lang.Object other) {
|
||||
return other instanceof EqualsAndHashCodeNewStyle;
|
||||
}
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public int hashCode() {
|
||||
final int PRIME = 59;
|
||||
int result = 1;
|
||||
result = result * PRIME + this.b;
|
||||
final long $c = java.lang.Double.doubleToLongBits(this.c);
|
||||
result = result * PRIME + (int) ($c >>> 32 ^ $c);
|
||||
result = result * PRIME + this.d;
|
||||
result = result * PRIME + this.f();
|
||||
final long $$i = this.i();
|
||||
result = result * PRIME + (int) ($$i >>> 32 ^ $$i);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import lombok.EqualsAndHashCode;
|
||||
public @EqualsAndHashCode class EqualsAndHashCodeNewStyle {
|
||||
@EqualsAndHashCode.Include int b;
|
||||
double c;
|
||||
int f;
|
||||
@EqualsAndHashCode.Include int d;
|
||||
int g;
|
||||
@EqualsAndHashCode.Exclude int j;
|
||||
public EqualsAndHashCodeNewStyle() {
|
||||
super();
|
||||
}
|
||||
@EqualsAndHashCode.Include int f() {
|
||||
return 0;
|
||||
}
|
||||
@EqualsAndHashCode.Include(replaces = "g") long i() {
|
||||
return 0;
|
||||
}
|
||||
public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
|
||||
if ((o == this))
|
||||
return true;
|
||||
if ((! (o instanceof EqualsAndHashCodeNewStyle)))
|
||||
return false;
|
||||
final EqualsAndHashCodeNewStyle other = (EqualsAndHashCodeNewStyle) o;
|
||||
if ((! other.canEqual((java.lang.Object) this)))
|
||||
return false;
|
||||
if ((this.b != other.b))
|
||||
return false;
|
||||
if ((java.lang.Double.compare(this.c, other.c) != 0))
|
||||
return false;
|
||||
if ((this.d != other.d))
|
||||
return false;
|
||||
if ((this.f() != other.f()))
|
||||
return false;
|
||||
if ((this.i() != other.i()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
|
||||
return (other instanceof EqualsAndHashCodeNewStyle);
|
||||
}
|
||||
public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
|
||||
final int PRIME = 59;
|
||||
int result = 1;
|
||||
result = ((result * PRIME) + this.b);
|
||||
final long $c = java.lang.Double.doubleToLongBits(this.c);
|
||||
result = ((result * PRIME) + (int) ($c ^ ($c >>> 32)));
|
||||
result = ((result * PRIME) + this.d);
|
||||
result = ((result * PRIME) + this.f());
|
||||
final long $$i = this.i();
|
||||
result = ((result * PRIME) + (int) ($$i ^ ($$i >>> 32)));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import lombok.EqualsAndHashCode;
|
||||
@EqualsAndHashCode
|
||||
public class EqualsAndHashCodeNewStyle {
|
||||
@EqualsAndHashCode.Include int b;
|
||||
double c;
|
||||
int f;
|
||||
@EqualsAndHashCode.Include int d;
|
||||
@EqualsAndHashCode.Include int f() {
|
||||
return 0;
|
||||
}
|
||||
int g;
|
||||
@EqualsAndHashCode.Include(replaces = "g") long i() {
|
||||
return 0;
|
||||
}
|
||||
@EqualsAndHashCode.Exclude int j;
|
||||
}
|
||||
Reference in new issue
Block a user