diff options
Diffstat (limited to 'src/core/lombok/javac/handlers')
-rw-r--r-- | src/core/lombok/javac/handlers/HandleConstructor.java | 42 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleData.java | 37 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleGetter.java | 71 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSetter.java | 75 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacHandlerUtil.java | 60 |
5 files changed, 170 insertions, 115 deletions
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index fe5f8566..e24c19d1 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -65,7 +65,7 @@ public class HandleConstructor { String staticName = ann.staticName(); if (level == AccessLevel.NONE) return true; List<JavacNode> fields = List.nil(); - new HandleConstructor().generateConstructor(level, typeNode, fields, staticName, false, false); + new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, false, false); return true; } } @@ -82,24 +82,28 @@ public class HandleConstructor { @SuppressWarnings("deprecation") boolean suppressConstructorProperties = ann.suppressConstructorProperties(); if (level == AccessLevel.NONE) return true; - List<JavacNode> fields = List.nil(); - for (JavacNode child : typeNode.down()) { - if (child.getKind() != Kind.FIELD) continue; - JCVariableDecl fieldDecl = (JCVariableDecl) child.get(); - //Skip fields that start with $ - if (fieldDecl.name.toString().startsWith("$")) continue; - long fieldFlags = fieldDecl.mods.flags; - //Skip static fields. - if ((fieldFlags & Flags.STATIC) != 0) continue; - boolean isFinal = (fieldFlags & Flags.FINAL) != 0; - boolean isNonNull = !findAnnotations(child, TransformationsUtil.NON_NULL_PATTERN).isEmpty(); - if ((isFinal || isNonNull) && fieldDecl.init == null) fields = fields.append(child); - } - new HandleConstructor().generateConstructor(level, typeNode, fields, staticName, false, suppressConstructorProperties); + new HandleConstructor().generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, false, suppressConstructorProperties); return true; } } + private static List<JavacNode> findRequiredFields(JavacNode typeNode) { + List<JavacNode> fields = List.nil(); + for (JavacNode child : typeNode.down()) { + if (child.getKind() != Kind.FIELD) continue; + JCVariableDecl fieldDecl = (JCVariableDecl) child.get(); + //Skip fields that start with $ + if (fieldDecl.name.toString().startsWith("$")) continue; + long fieldFlags = fieldDecl.mods.flags; + //Skip static fields. + if ((fieldFlags & Flags.STATIC) != 0) continue; + boolean isFinal = (fieldFlags & Flags.FINAL) != 0; + boolean isNonNull = !findAnnotations(child, TransformationsUtil.NON_NULL_PATTERN).isEmpty(); + if ((isFinal || isNonNull) && fieldDecl.init == null) fields = fields.append(child); + } + return fields; + } + @ProviderFor(JavacAnnotationHandler.class) public static class HandleAllArgsConstructor implements JavacAnnotationHandler<AllArgsConstructor> { @Override public boolean handle(AnnotationValues<AllArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) { @@ -123,12 +127,16 @@ public class HandleConstructor { if ((fieldFlags & Flags.STATIC) != 0) continue; fields = fields.append(child); } - new HandleConstructor().generateConstructor(level, typeNode, fields, staticName, false, suppressConstructorProperties); + new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, false, suppressConstructorProperties); return true; } } - public void generateConstructor(AccessLevel level, JavacNode typeNode, List<JavacNode> fields, String staticName, boolean skipIfConstructorExists, boolean suppressConstructorProperties) { + public void generateRequiredArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists) { + generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, skipIfConstructorExists, false); + } + + public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JavacNode> fields, String staticName, boolean skipIfConstructorExists, boolean suppressConstructorProperties) { if (skipIfConstructorExists && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return; if (skipIfConstructorExists) { for (JavacNode child : typeNode.down()) { diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java index e20b230e..2087c133 100644 --- a/src/core/lombok/javac/handlers/HandleData.java +++ b/src/core/lombok/javac/handlers/HandleData.java @@ -21,16 +21,10 @@ */ package lombok.javac.handlers; -import static lombok.javac.handlers.JavacHandlerUtil.*; - -import java.util.LinkedHashMap; -import java.util.Map; - +import static lombok.javac.handlers.JavacHandlerUtil.markAnnotationAsProcessed; import lombok.AccessLevel; import lombok.Data; -import lombok.core.AST.Kind; import lombok.core.AnnotationValues; -import lombok.core.handlers.TransformationsUtil; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; @@ -39,8 +33,6 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCClassDecl; -import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.util.List; /** * Handles the {@code lombok.Data} annotation for javac. @@ -60,31 +52,12 @@ public class HandleData implements JavacAnnotationHandler<Data> { return false; } - List<JavacNode> nodesForConstructor = List.nil(); - Map<JavacNode, Boolean> gettersAndSetters = new LinkedHashMap<JavacNode, Boolean>(); - for (JavacNode child : typeNode.down()) { - if (child.getKind() != Kind.FIELD) continue; - JCVariableDecl fieldDecl = (JCVariableDecl) child.get(); - //Skip fields that start with $ - if (fieldDecl.name.toString().startsWith("$")) continue; - long fieldFlags = fieldDecl.mods.flags; - //Skip static fields. - if ((fieldFlags & Flags.STATIC) != 0) continue; - boolean isFinal = (fieldFlags & Flags.FINAL) != 0; - boolean isNonNull = !findAnnotations(child, TransformationsUtil.NON_NULL_PATTERN).isEmpty(); - if ((isFinal || isNonNull) && fieldDecl.init == null) nodesForConstructor = nodesForConstructor.append(child); - gettersAndSetters.put(child, !isFinal); - } - String staticConstructorName = annotation.getInstance().staticConstructor(); - new HandleConstructor().generateConstructor(AccessLevel.PUBLIC, typeNode, nodesForConstructor, staticConstructorName, true, false); - - for (Map.Entry<JavacNode, Boolean> field : gettersAndSetters.entrySet()) { - new HandleGetter().generateGetterForField(field.getKey(), annotationNode.get(), AccessLevel.PUBLIC, true); - if (field.getValue()) new HandleSetter().generateSetterForField(field.getKey(), annotationNode.get(), AccessLevel.PUBLIC, true); - } - + // TODO move this to the end OR move it to the top in eclipse. + new HandleConstructor().generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, true); + new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true); + new HandleSetter().generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true); new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode); new HandleToString().generateToStringForType(typeNode, annotationNode); diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 582aa02b..28402346 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -56,6 +56,45 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; */ @ProviderFor(JavacAnnotationHandler.class) public class HandleGetter implements JavacAnnotationHandler<Getter> { + public boolean generateGetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelGetter) { + if (checkForTypeLevelGetter) { + if (typeNode != null) for (JavacNode child : typeNode.down()) { + if (child.getKind() == Kind.ANNOTATION) { + if (Javac.annotationTypeMatches(Getter.class, child)) { + //The annotation will make it happen, so we can skip it. + return true; + } + } + } + } + + JCClassDecl typeDecl = null; + if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); + long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; + boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0; + + if (typeDecl == null || notAClass) { + errorNode.addError("@Getter is only supported on a class or a field."); + return false; + } + + for (JavacNode field : typeNode.down()) { + if (fieldQualifiesForGetterGeneration(field)) generateGetterForField(field, errorNode.get(), level); + } + + return true; + } + + public boolean fieldQualifiesForGetterGeneration(JavacNode field) { + if (field.getKind() != Kind.FIELD) return false; + JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); + //Skip fields that start with $ + if (fieldDecl.name.toString().startsWith("$")) return false; + //Skip static fields. + if ((fieldDecl.mods.flags & Flags.STATIC) != 0) return false; + return true; + } + /** * Generates a getter on the stated field. * @@ -71,7 +110,7 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { * @param fieldNode The node representing the field you want a getter for. * @param pos The node responsible for generating the getter (the {@code @Data} or {@code @Getter} annotation). */ - public void generateGetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, boolean checkForTypeLevelGetter) { + public void generateGetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level) { for (JavacNode child : fieldNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (Javac.annotationTypeMatches(Getter.class, child)) { @@ -81,18 +120,6 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { } } - if (checkForTypeLevelGetter) { - JavacNode containingType = fieldNode.up(); - if (containingType != null) for (JavacNode child : containingType.down()) { - if (child.getKind() == Kind.ANNOTATION) { - if (Javac.annotationTypeMatches(Getter.class, child)) { - //The annotation will make it happen, so we can skip it. - return; - } - } - } - } - createGetterForField(level, fieldNode, fieldNode, false); } @@ -109,21 +136,7 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { return createGetterForFields(level, fields, annotationNode, true); } if (node.getKind() == Kind.TYPE) { - JCClassDecl typeDecl = null; - if (node.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) node.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0; - - if (typeDecl == null || notAClass) { - annotationNode.addError("@Getter is only supported on a class."); - return false; - } - - for (JavacNode field : node.down()) { - if (field.getKind() != Kind.FIELD) continue; - generateGetterForField(field, ast, level, false); - } - return true; + return generateGetterForType(node, annotationNode, level, false); } return false; } @@ -139,7 +152,7 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { private boolean createGetterForField(AccessLevel level, JavacNode fieldNode, JavacNode errorNode, boolean whineIfExists) { if (fieldNode.getKind() != Kind.FIELD) { - errorNode.addError("@Getter is only supported on a field."); + errorNode.addError("@Getter is only supported on a class or a field."); return true; } diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 8728ceb3..0c248527 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -32,8 +32,8 @@ import javax.lang.model.type.TypeVisitor; import lombok.AccessLevel; import lombok.Setter; -import lombok.core.AnnotationValues; import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; import lombok.core.handlers.TransformationsUtil; import lombok.javac.Javac; import lombok.javac.JavacAnnotationHandler; @@ -44,7 +44,6 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.TypeTags; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; import com.sun.tools.javac.tree.JCTree.JCBlock; @@ -55,15 +54,53 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; /** * Handles the {@code lombok.Setter} annotation for javac. */ @ProviderFor(JavacAnnotationHandler.class) public class HandleSetter implements JavacAnnotationHandler<Setter> { + public boolean generateSetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelSetter) { + if (checkForTypeLevelSetter) { + if (typeNode != null) for (JavacNode child : typeNode.down()) { + if (child.getKind() == Kind.ANNOTATION) { + if (Javac.annotationTypeMatches(Setter.class, child)) { + //The annotation will make it happen, so we can skip it. + return true; + } + } + } + } + + JCClassDecl typeDecl = null; + if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); + long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; + boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0; + + if (typeDecl == null || notAClass) { + errorNode.addError("@Setter is only supported on a class or a field."); + return false; + } + + for (JavacNode field : typeNode.down()) { + if (field.getKind() != Kind.FIELD) continue; + JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); + //Skip fields that start with $ + if (fieldDecl.name.toString().startsWith("$")) continue; + //Skip static fields. + if ((fieldDecl.mods.flags & Flags.STATIC) != 0) continue; + //Skip final fields. + if ((fieldDecl.mods.flags & Flags.FINAL) != 0) continue; + + generateSetterForField(field, errorNode.get(), level); + } + return true; + } + /** * Generates a setter on the stated field. * @@ -79,7 +116,7 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { * @param fieldNode The node representing the field you want a setter for. * @param pos The node responsible for generating the setter (the {@code @Data} or {@code @Setter} annotation). */ - public void generateSetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, boolean checkForTypeLevelSetter) { + public void generateSetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level) { for (JavacNode child : fieldNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (Javac.annotationTypeMatches(Setter.class, child)) { @@ -89,18 +126,6 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { } } - if (checkForTypeLevelSetter) { - JavacNode containingType = fieldNode.up(); - if (containingType != null) for (JavacNode child : containingType.down()) { - if (child.getKind() == Kind.ANNOTATION) { - if (Javac.annotationTypeMatches(Setter.class, child)) { - //The annotation will make it happen, so we can skip it. - return; - } - } - } - } - createSetterForField(level, fieldNode, fieldNode, false); } @@ -118,21 +143,7 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { return createSetterForFields(level, fields, annotationNode, true); } if (node.getKind() == Kind.TYPE) { - JCClassDecl typeDecl = null; - if (node.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) node.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0; - - if (typeDecl == null || notAClass) { - annotationNode.addError("@Setter is only supported on a class."); - return false; - } - - for (JavacNode field : node.down()) { - if (field.getKind() != Kind.FIELD) continue; - generateSetterForField(field, ast, level, false); - } - return true; + return generateSetterForType(node, annotationNode, level, false); } return false; } @@ -148,7 +159,7 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { private boolean createSetterForField(AccessLevel level, JavacNode fieldNode, JavacNode errorNode, boolean whineIfExists) { if (fieldNode.getKind() != Kind.FIELD) { - fieldNode.addError("@Setter is only supported on a field."); + fieldNode.addError("@Setter is only supported on a class or a field."); return true; } diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index cb2697f1..09d5c3fe 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -21,12 +21,18 @@ */ package lombok.javac.handlers; +import static lombok.javac.Javac.annotationTypeMatches; + import java.lang.annotation.Annotation; import java.util.regex.Pattern; import lombok.AccessLevel; +import lombok.Data; +import lombok.Getter; +import lombok.core.AnnotationValues; import lombok.core.AST.Kind; import lombok.core.handlers.TransformationsUtil; +import lombok.javac.Javac; import lombok.javac.JavacNode; import com.sun.tools.javac.code.Flags; @@ -270,7 +276,17 @@ public class JavacHandlerUtil { } } - private static JCMethodDecl findGetter(JavacNode field) { + private static class GetterMethod { + private final Name name; + private final JCExpression type; + + GetterMethod(Name name, JCExpression type) { + this.name = name; + this.type = type; + } + } + + private static GetterMethod findGetter(JavacNode field) { JCVariableDecl decl = (JCVariableDecl)field.get(); JavacNode typeNode = field.up(); for (String potentialGetterName : toAllGetterNames(decl)) { @@ -280,15 +296,49 @@ public class JavacHandlerUtil { for (JavacNode potentialGetter : typeNode.down()) { if (potentialGetter.getKind() != Kind.METHOD) continue; JCMethodDecl method = (JCMethodDecl) potentialGetter.get(); + if (!method.name.contentEquals(potentialGetterName)) continue; /** static getX() methods don't count. */ if ((method.mods.flags & Flags.STATIC) != 0) continue; /** Nor do getters with a non-empty parameter list. */ if (method.params != null && method.params.size() > 0) continue; - return method; + return new GetterMethod(method.name, method.restype); + } + } + } + + // Check if the field has a @Getter annotation. + + boolean hasGetterAnnotation = false; + + for (JavacNode child : field.down()) { + if (child.getKind() == Kind.ANNOTATION && annotationTypeMatches(Getter.class, child)) { + AnnotationValues<Getter> ann = Javac.createAnnotation(Getter.class, child); + if (ann.getInstance().value() == AccessLevel.NONE) return null; //Definitely WONT have a getter. + hasGetterAnnotation = true; + } + } + + // Check if the class has a @Getter annotation. + + if (!hasGetterAnnotation && new HandleGetter().fieldQualifiesForGetterGeneration(field)) { + //Check if the class has @Getter or @Data annotation. + + JavacNode containingType = field.up(); + if (containingType != null) for (JavacNode child : containingType.down()) { + if (child.getKind() == Kind.ANNOTATION && annotationTypeMatches(Data.class, child)) hasGetterAnnotation = true; + if (child.getKind() == Kind.ANNOTATION && annotationTypeMatches(Getter.class, child)) { + AnnotationValues<Getter> ann = Javac.createAnnotation(Getter.class, child); + if (ann.getInstance().value() == AccessLevel.NONE) return null; //Definitely WONT have a getter. + hasGetterAnnotation = true; } } } + if (hasGetterAnnotation) { + String getterName = toGetterName(decl); + return new GetterMethod(field.toName(getterName), decl.vartype); + } + return null; } @@ -298,13 +348,13 @@ public class JavacHandlerUtil { * @see #createFieldAccessor(TreeMaker, JavacNode) */ static JCExpression getFieldType(JavacNode field, boolean useFieldsDirectly) { - JCMethodDecl getter = useFieldsDirectly ? null : findGetter(field); + GetterMethod getter = useFieldsDirectly ? null : findGetter(field); if (getter == null) { return ((JCVariableDecl)field.get()).vartype; } - return getter.restype; + return getter.type; } /** @@ -315,7 +365,7 @@ public class JavacHandlerUtil { } static JCExpression createFieldAccessor(TreeMaker maker, JavacNode field, boolean useFieldsDirectly, JCExpression receiver) { - JCMethodDecl getter = useFieldsDirectly ? null : findGetter(field); + GetterMethod getter = useFieldsDirectly ? null : findGetter(field); if (getter == null) { return maker.Select(receiver, ((JCVariableDecl)field.get()).name); |