diff options
author | Andre Brait <andrebrait@gmail.com> | 2020-07-13 17:15:03 +0200 |
---|---|---|
committer | Roel Spilker <r.spilker@gmail.com> | 2020-09-24 22:25:15 +0200 |
commit | 4e0ffbc32913001082dd2387a20b480076ddd20a (patch) | |
tree | 2b4f761937c59192549348753a051b06f1c13a90 /src/core/lombok/eclipse | |
parent | b78a6af49cb82dd1dc03e6839b33827688fda3f6 (diff) | |
download | lombok-4e0ffbc32913001082dd2387a20b480076ddd20a.tar.gz lombok-4e0ffbc32913001082dd2387a20b480076ddd20a.tar.bz2 lombok-4e0ffbc32913001082dd2387a20b480076ddd20a.zip |
Eclipse impl and tests
Diffstat (limited to 'src/core/lombok/eclipse')
-rwxr-xr-x | src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java | 77 |
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); |