diff options
author | Roel Spilker <r.spilker@gmail.com> | 2010-11-11 01:58:48 +0100 |
---|---|---|
committer | Roel Spilker <r.spilker@gmail.com> | 2010-11-11 01:58:48 +0100 |
commit | 1c323332493148f0aaa936e668e1b0da5d09c8be (patch) | |
tree | 7b9107aa641fb913702360cc95133a640218552d /src/core/lombok/eclipse | |
parent | c8774389e7cb73e494267af3a87f70c7497b220a (diff) | |
download | lombok-1c323332493148f0aaa936e668e1b0da5d09c8be.tar.gz lombok-1c323332493148f0aaa936e668e1b0da5d09c8be.tar.bz2 lombok-1c323332493148f0aaa936e668e1b0da5d09c8be.zip |
@Getter(lazy=true) support for javac
Diffstat (limited to 'src/core/lombok/eclipse')
5 files changed, 90 insertions, 40 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index f252793d..ba34df77 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -175,8 +175,29 @@ public class EclipseHandlerUtil { return null; } - static TypeReference getFieldType(EclipseNode field, boolean useFieldsDirectly) { - GetterMethod getter = useFieldsDirectly ? null : findGetter(field); + enum FieldAccess { + GETTER, PREFER_FIELD, ALWAYS_FIELD; + } + + static boolean lookForGetter(EclipseNode field, FieldAccess fieldAccess) { + if (fieldAccess == FieldAccess.GETTER) return true; + if (fieldAccess == FieldAccess.ALWAYS_FIELD) return false; + + // If @Getter(lazy = true) is used, then using it is mandatory. + for (EclipseNode child : field.down()) { + if (child.getKind() != Kind.ANNOTATION) continue; + if (Eclipse.annotationTypeMatches(Getter.class, child)) { + AnnotationValues<Getter> ann = Eclipse.createAnnotation(Getter.class, child); + if (ann.getInstance().lazy()) return true; + } + } + return false; + } + + static TypeReference getFieldType(EclipseNode field, FieldAccess fieldAccess) { + boolean lookForGetter = lookForGetter(field, fieldAccess); + + GetterMethod getter = lookForGetter ? findGetter(field) : null; if (getter == null) { return ((FieldDeclaration)field.get()).type; } @@ -184,11 +205,13 @@ public class EclipseHandlerUtil { return getter.type; } - static Expression createFieldAccessor(EclipseNode field, boolean useFieldsDirectly, ASTNode source) { + static Expression createFieldAccessor(EclipseNode field, FieldAccess fieldAccess, ASTNode source) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; - GetterMethod getter = useFieldsDirectly ? null : findGetter(field); + boolean lookForGetter = lookForGetter(field, fieldAccess); + + GetterMethod getter = lookForGetter ? findGetter(field) : null; if (getter == null) { FieldDeclaration fieldDecl = (FieldDeclaration)field.get(); @@ -219,11 +242,13 @@ public class EclipseHandlerUtil { return call; } - static Expression createFieldAccessor(EclipseNode field, boolean useFieldsDirectly, ASTNode source, char[] receiver) { + static Expression createFieldAccessor(EclipseNode field, FieldAccess fieldAccess, ASTNode source, char[] receiver) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; - GetterMethod getter = useFieldsDirectly ? null : findGetter(field); + boolean lookForGetter = lookForGetter(field, fieldAccess); + + GetterMethod getter = lookForGetter ? findGetter(field) : null; if (getter == null) { NameReference ref; diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 2b830241..895c076e 100644 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -113,7 +113,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA } } - generateMethods(typeNode, errorNode, null, null, null, false, false); + generateMethods(typeNode, errorNode, null, null, null, false, FieldAccess.GETTER); } @Override public boolean handle(AnnotationValues<EqualsAndHashCode> annotation, @@ -135,11 +135,13 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored."); } - return generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true, ann.doNotUseGetters()); + FieldAccess fieldAccess = ann.doNotUseGetters() ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER; + + return generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true, fieldAccess); } public boolean generateMethods(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes, List<String> includes, - Boolean callSuper, boolean whineIfExists, boolean useFieldsDirectly) { + Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) { assert excludes == null || includes == null; TypeDeclaration typeDecl = null; @@ -209,7 +211,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA boolean isFinal = (typeDecl.modifiers & ClassFileConstants.AccFinal) != 0; needsCanEqual = !isDirectDescendantOfObject || !isFinal; - MethodDeclaration equals = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get(), useFieldsDirectly, needsCanEqual); + MethodDeclaration equals = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get(), fieldAccess, needsCanEqual); injectMethod(typeNode, equals); break; case EXISTS_BY_LOMBOK: @@ -237,7 +239,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA switch (methodExists("hashCode", typeNode)) { case NOT_EXISTS: - MethodDeclaration hashCode = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get(), useFieldsDirectly); + MethodDeclaration hashCode = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get(), fieldAccess); injectMethod(typeNode, hashCode); break; case EXISTS_BY_LOMBOK: @@ -253,7 +255,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA return true; } - private MethodDeclaration createHashCode(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, boolean useFieldsDirectly) { + private MethodDeclaration createHashCode(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, FieldAccess fieldAccess) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; @@ -318,9 +320,9 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA int tempCounter = 0; for (EclipseNode field : fields) { - TypeReference fType = getFieldType(field, useFieldsDirectly); + TypeReference fType = getFieldType(field, fieldAccess); char[] token = fType.getLastToken(); - Expression fieldAccessor = createFieldAccessor(field, useFieldsDirectly, source); + Expression fieldAccessor = createFieldAccessor(field, fieldAccess, source); if (fType.dimensions() == 0 && token != null) { if (Arrays.equals(TypeConstants.FLOAT, token)) { /* Float.floatToIntBits(fieldName) */ @@ -363,7 +365,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA Eclipse.setGeneratedBy(int1231or1237, source); intoResult.add(int1231or1237); } else if (Arrays.equals(TypeConstants.LONG, token)) { - intoResult.add(longToIntForHashCode(fieldAccessor, createFieldAccessor(field, useFieldsDirectly, source), source)); + intoResult.add(longToIntForHashCode(fieldAccessor, createFieldAccessor(field, fieldAccess, source), source)); } else if (BUILT_IN_TYPES.contains(new String(token))) { intoResult.add(fieldAccessor); } else /* objects */ { @@ -371,7 +373,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA MessageSend hashCodeCall = new MessageSend(); hashCodeCall.sourceStart = pS; hashCodeCall.sourceEnd = pE; Eclipse.setGeneratedBy(hashCodeCall, source); - hashCodeCall.receiver = createFieldAccessor(field, useFieldsDirectly, source); + hashCodeCall.receiver = createFieldAccessor(field, fieldAccess, source); hashCodeCall.selector = "hashCode".toCharArray(); NullLiteral nullLiteral = new NullLiteral(pS, pE); Eclipse.setGeneratedBy(nullLiteral, source); @@ -433,7 +435,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA return method; } - private MethodDeclaration createEquals(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, boolean useFieldsDirectly, boolean needsCanEqual) { + private MethodDeclaration createEquals(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, FieldAccess fieldAccess, boolean needsCanEqual) { int pS = source.sourceStart; int pE = source.sourceEnd; long p = (long)pS << 32 | pE; TypeDeclaration typeDecl = (TypeDeclaration)type.get(); @@ -589,10 +591,10 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA } for (EclipseNode field : fields) { - TypeReference fType = getFieldType(field, useFieldsDirectly); + TypeReference fType = getFieldType(field, fieldAccess); char[] token = fType.getLastToken(); - Expression thisFieldAccessor = createFieldAccessor(field, useFieldsDirectly, source); - Expression otherFieldAccessor = createFieldAccessor(field, useFieldsDirectly, source, otherName); + Expression thisFieldAccessor = createFieldAccessor(field, fieldAccess, source); + Expression otherFieldAccessor = createFieldAccessor(field, fieldAccess, source, otherName); if (fType.dimensions() == 0 && token != null) { if (Arrays.equals(TypeConstants.FLOAT, token)) { @@ -619,9 +621,9 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA MessageSend equalsCall = new MessageSend(); equalsCall.sourceStart = pS; equalsCall.sourceEnd = pE; Eclipse.setGeneratedBy(equalsCall, source); - equalsCall.receiver = createFieldAccessor(field, useFieldsDirectly, source); + equalsCall.receiver = createFieldAccessor(field, fieldAccess, source); equalsCall.selector = "equals".toCharArray(); - equalsCall.arguments = new Expression[] { createFieldAccessor(field, useFieldsDirectly, source, otherName) }; + equalsCall.arguments = new Expression[] { createFieldAccessor(field, fieldAccess, source, otherName) }; UnaryExpression fieldsNotEqual = new UnaryExpression(equalsCall, OperatorIds.NOT); fieldsNotEqual.sourceStart = pS; fieldsNotEqual.sourceEnd = pE; Eclipse.setGeneratedBy(fieldsNotEqual, source); diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index 38a6b468..e5ddbc3f 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -76,7 +76,7 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { } for (EclipseNode field : typeNode.down()) { - if (fieldQualifiesForGetterGeneration(field)) generateGetterForField(field, pos.get(), level, null); + if (fieldQualifiesForGetterGeneration(field)) generateGetterForField(field, pos.get(), level, null, false); } return true; } @@ -103,7 +103,7 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { * If not, the getter is still generated if it isn't already there, though there will not * be a warning if its already there. The default access level is used. */ - public void generateGetterForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level, Annotation[] onMethod) { + public void generateGetterForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level, Annotation[] onMethod, boolean lazy) { for (EclipseNode child : fieldNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (annotationTypeMatches(Getter.class, child)) { @@ -113,42 +113,61 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { } } - createGetterForField(level, fieldNode, fieldNode, pos, false, onMethod); + createGetterForField(level, fieldNode, fieldNode, pos, false, onMethod, lazy); } public boolean handle(AnnotationValues<Getter> annotation, Annotation ast, EclipseNode annotationNode) { EclipseNode node = annotationNode.up(); - AccessLevel level = annotation.getInstance().value(); - if (level == AccessLevel.NONE) return true; + Getter annotationInstance = annotation.getInstance(); + AccessLevel level = annotationInstance.value(); + boolean lazy = annotationInstance.lazy(); + if (level == AccessLevel.NONE) { + if (lazy) { + annotationNode.addWarning("'lazy' requires AccessLevel.PRIVATE or higher."); + } + return true; + } if (node == null) return false; Annotation[] onMethod = getAndRemoveAnnotationParameter(ast, "onMethod"); if (node.getKind() == Kind.FIELD) { - return createGetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod); + return createGetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod, lazy); } if (node.getKind() == Kind.TYPE) { if (onMethod != null && onMethod.length != 0) annotationNode.addError("'onMethod' is not supported for @Getter on a type."); + if (lazy) annotationNode.addError("'lazy' is not supported for @Getter on a type."); return generateGetterForType(node, annotationNode, level, false); } return false; } - private boolean createGetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod) { + private boolean createGetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod, boolean lazy) { for (EclipseNode fieldNode : fieldNodes) { - createGetterForField(level, fieldNode, errorNode, source, whineIfExists, onMethod); + createGetterForField(level, fieldNode, errorNode, source, whineIfExists, onMethod, lazy); } return true; } private boolean createGetterForField(AccessLevel level, - EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod) { + EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod, boolean lazy) { if (fieldNode.getKind() != Kind.FIELD) { errorNode.addError("@Getter is only supported on a class or a field."); return true; } FieldDeclaration field = (FieldDeclaration) fieldNode.get(); + if (lazy) { + if ((field.modifiers & (ClassFileConstants.AccPrivate | ClassFileConstants.AccFinal)) != 0) { + errorNode.addError("'lazy' requires the field to be private and final."); + return true; + } + if (field.initialization == null) { + errorNode.addError("'lazy' requires field initialization."); + return true; + } + } + TypeReference fieldType = copyType(field.type, source); String fieldName = new String(field.name); boolean isBoolean = nameEquals(fieldType.getTypeName(), "boolean") && fieldType.dimensions() == 0; @@ -198,7 +217,7 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { method.thrownExceptions = null; method.typeParameters = null; method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - Expression fieldRef = createFieldAccessor(fieldNode, true, source); + Expression fieldRef = createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source); Statement returnStatement = new ReturnStatement(fieldRef, field.sourceStart, field.sourceEnd); Eclipse.setGeneratedBy(returnStatement, source); method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index 48e688fd..2c3ca6ed 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -35,6 +35,7 @@ import lombok.core.handlers.TransformationsUtil; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; +import lombok.eclipse.handlers.EclipseHandlerUtil.FieldAccess; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Annotation; @@ -206,7 +207,7 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> { method.thrownExceptions = null; method.typeParameters = null; method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - Expression fieldRef = createFieldAccessor(fieldNode, true, source); + Expression fieldRef = createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source); NameReference fieldNameRef = new SingleNameReference(field.name, p); Eclipse.setGeneratedBy(fieldNameRef, source); Assignment assignment = new Assignment(fieldRef, fieldNameRef, (int)p); diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java index b3f4abaa..f39cb129 100644 --- a/src/core/lombok/eclipse/handlers/HandleToString.java +++ b/src/core/lombok/eclipse/handlers/HandleToString.java @@ -38,6 +38,7 @@ import lombok.core.AST.Kind; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; +import lombok.eclipse.handlers.EclipseHandlerUtil.FieldAccess; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Annotation; @@ -94,7 +95,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { try { includeFieldNames = ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue(); } catch (Exception ignore) {} - generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, false); + generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, FieldAccess.GETTER); } public boolean handle(AnnotationValues<ToString> annotation, Annotation ast, EclipseNode annotationNode) { @@ -115,11 +116,13 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { checkForBogusFieldNames(typeNode, annotation); - return generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true, ann.doNotUseGetters()); + FieldAccess fieldAccess = ann.doNotUseGetters() ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER; + + return generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true, fieldAccess); } public boolean generateToString(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes, List<String> includes, - boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, boolean useFieldsDirectly) { + boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) { TypeDeclaration typeDecl = null; if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); @@ -161,7 +164,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { switch (methodExists("toString", typeNode)) { case NOT_EXISTS: - MethodDeclaration toString = createToString(typeNode, nodesForToString, includeFieldNames, callSuper, errorNode.get(), useFieldsDirectly); + MethodDeclaration toString = createToString(typeNode, nodesForToString, includeFieldNames, callSuper, errorNode.get(), fieldAccess); injectMethod(typeNode, toString); return true; case EXISTS_BY_LOMBOK: @@ -176,7 +179,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { } private MethodDeclaration createToString(EclipseNode type, Collection<EclipseNode> fields, - boolean includeFieldNames, boolean callSuper, ASTNode source, boolean useFieldsDirectly) { + boolean includeFieldNames, boolean callSuper, ASTNode source, FieldAccess fieldAccess) { String typeName = getTypeName(type); char[] suffix = ")".toCharArray(); String infixS = ", "; @@ -214,8 +217,8 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { } for (EclipseNode field : fields) { - TypeReference fType = getFieldType(field, useFieldsDirectly); - Expression fieldAccessor = createFieldAccessor(field, useFieldsDirectly, source); + TypeReference fType = getFieldType(field, fieldAccess); + Expression fieldAccessor = createFieldAccessor(field, fieldAccess, source); Expression ex; if (fType.dimensions() > 0) { |