aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/lombok/Delegate.java2
-rw-r--r--src/core/lombok/bytecode/ClassFileMetaData.java13
-rw-r--r--src/core/lombok/core/Version.java2
-rw-r--r--src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java3
-rw-r--r--src/core/lombok/eclipse/handlers/HandleGetter.java23
-rw-r--r--src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java11
-rw-r--r--src/core/lombok/javac/handlers/HandleDelegate.java67
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java27
8 files changed, 118 insertions, 30 deletions
diff --git a/src/core/lombok/Delegate.java b/src/core/lombok/Delegate.java
index 6d03d649..9ab9acae 100644
--- a/src/core/lombok/Delegate.java
+++ b/src/core/lombok/Delegate.java
@@ -40,7 +40,7 @@ import java.lang.annotation.Target;
* that exist in {@link Object}, the {@code canEqual(Object)} method, and any methods that appear in types
* that are listed in the {@code excludes} property.
*/
-@Target(ElementType.FIELD)
+@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
public @interface Delegate {
/**
diff --git a/src/core/lombok/bytecode/ClassFileMetaData.java b/src/core/lombok/bytecode/ClassFileMetaData.java
index 794705cb..68b8bb7d 100644
--- a/src/core/lombok/bytecode/ClassFileMetaData.java
+++ b/src/core/lombok/bytecode/ClassFileMetaData.java
@@ -214,6 +214,7 @@ public class ClassFileMetaData {
* Checks if the constant pool contains the provided string constant, which implies the constant is used somewhere in the code.
*
* NB: String literals get concatenated by the compiler.
+ * NB2: This method does NOT do any kind of normalization.
*/
public boolean containsStringConstant(String value) {
int index = findUtf8(value);
@@ -282,25 +283,23 @@ public class ClassFileMetaData {
private long readLong(int index) {
int pos = offsets[index];
- return ((long)read32(pos)) << 32 | read32(pos + 4);
+ return ((long)read32(pos)) << 32 | (read32(pos + 4) & 0x00000000FFFFFFFFL);
}
private double readDouble(int index) {
- int pos = offsets[index];
- long bits = ((long)read32(pos)) << 32 | (read32(pos + 4) & 0x00000000FFFFFFFF);
- return Double.longBitsToDouble(bits);
+ return Double.longBitsToDouble(readLong(index));
}
- private long readInteger(int index) {
+ private int readInteger(int index) {
return read32(offsets[index]);
}
private float readFloat(int index) {
- return Float.intBitsToFloat(read32(offsets[index]));
+ return Float.intBitsToFloat(readInteger(index));
}
private int read32(int pos) {
- return (byteCode[pos] & 0xFF) << 24 | (byteCode[pos + 1] & 0xFF) << 16 | (byteCode[pos + 2] & 0xFF) << 8 | (byteCode[pos + 3] &0xFF);
+ return (byteCode[pos] & 0xFF) << 24 | (byteCode[pos + 1] & 0xFF) << 16 | (byteCode[pos + 2] & 0xFF) << 8 | (byteCode[pos + 3] & 0xFF);
}
/**
diff --git a/src/core/lombok/core/Version.java b/src/core/lombok/core/Version.java
index 332bb7d6..f5c08112 100644
--- a/src/core/lombok/core/Version.java
+++ b/src/core/lombok/core/Version.java
@@ -28,7 +28,7 @@ public class Version {
// ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries).
// Note: In 'X.Y.Z', if Z is odd, its a snapshot build built from the repository, so many different 0.10.3 versions can exist, for example.
// Official builds always end in an even number. (Since 0.10.2).
- private static final String VERSION = "0.10.7";
+ private static final String VERSION = "0.10.9";
private static final String RELEASE_NAME = "Burning Emu";
private Version() {
diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
index d4c63da3..ef01835c 100644
--- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
@@ -222,14 +222,17 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
}
MethodDeclaration equalsMethod = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get(), fieldAccess, needsCanEqual);
+ equalsMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
injectMethod(typeNode, equalsMethod);
if (needsCanEqual) {
MethodDeclaration canEqualMethod = createCanEqual(typeNode, errorNode.get());
+ canEqualMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
injectMethod(typeNode, canEqualMethod);
}
MethodDeclaration hashCodeMethod = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get(), fieldAccess);
+ hashCodeMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
injectMethod(typeNode, hashCodeMethod);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java
index 1d59afb4..b7d9c5ed 100644
--- a/src/core/lombok/eclipse/handlers/HandleGetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleGetter.java
@@ -24,18 +24,23 @@ package lombok.eclipse.handlers;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import lombok.AccessLevel;
+import lombok.Delegate;
import lombok.Getter;
+import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.TransformationsUtil;
-import lombok.core.AST.Kind;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.eclipse.agent.PatchDelegate;
+import lombok.eclipse.handlers.EclipseHandlerUtil.FieldAccess;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
@@ -69,6 +74,8 @@ import org.mangosdk.spi.ProviderFor;
*/
@ProviderFor(EclipseAnnotationHandler.class)
public class HandleGetter extends EclipseAnnotationHandler<Getter> {
+ private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY = new Annotation[0];
+
public boolean generateGetterForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean checkForTypeLevelGetter) {
if (checkForTypeLevelGetter) {
if (typeNode != null) for (EclipseNode child : typeNode.down()) {
@@ -205,13 +212,25 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
}
MethodDeclaration method = generateGetter((TypeDeclaration) fieldNode.up().get(), fieldNode, getterName, modifier, source, lazy);
- Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN));
+ Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), findDelegatesAndMarkAsHandled(fieldNode));
if (copiedAnnotations.length != 0) {
method.annotations = copiedAnnotations;
}
injectMethod(fieldNode.up(), method);
}
+
+ private static Annotation[] findDelegatesAndMarkAsHandled(EclipseNode fieldNode) {
+ List<Annotation> delegates = new ArrayList<Annotation>();
+ for (EclipseNode child : fieldNode.down()) {
+ if (annotationTypeMatches(Delegate.class, child)) {
+ Annotation delegate = (Annotation)child.get();
+ PatchDelegate.markHandled(delegate);
+ delegates.add(delegate);
+ }
+ }
+ return delegates.toArray(EMPTY_ANNOTATIONS_ARRAY);
+ }
private MethodDeclaration generateGetter(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source, boolean lazy) {
diff --git a/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java b/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java
index 13292cdd..7d2b7a74 100644
--- a/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java
+++ b/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java
@@ -247,6 +247,13 @@ public final class SetGeneratedByVisitor extends ASTVisitor {
node.nameSourcePosition = recalcSourcePosition(node.nameSourcePosition);
}
+ private void applyOffsetQualifiedNameReference(QualifiedNameReference node) {
+ applyOffsetExpression(node);
+ for (int i = 0; i < node.sourcePositions.length; i++) {
+ node.sourcePositions[i] = recalcSourcePosition(node.sourcePositions[i]);
+ }
+ }
+
private void applyOffsetQualifiedTypeReference(QualifiedTypeReference node) {
applyOffsetExpression(node);
for (int i = 0; i < node.sourcePositions.length; i++) {
@@ -787,8 +794,8 @@ public final class SetGeneratedByVisitor extends ASTVisitor {
}
@Override public boolean visit(QualifiedNameReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ setGeneratedBy(node, source);
+ applyOffsetQualifiedNameReference(node);
return super.visit(node, scope);
}
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)));
}