aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/javac
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lombok/javac')
-rw-r--r--src/core/lombok/javac/handlers/HandleDelegate.java67
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java27
2 files changed, 77 insertions, 17 deletions
diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java
index f6a81474..3674ae5a 100644
--- a/src/core/lombok/javac/handlers/HandleDelegate.java
+++ b/src/core/lombok/javac/handlers/HandleDelegate.java
@@ -94,23 +94,42 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
@Override public void handle(AnnotationValues<Delegate> annotation, JCAnnotation ast, JavacNode annotationNode) {
deleteAnnotationIfNeccessary(annotationNode, Delegate.class);
- if (annotationNode.up().getKind() != Kind.FIELD) {
- // As the annotation is legal on fields only, javac itself will take care of printing an error message for this.
+
+ Type delegateType;
+ Name delegateName = annotationNode.toName(annotationNode.up().getName());
+ DelegateReceiver delegateReceiver;
+ JavacResolution reso = new JavacResolution(annotationNode.getContext());
+ if (annotationNode.up().getKind() == Kind.FIELD) {
+ delegateReceiver = DelegateReceiver.FIELD;
+ delegateType = annotationNode.up().get().type;
+ if (delegateType == null) reso.resolveClassMember(annotationNode.up());
+ delegateType = annotationNode.up().get().type;
+ } else if (annotationNode.up().getKind() == Kind.METHOD) {
+ if (!(annotationNode.up().get() instanceof JCMethodDecl)) {
+ annotationNode.addError("@Delegate is legal only on no-argument methods.");
+ return;
+ }
+ JCMethodDecl methodDecl = (JCMethodDecl) annotationNode.up().get();
+ if (!methodDecl.params.isEmpty()) {
+ annotationNode.addError("@Delegate is legal only on no-argument methods.");
+ return;
+ }
+ delegateReceiver = DelegateReceiver.METHOD;
+ delegateType = methodDecl.restype.type;
+ if (delegateType == null) reso.resolveClassMember(annotationNode.up());
+ delegateType = methodDecl.restype.type;
+ } else {
+ // As the annotation is legal on fields and methods only, javac itself will take care of printing an error message for this.
return;
}
List<Object> delegateTypes = annotation.getActualExpressions("types");
List<Object> excludeTypes = annotation.getActualExpressions("excludes");
- JavacResolution reso = new JavacResolution(annotationNode.getContext());
List<Type> toDelegate = new ArrayList<Type>();
List<Type> toExclude = new ArrayList<Type>();
if (delegateTypes.isEmpty()) {
- Type type = ((JCVariableDecl)annotationNode.up().get()).type;
- if (type == null) reso.resolveClassMember(annotationNode.up());
- //TODO I'm fairly sure the above line (and that entire method) does effectively bupkis!
- type = ((JCVariableDecl)annotationNode.up().get()).type;
- if (type != null) toDelegate.add(type);
+ if (delegateType != null) toDelegate.add(delegateType);
} else {
for (Object dt : delegateTypes) {
if (dt instanceof JCFieldAccess && ((JCFieldAccess)dt).name.toString().equals("class")) {
@@ -167,15 +186,13 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
}
}
- Name delegateFieldName = annotationNode.toName(annotationNode.up().getName());
-
- for (MethodSig sig : signaturesToDelegate) generateAndAdd(sig, annotationNode, delegateFieldName);
+ for (MethodSig sig : signaturesToDelegate) generateAndAdd(sig, annotationNode, delegateName, delegateReceiver);
}
- private void generateAndAdd(MethodSig sig, JavacNode annotation, Name delegateFieldName) {
+ private void generateAndAdd(MethodSig sig, JavacNode annotation, Name delegateName, DelegateReceiver delegateReceiver) {
List<JCMethodDecl> toAdd = new ArrayList<JCMethodDecl>();
try {
- toAdd.add(createDelegateMethod(sig, annotation, delegateFieldName));
+ toAdd.add(createDelegateMethod(sig, annotation, delegateName, delegateReceiver));
} catch (TypeNotConvertibleException e) {
annotation.addError("Can't create delegate method for " + sig.name + ": " + e.getMessage());
return;
@@ -240,7 +257,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
}
}
- private JCMethodDecl createDelegateMethod(MethodSig sig, JavacNode annotation, Name delegateFieldName) throws TypeNotConvertibleException, CantMakeDelegates {
+ private JCMethodDecl createDelegateMethod(MethodSig sig, JavacNode annotation, Name delegateName, DelegateReceiver delegateReceiver) throws TypeNotConvertibleException, CantMakeDelegates {
/* public <T, U, ...> ReturnType methodName(ParamType1 name1, ParamType2 name2, ...) throws T1, T2, ... {
* (return) delegate.<T, U>methodName(name1, name2);
* }
@@ -288,9 +305,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
args.append(maker.Ident(name));
}
- JCExpression delegateFieldRef = maker.Select(maker.Ident(annotation.toName("this")), delegateFieldName);
-
- JCExpression delegateCall = maker.Apply(toList(typeArgs), maker.Select(delegateFieldRef, sig.name), toList(args));
+ JCExpression delegateCall = maker.Apply(toList(typeArgs), maker.Select(delegateReceiver.get(annotation, delegateName), sig.name), toList(args));
JCStatement body = useReturn ? maker.Return(delegateCall) : maker.Exec(delegateCall);
JCBlock bodyBlock = maker.Block(0, com.sun.tools.javac.util.List.of(body));
@@ -367,4 +382,22 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
binding = types.erasure(binding);
return binding.toString();
}
+
+ private enum DelegateReceiver {
+ METHOD {
+ public JCExpression get(final JavacNode node, final Name name) {
+ com.sun.tools.javac.util.List<JCExpression> nilExprs = com.sun.tools.javac.util.List.nil();
+ final TreeMaker maker = node.getTreeMaker();
+ return maker.Apply(nilExprs, maker.Select(maker.Ident(node.toName("this")), name), nilExprs);
+ }
+ },
+ FIELD {
+ public JCExpression get(final JavacNode node, final Name name) {
+ final TreeMaker maker = node.getTreeMaker();
+ return maker.Select(maker.Ident(node.toName("this")), name);
+ }
+ };
+
+ public abstract JCExpression get(final JavacNode node, final Name name);
+ }
}
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java
index fe3b86a4..c9d67d7f 100644
--- a/src/core/lombok/javac/handlers/HandleGetter.java
+++ b/src/core/lombok/javac/handlers/HandleGetter.java
@@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.Map;
import lombok.AccessLevel;
+import lombok.Delegate;
import lombok.Getter;
import lombok.core.AnnotationValues;
import lombok.core.TransformationsUtil;
@@ -240,16 +241,42 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
List<JCAnnotation> nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN);
List<JCAnnotation> nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN);
+ List<JCAnnotation> delegates = findDelegatesAndRemoveFromField(field);
+
List<JCAnnotation> annsOnMethod = nonNulls.appendList(nullables);
JCMethodDecl decl = recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source);
if (toClearOfMarkers != null) recursiveSetGeneratedBy(toClearOfMarkers, null);
+ decl.mods.annotations = decl.mods.annotations.appendList(delegates);
return decl;
}
+ private static List<JCAnnotation> findDelegatesAndRemoveFromField(JavacNode field) {
+ JCVariableDecl fieldNode = (JCVariableDecl) field.get();
+
+ List<JCAnnotation> delegates = List.nil();
+ for (JCAnnotation annotation : fieldNode.mods.annotations) {
+ if (typeMatches(Delegate.class, field, annotation.annotationType)) {
+ delegates = delegates.append(annotation);
+ }
+ }
+
+ if (!delegates.isEmpty()) {
+ ListBuffer<JCAnnotation> withoutDelegates = ListBuffer.lb();
+ for (JCAnnotation annotation : fieldNode.mods.annotations) {
+ if (!delegates.contains(annotation)) {
+ withoutDelegates.append(annotation);
+ }
+ }
+ fieldNode.mods.annotations = withoutDelegates.toList();
+ field.rebuild();
+ }
+ return delegates;
+ }
+
private List<JCStatement> createSimpleGetterBody(TreeMaker treeMaker, JavacNode field) {
return List.<JCStatement>of(treeMaker.Return(createFieldAccessor(treeMaker, field, FieldAccess.ALWAYS_FIELD)));
}