aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/eclipse
diff options
context:
space:
mode:
authorAndre Brait <andrebrait@gmail.com>2020-07-13 17:15:03 +0200
committerRoel Spilker <r.spilker@gmail.com>2020-09-24 22:25:15 +0200
commit4e0ffbc32913001082dd2387a20b480076ddd20a (patch)
tree2b4f761937c59192549348753a051b06f1c13a90 /src/core/lombok/eclipse
parentb78a6af49cb82dd1dc03e6839b33827688fda3f6 (diff)
downloadlombok-4e0ffbc32913001082dd2387a20b480076ddd20a.tar.gz
lombok-4e0ffbc32913001082dd2387a20b480076ddd20a.tar.bz2
lombok-4e0ffbc32913001082dd2387a20b480076ddd20a.zip
Eclipse impl and tests
Diffstat (limited to 'src/core/lombok/eclipse')
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java77
1 files changed, 72 insertions, 5 deletions
diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
index 7147343e..76a46814 100755
--- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
@@ -36,6 +36,7 @@ import java.util.Set;
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.EqualsAndHashCode;
+import lombok.EqualsAndHashCode.CacheStrategy;
import lombok.core.AST.Kind;
import lombok.core.handlers.HandlerUtil;
import lombok.core.handlers.InclusionExclusionUtils;
@@ -47,6 +48,7 @@ import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
+import lombok.javac.JavacTreeMaker;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
@@ -59,9 +61,11 @@ 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;
+import org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
@@ -76,6 +80,7 @@ import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
@@ -84,16 +89,24 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.mangosdk.spi.ProviderFor;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.tree.JCTree.JCModifiers;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+
/**
* Handles the {@code EqualsAndHashCode} annotation for eclipse.
*/
@ProviderFor(EclipseAnnotationHandler.class)
public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndHashCode> {
+ private static final String HASH_CODE_CACHE_NAME = "$hashCodeCache";
+
+ private final char[] HASH_CODE_CACHE_NAME_ARR = HASH_CODE_CACHE_NAME.toCharArray();
private final char[] PRIME = "PRIME".toCharArray();
private final char[] RESULT = "result".toCharArray();
@@ -116,7 +129,9 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
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);
+ boolean cacheHashCode = ann.cacheStrategy() == CacheStrategy.LAZY;
+
+ generateMethods(annotationNode.up(), annotationNode, members, callSuper, true, cacheHashCode, fieldAccess, onParam);
}
public void generateEqualsAndHashCodeForType(EclipseNode typeNode, EclipseNode errorNode) {
@@ -130,11 +145,11 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
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, members, null, false, access, new ArrayList<Annotation>());
+ generateMethods(typeNode, errorNode, members, null, false, false, access, new ArrayList<Annotation>());
}
public void generateMethods(EclipseNode typeNode, EclipseNode errorNode, List<Included<EclipseNode, EqualsAndHashCode.Include>> members,
- Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List<Annotation> onParam) {
+ Boolean callSuper, boolean whineIfExists, boolean cacheHashCode, FieldAccess fieldAccess, List<Annotation> onParam) {
TypeDeclaration typeDecl = null;
@@ -222,12 +237,38 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
injectMethod(typeNode, canEqualMethod);
}
- MethodDeclaration hashCodeMethod = createHashCode(typeNode, members, callSuper, errorNode.get(), fieldAccess);
+ if (cacheHashCode){
+ if (!isFinal) {
+ String msg = "Not caching the result of hashCode: Annotated type is not final.";
+ errorNode.addWarning(msg);
+ cacheHashCode = false;
+ } else if (fieldExists(HASH_CODE_CACHE_NAME, typeNode) != MemberExistsResult.NOT_EXISTS) {
+ String msg = String.format("Not caching the result of hashCode: A field named %s already exists.", HASH_CODE_CACHE_NAME);
+ errorNode.addWarning(msg);
+ cacheHashCode = false;
+ } else {
+ createHashCodeCacheField(typeNode, errorNode.get());
+ }
+ }
+
+ MethodDeclaration hashCodeMethod = createHashCode(typeNode, members, callSuper, cacheHashCode, errorNode.get(), fieldAccess);
hashCodeMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
injectMethod(typeNode, hashCodeMethod);
}
+
+ private void createHashCodeCacheField(EclipseNode typeNode, ASTNode source) {
+ FieldDeclaration hashCodeCacheDecl = new FieldDeclaration(HASH_CODE_CACHE_NAME_ARR, 0, -1);
+ hashCodeCacheDecl.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccTransient;
+ hashCodeCacheDecl.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
+ hashCodeCacheDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
+ hashCodeCacheDecl.declarationSourceEnd = -1;
+ hashCodeCacheDecl.initialization = makeIntLiteral("0".toCharArray(), source);
+ injectFieldAndMarkGenerated(typeNode, hashCodeCacheDecl);
+ setGeneratedBy(hashCodeCacheDecl, source);
+ setGeneratedBy(hashCodeCacheDecl.type, source);
+ }
- public MethodDeclaration createHashCode(EclipseNode type, Collection<Included<EclipseNode, EqualsAndHashCode.Include>> members, boolean callSuper, ASTNode source, FieldAccess fieldAccess) {
+ public MethodDeclaration createHashCode(EclipseNode type, Collection<Included<EclipseNode, EqualsAndHashCode.Include>> members, boolean callSuper, boolean cacheHashCode, ASTNode source, FieldAccess fieldAccess) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
@@ -262,6 +303,20 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
}
}
+ /* if ($hashCodeCache != 0) return $hashCodeCache; */ {
+ if (cacheHashCode) {
+ SingleNameReference hashCodeCacheRef = new SingleNameReference(HASH_CODE_CACHE_NAME_ARR, p);
+ setGeneratedBy(hashCodeCacheRef, source);
+ EqualExpression cacheNotZero = new EqualExpression(hashCodeCacheRef, makeIntLiteral("0".toCharArray(), source), OperatorIds.NOT_EQUAL);
+ setGeneratedBy(cacheNotZero, source);
+ ReturnStatement returnCache = new ReturnStatement(hashCodeCacheRef, pS, pS);
+ setGeneratedBy(returnCache, source);
+ IfStatement ifStatement = new IfStatement(cacheNotZero, returnCache, pS, pE);
+ setGeneratedBy(ifStatement, source);
+ statements.add(ifStatement);
+ }
+ }
+
/* final int PRIME = X; */ {
/* Without members, PRIME isn't used, as that would trigger a 'local variable not used' warning. */
if (!isEmpty) {
@@ -391,6 +446,18 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
}
}
+ /* $hashCodeCache = result; */ {
+ if (cacheHashCode) {
+ SingleNameReference hashCodeCacheRef = new SingleNameReference(HASH_CODE_CACHE_NAME_ARR, p);
+ setGeneratedBy(hashCodeCacheRef, source);
+ SingleNameReference resultRef = new SingleNameReference(RESULT, p);
+ setGeneratedBy(resultRef, source);
+ Assignment cacheResult = new Assignment(hashCodeCacheRef, resultRef, pE);
+ setGeneratedBy(cacheResult, source);
+ statements.add(cacheResult);
+ }
+ }
+
/* return result; */ {
SingleNameReference resultRef = new SingleNameReference(RESULT, p);
setGeneratedBy(resultRef, source);