mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 04:16:19 +00:00
Implements issue #129: @Getter and @Setter are now legal on entire types.
This commit is contained in:
1 parent
99f763a729
commit
32a23d7786
9 files changed
+174
-32
No files matched your search
@@ -9,6 +9,7 @@ Lombok Changelog
|
||||
* FEATURE: If `tools.jar` isn't found (required when running _delombok_), now a useful error message is generated. The search for `tools.jar` now also looks in `JAVA_HOME`.
|
||||
* FEATURE: FindBugs' `@CheckForNull` is now copied from a field to a setter's parameter and the getter method just like `@Nullable`. [Issue #128](http://code.google.com/p/projectlombok/issues/detail?id=128)
|
||||
* BUILD: dependencies are now fetched automatically via ivy, and most dependencies now include sources by default, which is particularly handy for those working on the lombok sources themselves.
|
||||
* FEATURE: Adding `@Getter` or `@Setter` to a class is now legal and is like adding those annotations to every non-static field in it. [Issue #129](http://code.google.com/p/projectlombok/issues/detail?id=129)
|
||||
|
||||
### v0.9.2 "Hailbunny" (December 15th, 2009)
|
||||
* preliminary support for lombok on NetBeans! - thanks go to Jan Lahoda from NetBeans. [Issue #20](http://code.google.com/p/projectlombok/issues/detail?id=20)
|
||||
|
||||
@@ -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 {
|
||||
/**
|
||||
|
||||
@@ -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 {
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user