aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/lombok/Getter.java14
-rw-r--r--src/core/lombok/Setter.java22
-rw-r--r--src/core/lombok/eclipse/Eclipse.java29
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java41
-rw-r--r--src/core/lombok/eclipse/handlers/HandleConstructor.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleGetter.java21
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSetter.java32
-rw-r--r--src/core/lombok/javac/handlers/HandleData.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java26
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java41
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java40
11 files changed, 205 insertions, 69 deletions
diff --git a/src/core/lombok/Getter.java b/src/core/lombok/Getter.java
index bff21abc..2c686595 100644
--- a/src/core/lombok/Getter.java
+++ b/src/core/lombok/Getter.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -58,4 +58,16 @@ public @interface Getter {
* If you want your setter to be non-public, you can specify an alternate access level here.
*/
lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
+
+ /**
+ * If you want your getter method to have additional annotations, you can specify them here.<br/>
+ * If the {code @Getter} is put on a type, {code onMethod} may not be specified.
+ */
+ AnyAnnotation[] onMethod() default {};
+
+ /**
+ * Placeholder annotation to enable the placement of annotations on the getter method.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @interface AnyAnnotation {}
}
diff --git a/src/core/lombok/Setter.java b/src/core/lombok/Setter.java
index 6e0485c2..cd549fed 100644
--- a/src/core/lombok/Setter.java
+++ b/src/core/lombok/Setter.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -55,4 +55,22 @@ public @interface Setter {
* If you want your setter to be non-public, you can specify an alternate access level here.
*/
lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
-}
+
+ /**
+ * If you want your setter method to have additional annotations, you can specify them here.
+ * If the {code @Setter} is put on a type, {code onMethod} may not be specified.
+ */
+ AnyAnnotation[] onMethod() default {};
+
+ /**
+ * If you want the parameter of your setter to have additional annotations, you can specify them here.
+ * If the {code @Setter} is put on a type, {code onParam} may not be specified.
+ */
+ AnyAnnotation[] onParam() default {};
+
+ /**
+ * Placeholder annotation to enable the placement of annotations on the setter method or its parameter.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @interface AnyAnnotation {}
+} \ No newline at end of file
diff --git a/src/core/lombok/eclipse/Eclipse.java b/src/core/lombok/eclipse/Eclipse.java
index f5b80552..8354215b 100644
--- a/src/core/lombok/eclipse/Eclipse.java
+++ b/src/core/lombok/eclipse/Eclipse.java
@@ -452,23 +452,22 @@ public class Eclipse {
}
- public static Annotation[] copyAnnotations(Annotation[] annotations, ASTNode source) {
- return copyAnnotations(annotations, null, source);
- }
+ private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
- public static Annotation[] copyAnnotations(Annotation[] annotations1, Annotation[] annotations2, ASTNode source) {
- if (annotations1 == null && annotations2 == null) return null;
- if (annotations1 == null) annotations1 = new Annotation[0];
- if (annotations2 == null) annotations2 = new Annotation[0];
- Annotation[] outs = new Annotation[annotations1.length + annotations2.length];
- int idx = 0;
- for (Annotation annotation : annotations1) {
- outs[idx++] = copyAnnotation(annotation, source);
- }
- for (Annotation annotation : annotations2) {
- outs[idx++] = copyAnnotation(annotation, source);
+ public static Annotation[] copyAnnotations(ASTNode source, Annotation[]... allAnnotations) {
+ boolean allNull = true;
+
+ List<Annotation> result = new ArrayList<Annotation>();
+ for (Annotation[] annotations : allAnnotations) {
+ if (annotations != null) {
+ allNull = false;
+ for (Annotation annotation : annotations) {
+ result.add(copyAnnotation(annotation, source));
+ }
+ }
}
- return outs;
+ if (allNull) return null;
+ return result.toArray(EMPTY_ANNOTATION_ARRAY);
}
public static Annotation copyAnnotation(Annotation annotation, ASTNode source) {
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index 0db0085f..f252793d 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -32,8 +32,8 @@ import java.util.regex.Pattern;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
-import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.AST.Kind;
import lombok.core.handlers.TransformationsUtil;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseNode;
@@ -43,6 +43,7 @@ import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.Clinit;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
@@ -51,9 +52,11 @@ import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
+import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
+import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
@@ -611,6 +614,42 @@ public class EclipseHandlerUtil {
return problematic;
}
+ private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
+ static Annotation[] getAndRemoveAnnotationParameter(Annotation annotation, String annotationName) {
+
+ List<Annotation> result = new ArrayList<Annotation>();
+ if (annotation instanceof NormalAnnotation) {
+ NormalAnnotation normalAnnotation = (NormalAnnotation)annotation;
+ MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
+ List<MemberValuePair> pairs = new ArrayList<MemberValuePair>();
+ if (memberValuePairs != null) for (MemberValuePair memberValuePair : memberValuePairs) {
+ if (annotationName.equals(new String(memberValuePair.name))) {
+ Expression value = memberValuePair.value;
+ if (value instanceof ArrayInitializer) {
+ ArrayInitializer array = (ArrayInitializer) value;
+ for(Expression expression : array.expressions) {
+ if (expression instanceof Annotation) {
+ result.add((Annotation)expression);
+ }
+ }
+ }
+ else if (value instanceof Annotation) {
+ result.add((Annotation)value);
+ }
+ continue;
+ }
+ pairs.add(memberValuePair);
+ }
+
+ if (!result.isEmpty()) {
+ normalAnnotation.memberValuePairs = pairs.isEmpty() ? null : pairs.toArray(new MemberValuePair[0]);
+ return result.toArray(EMPTY_ANNOTATION_ARRAY);
+ }
+ }
+
+ return EMPTY_ANNOTATION_ARRAY;
+ }
+
static NameReference createNameReference(String name, Annotation source) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long)pS << 32 | pE;
diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java
index 91733839..826d4c1c 100644
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -247,7 +247,7 @@ public class HandleConstructor {
Statement nullCheck = generateNullCheck(field, source);
if (nullCheck != null) nullChecks.add(nullCheck);
}
- Annotation[] copiedAnnotations = copyAnnotations(nonNulls, nullables, source);
+ Annotation[] copiedAnnotations = copyAnnotations(source, nonNulls, nullables);
if (copiedAnnotations.length != 0) parameter.annotations = copiedAnnotations;
params.add(parameter);
}
@@ -316,9 +316,7 @@ public class HandleConstructor {
Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL);
Eclipse.setGeneratedBy(parameter, source);
- Annotation[] copiedAnnotations = copyAnnotations(
- findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN),
- findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), source);
+ Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN));
if (copiedAnnotations.length != 0) parameter.annotations = copiedAnnotations;
params.add(new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL));
}
diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java
index 1a2a10ac..38a6b468 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);
+ if (fieldQualifiesForGetterGeneration(field)) generateGetterForField(field, pos.get(), level, null);
}
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) {
+ public void generateGetterForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level, Annotation[] onMethod) {
for (EclipseNode child : fieldNode.down()) {
if (child.getKind() == Kind.ANNOTATION) {
if (annotationTypeMatches(Getter.class, child)) {
@@ -113,7 +113,7 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> {
}
}
- createGetterForField(level, fieldNode, fieldNode, pos, false);
+ createGetterForField(level, fieldNode, fieldNode, pos, false, onMethod);
}
public boolean handle(AnnotationValues<Getter> annotation, Annotation ast, EclipseNode annotationNode) {
@@ -122,24 +122,27 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> {
if (level == AccessLevel.NONE) 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);
+ return createGetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod);
}
if (node.getKind() == Kind.TYPE) {
+ if (onMethod != null && onMethod.length != 0) annotationNode.addError("'onMethod' 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) {
+ private boolean createGetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod) {
for (EclipseNode fieldNode : fieldNodes) {
- createGetterForField(level, fieldNode, errorNode, source, whineIfExists);
+ createGetterForField(level, fieldNode, errorNode, source, whineIfExists, onMethod);
}
return true;
}
private boolean createGetterForField(AccessLevel level,
- EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists) {
+ EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod) {
if (fieldNode.getKind() != Kind.FIELD) {
errorNode.addError("@Getter is only supported on a class or a field.");
return true;
@@ -172,9 +175,7 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> {
}
MethodDeclaration method = generateGetter((TypeDeclaration) fieldNode.up().get(), fieldNode, getterName, modifier, source);
- Annotation[] copiedAnnotations = copyAnnotations(
- findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN),
- findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), source);
+ Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), onMethod);
if (copiedAnnotations.length != 0) {
method.annotations = copiedAnnotations;
}
diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java
index 7c4aaabb..48e688fd 100644
--- a/src/core/lombok/eclipse/handlers/HandleSetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleSetter.java
@@ -57,6 +57,7 @@ import org.mangosdk.spi.ProviderFor;
*/
@ProviderFor(EclipseAnnotationHandler.class)
public class HandleSetter implements EclipseAnnotationHandler<Setter> {
+ private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY = new Annotation[0];
public boolean generateSetterForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean checkForTypeLevelSetter) {
if (checkForTypeLevelSetter) {
if (typeNode != null) for (EclipseNode child : typeNode.down()) {
@@ -90,7 +91,7 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {
//Skip final fields.
if ((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0) continue;
- generateSetterForField(field, pos.get(), level);
+ generateSetterForField(field, pos.get(), level, EMPTY_ANNOTATIONS_ARRAY, EMPTY_ANNOTATIONS_ARRAY);
}
return true;
}
@@ -107,7 +108,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, AccessLevel level) {
+ public void generateSetterForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level, Annotation[] onMethod , Annotation[] onParam) {
for (EclipseNode child : fieldNode.down()) {
if (child.getKind() == Kind.ANNOTATION) {
if (annotationTypeMatches(Setter.class, child)) {
@@ -117,7 +118,7 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {
}
}
- createSetterForField(level, fieldNode, fieldNode, pos, false);
+ createSetterForField(level, fieldNode, fieldNode, pos, false, onMethod, onParam);
}
public boolean handle(AnnotationValues<Setter> annotation, Annotation ast, EclipseNode annotationNode) {
@@ -126,24 +127,31 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {
if (level == AccessLevel.NONE) return true;
if (node == null) return false;
+
+ Annotation[] onMethod = getAndRemoveAnnotationParameter(ast, "onMethod");
+ Annotation[] onParam = getAndRemoveAnnotationParameter(ast, "onParam");
+
if (node.getKind() == Kind.FIELD) {
- return createSetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true);
+ return createSetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod, onParam);
+
}
if (node.getKind() == Kind.TYPE) {
+ if (onMethod != null && onMethod.length != 0) annotationNode.addError("'onMethod' is not supported for @Setter on a type.");
+ if (onParam != null && onParam.length != 0) annotationNode.addError("'onParam' is not supported for @Setter on a type.");
return generateSetterForType(node, annotationNode, level, false);
}
return false;
}
- private boolean createSetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists) {
+ private boolean createSetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod , Annotation[] onParam) {
for (EclipseNode fieldNode : fieldNodes) {
- createSetterForField(level, fieldNode, errorNode, source, whineIfExists);
+ createSetterForField(level, fieldNode, errorNode, source, whineIfExists, onMethod, onParam);
}
return true;
}
private boolean createSetterForField(AccessLevel level,
- EclipseNode fieldNode, EclipseNode errorNode, ASTNode pos, boolean whineIfExists) {
+ EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod , Annotation[] onParam) {
if (fieldNode.getKind() != Kind.FIELD) {
errorNode.addError("@Setter is only supported on a class or a field.");
return true;
@@ -167,14 +175,18 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {
//continue with creating the setter
}
- MethodDeclaration method = generateSetter((TypeDeclaration) fieldNode.up().get(), fieldNode, setterName, modifier, pos);
+ MethodDeclaration method = generateSetter((TypeDeclaration) fieldNode.up().get(), fieldNode, setterName, modifier, source, onParam);
+ Annotation[] copiedAnnotations = copyAnnotations(source, onMethod);
+ if (copiedAnnotations.length != 0) {
+ method.annotations = copiedAnnotations;
+ }
injectMethod(fieldNode.up(), method);
return true;
}
- private MethodDeclaration generateSetter(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source) {
+ private MethodDeclaration generateSetter(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source, Annotation[] onParam) {
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long)pS << 32 | pE;
@@ -212,7 +224,7 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {
if (nullCheck != null) method.statements = new Statement[] { nullCheck, assignment };
else method.statements = new Statement[] { assignment };
}
- Annotation[] copiedAnnotations = copyAnnotations(nonNulls, nullables, source);
+ Annotation[] copiedAnnotations = copyAnnotations(source, nonNulls, nullables, onParam);
if (copiedAnnotations.length != 0) param.annotations = copiedAnnotations;
return method;
}
diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java
index 2087c133..6767f073 100644
--- a/src/core/lombok/javac/handlers/HandleData.java
+++ b/src/core/lombok/javac/handlers/HandleData.java
@@ -33,6 +33,8 @@ 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.JCExpression;
+import com.sun.tools.javac.util.List;
/**
* Handles the {@code lombok.Data} annotation for javac.
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java
index ac3a16a1..79e842dc 100644
--- a/src/core/lombok/javac/handlers/HandleGetter.java
+++ b/src/core/lombok/javac/handlers/HandleGetter.java
@@ -78,7 +78,7 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {
}
for (JavacNode field : typeNode.down()) {
- if (fieldQualifiesForGetterGeneration(field)) generateGetterForField(field, errorNode.get(), level);
+ if (fieldQualifiesForGetterGeneration(field)) generateGetterForField(field, errorNode.get(), level, List.<JCExpression>nil());
}
return true;
@@ -109,7 +109,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) {
+ public void generateGetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, List<JCExpression> onMethod) {
for (JavacNode child : fieldNode.down()) {
if (child.getKind() == Kind.ANNOTATION) {
if (Javac.annotationTypeMatches(Getter.class, child)) {
@@ -119,7 +119,7 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {
}
}
- createGetterForField(level, fieldNode, fieldNode, false);
+ createGetterForField(level, fieldNode, fieldNode, false, onMethod);
}
@Override public boolean handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) {
@@ -131,25 +131,28 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {
if (level == AccessLevel.NONE) return true;
if (node == null) return false;
+
+ List<JCExpression> onMethod = getAndRemoveAnnotationParameter(ast, "onMethod");
if (node.getKind() == Kind.FIELD) {
- return createGetterForFields(level, fields, annotationNode, true);
+ return createGetterForFields(level, fields, annotationNode, true, onMethod);
}
if (node.getKind() == Kind.TYPE) {
+ if (!onMethod.isEmpty()) annotationNode.addError("'onMethod' is not supported for @Getter on a type.");
return generateGetterForType(node, annotationNode, level, false);
}
return false;
}
- private boolean createGetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists) {
+ private boolean createGetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod) {
for (JavacNode fieldNode : fieldNodes) {
- createGetterForField(level, fieldNode, errorNode, whineIfExists);
+ createGetterForField(level, fieldNode, errorNode, whineIfExists, onMethod);
}
return true;
}
private boolean createGetterForField(AccessLevel level,
- JavacNode fieldNode, JavacNode errorNode, boolean whineIfExists) {
+ JavacNode fieldNode, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod) {
if (fieldNode.getKind() != Kind.FIELD) {
errorNode.addError("@Getter is only supported on a class or a field.");
return true;
@@ -178,12 +181,12 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {
long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC);
- injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker()));
+ injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), onMethod));
return true;
}
- private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker) {
+ private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker, List<JCExpression> onMethod) {
JCVariableDecl fieldNode = (JCVariableDecl) field.get();
JCExpression fieldRef = createFieldAccessor(treeMaker, field, true);
JCStatement returnStatement = treeMaker.Return(fieldRef);
@@ -199,7 +202,10 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {
List<JCAnnotation> nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN);
List<JCAnnotation> nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN);
- return treeMaker.MethodDef(treeMaker.Modifiers(access, nonNulls.appendList(nullables)), methodName, methodType,
+
+ List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod).appendList(nonNulls).appendList(nullables);
+
+ return treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue);
}
}
diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java
index 98b68e4a..af6f546d 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.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.AST.Kind;
import lombok.core.handlers.TransformationsUtil;
import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
@@ -44,6 +44,7 @@ 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;
@@ -53,10 +54,9 @@ 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.
@@ -95,7 +95,7 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {
//Skip final fields.
if ((fieldDecl.mods.flags & Flags.FINAL) != 0) continue;
- generateSetterForField(field, errorNode.get(), level);
+ generateSetterForField(field, errorNode.get(), level, List.<JCExpression>nil(), List.<JCExpression>nil());
}
return true;
}
@@ -115,7 +115,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) {
+ public void generateSetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, List<JCExpression> onMethod, List<JCExpression> onParam) {
for (JavacNode child : fieldNode.down()) {
if (child.getKind() == Kind.ANNOTATION) {
if (Javac.annotationTypeMatches(Setter.class, child)) {
@@ -125,7 +125,7 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {
}
}
- createSetterForField(level, fieldNode, fieldNode, false);
+ createSetterForField(level, fieldNode, fieldNode, false, onMethod, onParam);
}
@Override public boolean handle(AnnotationValues<Setter> annotation, JCAnnotation ast, JavacNode annotationNode) {
@@ -136,27 +136,36 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {
AccessLevel level = annotation.getInstance().value();
if (level == AccessLevel.NONE) return true;
-
if (node == null) return false;
+
+ List<JCExpression> onParamList = getAndRemoveAnnotationParameter(ast, "onParam");
+ List<JCExpression> onMethodList = getAndRemoveAnnotationParameter(ast, "onMethod");
+
if (node.getKind() == Kind.FIELD) {
- return createSetterForFields(level, fields, annotationNode, true);
+ return createSetterForFields(level, fields, annotationNode, true, onMethodList, onParamList);
}
if (node.getKind() == Kind.TYPE) {
+ if (!onMethodList.isEmpty()) annotationNode.addError("'onMethod' is not supported for @Setter on a type.");
+ if (!onParamList.isEmpty()) annotationNode.addError("'onParam' is not supported for @Setter on a type.");
+
return generateSetterForType(node, annotationNode, level, false);
}
return false;
}
- private boolean createSetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists) {
+ private boolean createSetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists,
+ List<JCExpression> onMethod, List<JCExpression> onParam) {
+
for (JavacNode fieldNode : fieldNodes) {
- createSetterForField(level, fieldNode, errorNode, whineIfExists);
+ createSetterForField(level, fieldNode, errorNode, whineIfExists, onMethod, onParam);
}
return true;
}
private boolean createSetterForField(AccessLevel level,
- JavacNode fieldNode, JavacNode errorNode, boolean whineIfExists) {
+ JavacNode fieldNode, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod, List<JCExpression> onParam) {
+
if (fieldNode.getKind() != Kind.FIELD) {
fieldNode.addError("@Setter is only supported on a class or a field.");
return true;
@@ -180,12 +189,12 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {
long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC);
- injectMethod(fieldNode.up(), createSetter(access, fieldNode, fieldNode.getTreeMaker()));
+ injectMethod(fieldNode.up(), createSetter(access, fieldNode, fieldNode.getTreeMaker(), onMethod, onParam));
return true;
}
- private JCMethodDecl createSetter(long access, JavacNode field, TreeMaker treeMaker) {
+ private JCMethodDecl createSetter(long access, JavacNode field, TreeMaker treeMaker, List<JCExpression> onMethod, List<JCExpression> onParam) {
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
JCExpression fieldRef = createFieldAccessor(treeMaker, field, true);
@@ -205,7 +214,9 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {
JCBlock methodBody = treeMaker.Block(0, statements);
Name methodName = field.toName(toSetterName(fieldDecl));
- JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.FINAL, nonNulls.appendList(nullables)), fieldDecl.name, fieldDecl.vartype, null);
+ List<JCAnnotation> annsOnParam = copyAnnotations(onParam);
+ annsOnParam = annsOnParam.appendList(nonNulls).appendList(nullables);
+ JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.FINAL, annsOnParam), fieldDecl.name, fieldDecl.vartype, null);
//WARNING: Do not use field.getSymbolTable().voidType - that field has gone through non-backwards compatible API changes within javac1.6.
JCExpression methodType = treeMaker.Type(new JCNoType(TypeTags.VOID));
@@ -214,7 +225,7 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {
List<JCExpression> throwsClauses = List.nil();
JCExpression annotationMethodDefaultValue = null;
- return treeMaker.MethodDef(treeMaker.Modifiers(access, List.<JCAnnotation>nil()), methodName, methodType,
+ return treeMaker.MethodDef(treeMaker.Modifiers(access, copyAnnotations(onMethod)), methodName, methodType,
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue);
}
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index 5dacf2ca..bf356853 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -42,12 +42,15 @@ import com.sun.tools.javac.tree.JCTree.JCLiteral;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
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.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCImport;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
+import com.sun.tools.javac.tree.JCTree.JCNewArray;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
@@ -567,4 +570,39 @@ public class JavacHandlerUtil {
return problematic;
}
+
+ static List<JCExpression> getAndRemoveAnnotationParameter(JCAnnotation ast, String parameterName) {
+ List<JCExpression> params = List.nil();
+ List<JCExpression> result = List.nil();
+
+ for (JCExpression param : ast.args) {
+ if (param instanceof JCAssign) {
+ JCAssign assign = (JCAssign) param;
+ if (assign.lhs instanceof JCIdent) {
+ JCIdent ident = (JCIdent) assign.lhs;
+ if (parameterName.equals(ident.name.toString())) {
+ if (assign.rhs instanceof JCNewArray) {
+ result = ((JCNewArray) assign.rhs).elems;
+ } else {
+ result = result.append(assign.rhs);
+ }
+ continue;
+ }
+ }
+ }
+
+ params = params.append(param);
+ }
+ ast.args = params;
+ return result;
+ }
+
+ static List<JCAnnotation> copyAnnotations(List<JCExpression> in) {
+ List<JCAnnotation> out = List.nil();
+ for (JCExpression expr : in) {
+ if (!(expr instanceof JCAnnotation)) continue;
+ out = out.append((JCAnnotation) expr.clone());
+ }
+ return out;
+ }
}