diff options
author | Reinier Zwitserloot <reinier@zwitserloot.com> | 2010-07-17 06:54:33 +0200 |
---|---|---|
committer | Reinier Zwitserloot <reinier@zwitserloot.com> | 2010-07-17 06:54:33 +0200 |
commit | 32a23d77866093c5ba97eefdd5482868cf505de5 (patch) | |
tree | f97477bdc0cc3547a90e6d2798a1f34337f30798 /src/core/lombok | |
parent | 99f763a7294065333bee1d269dc28a744e072bcc (diff) | |
download | lombok-32a23d77866093c5ba97eefdd5482868cf505de5.tar.gz lombok-32a23d77866093c5ba97eefdd5482868cf505de5.tar.bz2 lombok-32a23d77866093c5ba97eefdd5482868cf505de5.zip |
Implements issue #129: @Getter and @Setter are now legal on entire types.
Diffstat (limited to 'src/core/lombok')
-rw-r--r-- | src/core/lombok/Getter.java | 7 | ||||
-rw-r--r-- | src/core/lombok/Setter.java | 7 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleData.java | 6 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleGetter.java | 44 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleSetter.java | 45 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleData.java | 7 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleGetter.java | 45 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSetter.java | 44 |
8 files changed, 173 insertions, 32 deletions
diff --git a/src/core/lombok/Getter.java b/src/core/lombok/Getter.java index fa84954c..bff21abc 100644 --- a/src/core/lombok/Getter.java +++ b/src/core/lombok/Getter.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -47,8 +47,11 @@ import java.lang.annotation.Target; * <p> * If any method named {@code getFoo}/{@code isFoo} exists, regardless of return type or parameters, no method is generated, * and instead a compiler warning is emitted. + * <p> + * This annotation can also be applied to a class, in which case it'll be as if all non-static fields that don't already have + * a {@code @Getter} annotation have the annotation. */ -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) public @interface Getter { /** diff --git a/src/core/lombok/Setter.java b/src/core/lombok/Setter.java index 778bb00d..6e0485c2 100644 --- a/src/core/lombok/Setter.java +++ b/src/core/lombok/Setter.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -44,8 +44,11 @@ import java.lang.annotation.Target; * * If any method named {@code setFoo} exists, regardless of return type or parameters, no method is generated, * and instead a compiler warning is emitted. + * <p> + * This annotation can also be applied to a class, in which case it'll be as if all non-static fields that don't already have + * a {@code Setter} annotation have the annotation. */ -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) public @interface Setter { /** diff --git a/src/core/lombok/eclipse/handlers/HandleData.java b/src/core/lombok/eclipse/handlers/HandleData.java index bbf1822e..68b4682c 100644 --- a/src/core/lombok/eclipse/handlers/HandleData.java +++ b/src/core/lombok/eclipse/handlers/HandleData.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -127,8 +127,8 @@ public class HandleData implements EclipseAnnotationHandler<Data> { } for (Map.Entry<EclipseNode, Boolean> field : gettersAndSetters.entrySet()) { - new HandleGetter().generateGetterForField(field.getKey(), annotationNode.get()); - if (field.getValue()) new HandleSetter().generateSetterForField(field.getKey(), annotationNode.get()); + new HandleGetter().generateGetterForField(field.getKey(), annotationNode.get(), AccessLevel.PUBLIC, true); + if (field.getValue()) new HandleSetter().generateSetterForField(field.getKey(), annotationNode.get(), AccessLevel.PUBLIC, true); } new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode); diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index d786f20f..43197ae4 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -62,7 +62,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) { + public void generateGetterForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level, boolean checkForTypeLevelGetter) { for (EclipseNode child : fieldNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (annotationTypeMatches(Getter.class, child)) { @@ -72,15 +72,49 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { } } - createGetterForField(AccessLevel.PUBLIC, fieldNode, fieldNode, pos, false); + if (checkForTypeLevelGetter) { + EclipseNode containingType = fieldNode.up(); + if (containingType != null) for (EclipseNode child : containingType.down()) { + if (child.getKind() == Kind.ANNOTATION) { + if (annotationTypeMatches(Getter.class, child)) { + //The annotation will make it happen, so we can skip it. + return; + } + } + } + } + + createGetterForField(level, fieldNode, fieldNode, pos, false); } public boolean handle(AnnotationValues<Getter> annotation, Annotation ast, EclipseNode annotationNode) { - EclipseNode fieldNode = annotationNode.up(); + EclipseNode node = annotationNode.up(); AccessLevel level = annotation.getInstance().value(); if (level == AccessLevel.NONE) return true; - return createGetterForField(level, fieldNode, annotationNode, annotationNode.get(), true); + if (node == null) return false; + if (node.getKind() == Kind.FIELD) { + return createGetterForField(level, node, annotationNode, annotationNode.get(), true); + } + if (node.getKind() == Kind.TYPE) { + TypeDeclaration typeDecl = null; + if (node.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) node.get(); + int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; + boolean notAClass = (modifiers & + (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0; + + if (typeDecl == null || notAClass) { + annotationNode.addError("@Getter is only supported on a class."); + return false; + } + + for (EclipseNode field : node.down()) { + if (field.getKind() != Kind.FIELD) continue; + generateGetterForField(field, ast, level, false); + } + return true; + } + return false; } private boolean createGetterForField(AccessLevel level, diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index 7760acd9..3dbbb2b5 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -69,7 +69,7 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> { * If not, the setter 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 generateSetterForField(EclipseNode fieldNode, ASTNode pos) { + public void generateSetterForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level, boolean checkForTypeLevelSetter) { for (EclipseNode child : fieldNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (annotationTypeMatches(Setter.class, child)) { @@ -79,16 +79,49 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> { } } - createSetterForField(AccessLevel.PUBLIC, fieldNode, fieldNode, pos, false); + if (checkForTypeLevelSetter) { + EclipseNode containingType = fieldNode.up(); + if (containingType != null) for (EclipseNode child : containingType.down()) { + if (child.getKind() == Kind.ANNOTATION) { + if (annotationTypeMatches(Setter.class, child)) { + //The annotation will make it happen, so we can skip it. + return; + } + } + } + } + + createSetterForField(level, fieldNode, fieldNode, pos, false); } public boolean handle(AnnotationValues<Setter> annotation, Annotation ast, EclipseNode annotationNode) { - EclipseNode fieldNode = annotationNode.up(); - if (fieldNode.getKind() != Kind.FIELD) return false; + EclipseNode node = annotationNode.up(); AccessLevel level = annotation.getInstance().value(); if (level == AccessLevel.NONE) return true; - return createSetterForField(level, fieldNode, annotationNode, annotationNode.get(), true); + if (node == null) return false; + if (node.getKind() == Kind.FIELD) { + return createSetterForField(level, node, annotationNode, annotationNode.get(), true); + } + if (node.getKind() == Kind.TYPE) { + TypeDeclaration typeDecl = null; + if (node.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) node.get(); + int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; + boolean notAClass = (modifiers & + (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0; + + if (typeDecl == null || notAClass) { + annotationNode.addError("@Setter is only supported on a class."); + return false; + } + + for (EclipseNode field : node.down()) { + if (field.getKind() != Kind.FIELD) continue; + generateSetterForField(field, ast, level, false); + } + return true; + } + return false; } private boolean createSetterForField(AccessLevel level, diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java index 88c0553c..efd86bba 100644 --- a/src/core/lombok/javac/handlers/HandleData.java +++ b/src/core/lombok/javac/handlers/HandleData.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,6 +32,7 @@ import java.lang.reflect.Modifier; import java.util.LinkedHashMap; import java.util.Map; +import lombok.AccessLevel; import lombok.Data; import lombok.core.AnnotationValues; import lombok.core.AST.Kind; @@ -107,8 +108,8 @@ public class HandleData implements JavacAnnotationHandler<Data> { } for (Map.Entry<JavacNode, Boolean> field : gettersAndSetters.entrySet()) { - new HandleGetter().generateGetterForField(field.getKey(), annotationNode.get()); - if (field.getValue()) new HandleSetter().generateSetterForField(field.getKey(), annotationNode.get()); + new HandleGetter().generateGetterForField(field.getKey(), annotationNode.get(), AccessLevel.PUBLIC, true); + if (field.getValue()) new HandleSetter().generateSetterForField(field.getKey(), annotationNode.get(), AccessLevel.PUBLIC, true); } new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode); diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 14570187..5af05c7c 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,6 +37,7 @@ import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBlock; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCStatement; @@ -66,7 +67,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) { + public void generateGetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, boolean checkForTypeLevelGetter) { for (JavacNode child : fieldNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (Javac.annotationTypeMatches(Getter.class, child)) { @@ -76,17 +77,49 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { } } - createGetterForField(AccessLevel.PUBLIC, fieldNode, fieldNode, false); + 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); } @Override public boolean handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) { markAnnotationAsProcessed(annotationNode, Getter.class); - JavacNode fieldNode = annotationNode.up(); + JavacNode node = annotationNode.up(); AccessLevel level = annotation.getInstance().value(); - if (level == AccessLevel.NONE) return true; - return createGetterForField(level, fieldNode, annotationNode, true); + if (node == null) return false; + if (node.getKind() == Kind.FIELD) { + return createGetterForField(level, node, 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 false; } private boolean createGetterForField(AccessLevel level, diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index e7f20f6c..a3822daa 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,6 +46,7 @@ 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; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; @@ -76,7 +77,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) { + public void generateSetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, boolean checkForTypeLevelSetter) { for (JavacNode child : fieldNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (Javac.annotationTypeMatches(Setter.class, child)) { @@ -86,17 +87,50 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { } } - createSetterForField(AccessLevel.PUBLIC, fieldNode, fieldNode, false); + 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); } @Override public boolean handle(AnnotationValues<Setter> annotation, JCAnnotation ast, JavacNode annotationNode) { markAnnotationAsProcessed(annotationNode, Setter.class); - JavacNode fieldNode = annotationNode.up(); + JavacNode node = annotationNode.up(); AccessLevel level = annotation.getInstance().value(); if (level == AccessLevel.NONE) return true; - return createSetterForField(level, fieldNode, annotationNode, true); + if (node == null) return false; + if (node.getKind() == Kind.FIELD) { + return createSetterForField(level, node, 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 false; } private boolean createSetterForField(AccessLevel level, |