diff options
author | Reinier Zwitserloot <reinier@zwitserloot.com> | 2012-08-06 22:47:59 +0200 |
---|---|---|
committer | Reinier Zwitserloot <reinier@zwitserloot.com> | 2012-08-06 22:47:59 +0200 |
commit | 70317c73841d3e83b4b8008b68bea95753a5275f (patch) | |
tree | 1c66ab010930425aa673b3988aa4a5ad3ae1dd13 /src/core/lombok/javac/handlers | |
parent | d1b0242dc5e38cddd0e1ecc2a089c13e744d75d4 (diff) | |
download | lombok-70317c73841d3e83b4b8008b68bea95753a5275f.tar.gz lombok-70317c73841d3e83b4b8008b68bea95753a5275f.tar.bz2 lombok-70317c73841d3e83b4b8008b68bea95753a5275f.zip |
Added @Value and @FieldDefaults implementations for javac and ecj, the annotations including @NonFinal and @PackagePrivate, and some refactors. No tests yet.
Diffstat (limited to 'src/core/lombok/javac/handlers')
-rw-r--r-- | src/core/lombok/javac/handlers/HandleConstructor.java | 36 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java | 10 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleFieldDefaults.java | 111 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleGetter.java | 18 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSetter.java | 20 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleToString.java | 13 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleValue.java | 60 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleWither.java | 10 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacHandlerUtil.java | 29 |
9 files changed, 245 insertions, 62 deletions
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index d701b41e..b6c31f83 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -116,21 +116,25 @@ public class HandleConstructor { @SuppressWarnings("deprecation") boolean suppressConstructorProperties = ann.suppressConstructorProperties(); if (level == AccessLevel.NONE) return; - ListBuffer<JavacNode> fields = ListBuffer.lb(); - 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; - // Skip initialized final fields. - if (((fieldFlags & Flags.FINAL) != 0) && fieldDecl.init != null) continue; - fields.append(child); - } - new HandleConstructor().generateConstructor(typeNode, level, fields.toList(), staticName, false, suppressConstructorProperties, annotationNode); + new HandleConstructor().generateConstructor(typeNode, level, findAllFields(typeNode), staticName, false, suppressConstructorProperties, annotationNode); + } + } + + private static List<JavacNode> findAllFields(JavacNode typeNode) { + ListBuffer<JavacNode> fields = ListBuffer.lb(); + 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; + //Skip initialized final fields + boolean isFinal = (fieldFlags & Flags.FINAL) != 0; + if (!isFinal || fieldDecl.init == null) fields.append(child); } + return fields.toList(); } static boolean checkLegality(JavacNode typeNode, JavacNode errorNode, String name) { @@ -151,6 +155,10 @@ public class HandleConstructor { generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, skipIfConstructorExists, false, source); } + public void generateAllArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists, JavacNode source) { + generateConstructor(typeNode, level, findAllFields(typeNode), staticName, skipIfConstructorExists, false, source); + } + public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JavacNode> fields, String staticName, boolean skipIfConstructorExists, boolean suppressConstructorProperties, JavacNode source) { boolean staticConstrRequired = staticName != null && !staticName.equals(""); diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index 3b8c7af3..2b9b546d 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -107,13 +107,9 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas } public void generateEqualsAndHashCodeForType(JavacNode typeNode, JavacNode source) { - for (JavacNode child : typeNode.down()) { - if (child.getKind() == Kind.ANNOTATION) { - if (annotationTypeMatches(EqualsAndHashCode.class, child)) { - //The annotation will make it happen, so we can skip it. - return; - } - } + if (hasAnnotation(EqualsAndHashCode.class, typeNode)) { + //The annotation will make it happen, so we can skip it. + return; } generateMethods(typeNode, source, null, null, null, false, FieldAccess.GETTER); diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java new file mode 100644 index 00000000..a2dfb7ce --- /dev/null +++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2012 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 + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.javac.handlers; + +import static lombok.javac.handlers.JavacHandlerUtil.*; +import lombok.AccessLevel; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.experimental.FieldDefaults; +import lombok.experimental.NonFinal; +import lombok.experimental.PackagePrivate; +import lombok.javac.JavacAnnotationHandler; +import lombok.javac.JavacNode; + +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.JCDiagnostic.DiagnosticPosition; + +/** + * Handles the {@code lombok.FieldDefaults} annotation for eclipse. + */ +@ProviderFor(JavacAnnotationHandler.class) +public class HandleFieldDefaults extends JavacAnnotationHandler<FieldDefaults> { + public boolean generateFieldDefaultsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean makeFinal, boolean checkForTypeLevelFieldDefaults) { + if (checkForTypeLevelFieldDefaults) { + if (hasAnnotation(FieldDefaults.class, typeNode)) { + //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)) != 0; + + if (typeDecl == null || notAClass) { + errorNode.addError("@FieldDefaults is only supported on a class or an enum."); + 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; + + setFieldDefaultsForField(field, errorNode.get(), level, makeFinal); + } + + return true; + } + + public void setFieldDefaultsForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, boolean makeFinal) { + JCVariableDecl field = (JCVariableDecl) fieldNode.get(); + if (level != null && level != AccessLevel.NONE) { + if ((field.mods.flags & (Flags.PUBLIC | Flags.PRIVATE | Flags.PROTECTED)) == 0) { + if (!hasAnnotationAndDeleteIfNeccessary(PackagePrivate.class, fieldNode)) { + field.mods.flags |= toJavacModifier(level); + } + } + } + + if (makeFinal && (field.mods.flags & Flags.FINAL) == 0) { + if (!hasAnnotationAndDeleteIfNeccessary(NonFinal.class, fieldNode)) { + field.mods.flags |= Flags.FINAL; + } + } + } + + @Override public void handle(AnnotationValues<FieldDefaults> annotation, JCAnnotation ast, JavacNode annotationNode) { + deleteAnnotationIfNeccessary(annotationNode, FieldDefaults.class); + deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); + JavacNode node = annotationNode.up(); + FieldDefaults instance = annotation.getInstance(); + AccessLevel level = instance.level(); + boolean makeFinal = instance.makeFinal(); + + if (level == AccessLevel.NONE && !makeFinal) { + annotationNode.addError("This does nothing; provide either level or makeFinal or both."); + return; + } + + if (node == null) return; + + generateFieldDefaultsForType(node, annotationNode, level, makeFinal, false); + } +} diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index fa60504f..8a1fb4e1 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -73,11 +73,9 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; public class HandleGetter extends JavacAnnotationHandler<Getter> { public void generateGetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelGetter) { if (checkForTypeLevelGetter) { - if (typeNode != null) for (JavacNode child : typeNode.down()) { - if (annotationTypeMatches(Getter.class, child)) { - //The annotation will make it happen, so we can skip it. - return; - } + if (hasAnnotation(Getter.class, typeNode)) { + //The annotation will make it happen, so we can skip it. + return; } } @@ -122,13 +120,9 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { * @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 lazy) { - for (JavacNode child : fieldNode.down()) { - if (child.getKind() == Kind.ANNOTATION) { - if (annotationTypeMatches(Getter.class, child)) { - //The annotation will make it happen, so we can skip it. - return; - } - } + if (hasAnnotation(Getter.class, fieldNode)) { + //The annotation will make it happen, so we can skip it. + return; } createGetterForField(level, fieldNode, fieldNode, false, lazy); diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index a782e605..093b1947 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -68,13 +68,9 @@ import com.sun.tools.javac.util.Name; public class HandleSetter extends JavacAnnotationHandler<Setter> { public void 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 (annotationTypeMatches(Setter.class, child)) { - //The annotation will make it happen, so we can skip it. - return; - } - } + if (hasAnnotation(Setter.class, typeNode)) { + //The annotation will make it happen, so we can skip it. + return; } } @@ -118,13 +114,9 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { * @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) { - for (JavacNode child : fieldNode.down()) { - if (child.getKind() == Kind.ANNOTATION) { - if (annotationTypeMatches(Setter.class, child)) { - //The annotation will make it happen, so we can skip it. - return; - } - } + if (hasAnnotation(Setter.class, fieldNode)) { + //The annotation will make it happen, so we can skip it. + return; } createSetterForField(level, fieldNode, fieldNode, false); diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index 27641cf2..aad06b83 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011 The Project Lombok Authors. + * Copyright (C) 2009-2012 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 @@ -95,15 +95,12 @@ public class HandleToString extends JavacAnnotationHandler<ToString> { } public void generateToStringForType(JavacNode typeNode, JavacNode errorNode) { - for (JavacNode child : typeNode.down()) { - if (child.getKind() == Kind.ANNOTATION) { - if (annotationTypeMatches(ToString.class, child)) { - //The annotation will make it happen, so we can skip it. - return; - } - } + if (hasAnnotation(ToString.class, typeNode)) { + //The annotation will make it happen, so we can skip it. + return; } + boolean includeFieldNames = true; try { includeFieldNames = ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue(); diff --git a/src/core/lombok/javac/handlers/HandleValue.java b/src/core/lombok/javac/handlers/HandleValue.java new file mode 100644 index 00000000..fac017a8 --- /dev/null +++ b/src/core/lombok/javac/handlers/HandleValue.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2012 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 + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.javac.handlers; + +import static lombok.javac.handlers.JavacHandlerUtil.*; +import lombok.AccessLevel; +import lombok.core.AnnotationValues; +import lombok.experimental.Value; +import lombok.javac.JavacAnnotationHandler; +import lombok.javac.JavacNode; + +import org.mangosdk.spi.ProviderFor; + +import com.sun.tools.javac.tree.JCTree.JCAnnotation; + +/** + * Handles the {@code lombok.Value} annotation for javac. + */ +@ProviderFor(JavacAnnotationHandler.class) +public class HandleValue extends JavacAnnotationHandler<Value> { + @Override public void handle(AnnotationValues<Value> annotation, JCAnnotation ast, JavacNode annotationNode) { + deleteAnnotationIfNeccessary(annotationNode, Value.class); + JavacNode typeNode = annotationNode.up(); + boolean notAClass = !isClass(typeNode); + + if (notAClass) { + annotationNode.addError("@Value is only supported on a class."); + return; + } + + String staticConstructorName = annotation.getInstance().staticConstructor(); + + // TODO move this to the end OR move it to the top in eclipse. + new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, true, annotationNode); + new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true); + new HandleWither().generateWitherForType(typeNode, annotationNode, AccessLevel.PUBLIC, true); + new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode); + new HandleToString().generateToStringForType(typeNode, annotationNode); + new HandleFieldDefaults().generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true); + } +} diff --git a/src/core/lombok/javac/handlers/HandleWither.java b/src/core/lombok/javac/handlers/HandleWither.java index 61bf7bd0..6b4067b1 100644 --- a/src/core/lombok/javac/handlers/HandleWither.java +++ b/src/core/lombok/javac/handlers/HandleWither.java @@ -63,13 +63,9 @@ import com.sun.tools.javac.util.Name; public class HandleWither extends JavacAnnotationHandler<Wither> { public void generateWitherForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelWither) { if (checkForTypeLevelWither) { - if (typeNode != null) for (JavacNode child : typeNode.down()) { - if (child.getKind() == Kind.ANNOTATION) { - if (annotationTypeMatches(Wither.class, child)) { - //The annotation will make it happen, so we can skip it. - return; - } - } + if (hasAnnotation(Wither.class, typeNode)) { + //The annotation will make it happen, so we can skip it. + return; } } diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index b0f2a890..08542664 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -137,6 +137,35 @@ public class JavacHandlerUtil { return node; } + public static boolean hasAnnotation(Class<? extends Annotation> type, JavacNode node) { + return hasAnnotation(type, node, false); + } + + public static boolean hasAnnotationAndDeleteIfNeccessary(Class<? extends Annotation> type, JavacNode node) { + return hasAnnotation(type, node, true); + } + + private static boolean hasAnnotation(Class<? extends Annotation> type, JavacNode node, boolean delete) { + if (node == null) return false; + if (type == null) return false; + switch (node.getKind()) { + case ARGUMENT: + case FIELD: + case LOCAL: + case TYPE: + case METHOD: + for (JavacNode child : node.down()) { + if (annotationTypeMatches(type, child)) { + if (delete) deleteAnnotationIfNeccessary(child, type); + return true; + } + } + // intentional fallthrough + default: + return false; + } + } + /** * Checks if the Annotation AST Node provided is likely to be an instance of the provided annotation type. * |