diff --git a/src/core/lombok/core/LombokNode.java b/src/core/lombok/core/LombokNode.java
index 90e55757..4989f304 100644
--- a/src/core/lombok/core/LombokNode.java
+++ b/src/core/lombok/core/LombokNode.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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
@@ -45,13 +45,6 @@ public abstract class LombokNode, L extends LombokNode children;
protected L parent;
- /** This flag has no specified meaning; you can set and retrieve it.
- *
- * In practice, for annotation nodes it means: Some AnnotationHandler finished whatever changes were required,
- * and for all other nodes it means: This node was made by a lombok operation.
- */
- protected boolean handled;
-
/** structurally significant are those nodes that can be annotated in java 1.6 or are method-like toplevels,
* so fields, local declarations, method arguments, methods, types, the Compilation Unit itself, and initializers. */
protected boolean isStructurallySignificant;
@@ -84,8 +77,8 @@ public abstract class LombokNode, L extends LombokNode, L extends LombokNode(children);
}
- /**
- * returns the value of the 'handled' flag.
- *
- * @see #handled
- */
- public boolean isHandled() {
- return handled;
- }
-
- /**
- * Sets the handled flag, then returns itself for chaining.
- *
- * @see #handled
- */
- @SuppressWarnings("unchecked")
- public L setHandled() {
- this.handled = true;
- return (L)this;
- }
-
/**
* Convenient shortcut to the owning ast object's top method.
*
@@ -308,18 +281,6 @@ public abstract class LombokNode, L extends LombokNode annotation, org.eclipse.jdt.internal.compiler.ast.Annotation ast, EclipseNode annotationNode);
+ void handle(AnnotationValues annotation, org.eclipse.jdt.internal.compiler.ast.Annotation ast, EclipseNode annotationNode);
}
diff --git a/src/core/lombok/eclipse/HandlerLibrary.java b/src/core/lombok/eclipse/HandlerLibrary.java
index ba7f891a..109f6fe1 100644
--- a/src/core/lombok/eclipse/HandlerLibrary.java
+++ b/src/core/lombok/eclipse/HandlerLibrary.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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
@@ -29,6 +29,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import java.util.WeakHashMap;
import lombok.Lombok;
import lombok.core.AnnotationValues;
@@ -38,6 +39,7 @@ import lombok.core.TypeLibrary;
import lombok.core.TypeResolver;
import lombok.core.AnnotationValues.AnnotationValueDecodeFail;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
@@ -65,10 +67,10 @@ public class HandlerLibrary {
this.annotationClass = annotationClass;
}
- public boolean handle(org.eclipse.jdt.internal.compiler.ast.Annotation annotation,
+ public void handle(org.eclipse.jdt.internal.compiler.ast.Annotation annotation,
final EclipseNode annotationNode) {
AnnotationValues annValues = Eclipse.createAnnotation(annotationClass, annotationNode);
- return handler.handle(annValues, annotation, annotationNode);
+ handler.handle(annValues, annotation, annotationNode);
}
}
@@ -126,6 +128,15 @@ public class HandlerLibrary {
}
}
+ private static final Map handledMap = new WeakHashMap();
+ private static final Object MARKER = new Object();
+
+ private boolean checkAndSetHandled(ASTNode node) {
+ synchronized (handledMap) {
+ return handledMap.put(node, MARKER) != MARKER;
+ }
+ }
+
/**
* Handles the provided annotation node by first finding a qualifying instance of
* {@link EclipseAnnotationHandler} and if one exists, calling it with a freshly cooked up
@@ -143,15 +154,15 @@ public class HandlerLibrary {
* @param annotationNode The Lombok AST Node representing the Annotation AST Node.
* @param annotation 'node.get()' - convenience parameter.
*/
- public boolean handle(CompilationUnitDeclaration ast, EclipseNode annotationNode,
- org.eclipse.jdt.internal.compiler.ast.Annotation annotation) {
+ public void handleAnnotation(CompilationUnitDeclaration ast, EclipseNode annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation) {
+ if (!checkAndSetHandled(annotation)) return;
+
String pkgName = annotationNode.getPackageDeclaration();
Collection imports = annotationNode.getImportStatements();
TypeResolver resolver = new TypeResolver(typeLibrary, pkgName, imports);
TypeReference rawType = annotation.type;
- if (rawType == null) return false;
- boolean handled = false;
+ if (rawType == null) return;
for (String fqn : resolver.findTypeMatches(annotationNode, toQualifiedName(annotation.type.getTypeName()))) {
boolean isPrintAST = fqn.equals(PrintAST.class.getName());
if (isPrintAST == skipPrintAST) continue;
@@ -160,15 +171,13 @@ public class HandlerLibrary {
if (container == null) continue;
try {
- handled |= container.handle(annotation, annotationNode);
+ container.handle(annotation, annotationNode);
} catch (AnnotationValueDecodeFail fail) {
fail.owner.setError(fail.getMessage(), fail.idx);
} catch (Throwable t) {
Eclipse.error(ast, String.format("Lombok annotation handler %s failed", container.handler.getClass()), t);
}
}
-
- return handled;
}
/**
diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java
index aada3ca4..314c8a7d 100644
--- a/src/core/lombok/eclipse/TransformEclipseAST.java
+++ b/src/core/lombok/eclipse/TransformEclipseAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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
@@ -168,38 +168,28 @@ public class TransformEclipseAST {
private static class AnnotationVisitor extends EclipseASTAdapter {
@Override public void visitAnnotationOnField(FieldDeclaration field, EclipseNode annotationNode, Annotation annotation) {
- if (annotationNode.isHandled()) return;
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
- boolean handled = handlers.handle(top, annotationNode, annotation);
- if (handled) annotationNode.setHandled();
+ handlers.handleAnnotation(top, annotationNode, annotation);
}
@Override public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) {
- if (annotationNode.isHandled()) return;
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
- boolean handled = handlers.handle(top, annotationNode, annotation);
- if (handled) annotationNode.setHandled();
+ handlers.handleAnnotation(top, annotationNode, annotation);
}
@Override public void visitAnnotationOnLocal(LocalDeclaration local, EclipseNode annotationNode, Annotation annotation) {
- if (annotationNode.isHandled()) return;
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
- boolean handled = handlers.handle(top, annotationNode, annotation);
- if (handled) annotationNode.setHandled();
+ handlers.handleAnnotation(top, annotationNode, annotation);
}
@Override public void visitAnnotationOnMethod(AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) {
- if (annotationNode.isHandled()) return;
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
- boolean handled = handlers.handle(top, annotationNode, annotation);
- if (handled) annotationNode.setHandled();
+ handlers.handleAnnotation(top, annotationNode, annotation);
}
@Override public void visitAnnotationOnType(TypeDeclaration type, EclipseNode annotationNode, Annotation annotation) {
- if (annotationNode.isHandled()) return;
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
- boolean handled = handlers.handle(top, annotationNode, annotation);
- if (handled) annotationNode.setHandled();
+ handlers.handleAnnotation(top, annotationNode, annotation);
}
}
}
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index d16e3ead..0eae12f2 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans.
+ * Copyright © 2009-2011 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
@@ -332,9 +332,7 @@ public class EclipseHandlerUtil {
char[] fName = def.name;
if (fName == null) continue;
if (fieldName.equals(new String(fName))) {
- EclipseNode existing = node.getNodeFor(def);
- if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER;
- return MemberExistsResult.EXISTS_BY_LOMBOK;
+ return Eclipse.getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK;
}
}
}
@@ -369,11 +367,7 @@ public class EclipseHandlerUtil {
char[] mName = def.selector;
if (mName == null) continue;
boolean nameEquals = caseSensitive ? methodName.equals(new String(mName)) : methodName.equalsIgnoreCase(new String(mName));
- if (nameEquals) {
- EclipseNode existing = node.getNodeFor(def);
- if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER;
- return MemberExistsResult.EXISTS_BY_LOMBOK;
- }
+ if (nameEquals) return Eclipse.getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK;
}
}
}
@@ -397,9 +391,7 @@ public class EclipseHandlerUtil {
if (typeDecl.methods != null) for (AbstractMethodDeclaration def : typeDecl.methods) {
if (def instanceof ConstructorDeclaration) {
if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue;
- EclipseNode existing = node.getNodeFor(def);
- if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER;
- return MemberExistsResult.EXISTS_BY_LOMBOK;
+ return Eclipse.getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK;
}
}
}
@@ -407,55 +399,6 @@ public class EclipseHandlerUtil {
return MemberExistsResult.NOT_EXISTS;
}
- /**
- * Returns the constructor that's already been generated by lombok.
- * Provide any node that represents the type (TypeDeclaration) to look in, or any child node thereof.
- */
- public static EclipseNode getExistingLombokConstructor(EclipseNode node) {
- while (node != null && !(node.get() instanceof TypeDeclaration)) {
- node = node.up();
- }
-
- if (node == null) return null;
-
- if (node.get() instanceof TypeDeclaration) {
- for (AbstractMethodDeclaration def : ((TypeDeclaration)node.get()).methods) {
- if (def instanceof ConstructorDeclaration) {
- if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue;
- EclipseNode existing = node.getNodeFor(def);
- if (existing.isHandled()) return existing;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Returns the method that's already been generated by lombok with the given name.
- * Provide any node that represents the type (TypeDeclaration) to look in, or any child node thereof.
- */
- public static EclipseNode getExistingLombokMethod(String methodName, EclipseNode node) {
- while (node != null && !(node.get() instanceof TypeDeclaration)) {
- node = node.up();
- }
-
- if (node == null) return null;
-
- if (node.get() instanceof TypeDeclaration) {
- for (AbstractMethodDeclaration def : ((TypeDeclaration)node.get()).methods) {
- char[] mName = def.selector;
- if (mName == null) continue;
- if (methodName.equals(new String(mName))) {
- EclipseNode existing = node.getNodeFor(def);
- if (existing.isHandled()) return existing;
- }
- }
- }
-
- return null;
- }
-
/**
* Inserts a field into an existing type. The type must represent a {@code TypeDeclaration}.
* The field carries the @{@link SuppressWarnings}("all") annotation.
@@ -487,7 +430,7 @@ public class EclipseHandlerUtil {
}
}
- type.add(field, Kind.FIELD).recursiveSetHandled();
+ type.add(field, Kind.FIELD);
}
private static boolean hasClinit(TypeDeclaration parent) {
@@ -573,7 +516,7 @@ public class EclipseHandlerUtil {
parent.methods = newArray;
}
- type.add(method, Kind.METHOD).recursiveSetHandled();
+ type.add(method, Kind.METHOD);
}
private static final char[] ALL = "all".toCharArray();
diff --git a/src/core/lombok/eclipse/handlers/HandleCleanup.java b/src/core/lombok/eclipse/handlers/HandleCleanup.java
index 9a63ce47..4f9615b6 100644
--- a/src/core/lombok/eclipse/handlers/HandleCleanup.java
+++ b/src/core/lombok/eclipse/handlers/HandleCleanup.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans.
+ * Copyright © 2009-2011 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
@@ -59,23 +59,23 @@ import org.mangosdk.spi.ProviderFor;
*/
@ProviderFor(EclipseAnnotationHandler.class)
public class HandleCleanup implements EclipseAnnotationHandler {
- public boolean handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
+ public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
String cleanupName = annotation.getInstance().value();
if (cleanupName.length() == 0) {
annotationNode.addError("cleanupName cannot be the empty string.");
- return true;
+ return;
}
if (annotationNode.up().getKind() != Kind.LOCAL) {
annotationNode.addError("@Cleanup is legal only on local variable declarations.");
- return true;
+ return;
}
LocalDeclaration decl = (LocalDeclaration)annotationNode.up().get();
if (decl.initialization == null) {
annotationNode.addError("@Cleanup variable declarations need to be initialized.");
- return true;
+ return;
}
EclipseNode ancestor = annotationNode.up().directUp();
@@ -94,12 +94,12 @@ public class HandleCleanup implements EclipseAnnotationHandler {
statements = ((SwitchStatement)blockNode).statements;
} else {
annotationNode.addError("@Cleanup is legal only on a local variable declaration inside a block.");
- return true;
+ return;
}
if (statements == null) {
annotationNode.addError("LOMBOK BUG: Parent block does not contain any statements.");
- return true;
+ return;
}
int start = 0;
@@ -109,7 +109,7 @@ public class HandleCleanup implements EclipseAnnotationHandler {
if (start == statements.length) {
annotationNode.addError("LOMBOK BUG: Can't find this local variable declaration inside its parent.");
- return true;
+ return;
}
start++; //We start with try{} *AFTER* the var declaration.
@@ -205,8 +205,6 @@ public class HandleCleanup implements EclipseAnnotationHandler {
}
ancestor.rebuild();
-
- return true;
}
private MessageSend preventNullAnalysis(Annotation ast, Expression expr) {
diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java
index db26beed..e0715961 100644
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -73,34 +73,32 @@ import org.mangosdk.spi.ProviderFor;
public class HandleConstructor {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleNoArgsConstructor implements EclipseAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
+ @Override public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
EclipseNode typeNode = annotationNode.up();
- if (!checkLegality(typeNode, annotationNode, NoArgsConstructor.class.getSimpleName())) return true;
+ if (!checkLegality(typeNode, annotationNode, NoArgsConstructor.class.getSimpleName())) return;
NoArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
String staticName = ann.staticName();
- if (level == AccessLevel.NONE) return true;
+ if (level == AccessLevel.NONE) return;
List fields = new ArrayList();
Annotation[] onConstructor = getAndRemoveAnnotationParameter(ast, "onConstructor");
new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, onConstructor, false, false, ast);
- return true;
}
}
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleRequiredArgsConstructor implements EclipseAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
+ @Override public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
EclipseNode typeNode = annotationNode.up();
- if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return true;
+ if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return;
RequiredArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
String staticName = ann.staticName();
@SuppressWarnings("deprecation")
boolean suppressConstructorProperties = ann.suppressConstructorProperties();
- if (level == AccessLevel.NONE) return true;
+ if (level == AccessLevel.NONE) return;
Annotation[] onConstructor = getAndRemoveAnnotationParameter(ast, "onConstructor");
new HandleConstructor().generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, onConstructor, false, suppressConstructorProperties, ast);
- return true;
}
}
@@ -119,15 +117,15 @@ public class HandleConstructor {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleAllArgsConstructor implements EclipseAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
+ @Override public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
EclipseNode typeNode = annotationNode.up();
- if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return true;
+ if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return;
AllArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
String staticName = ann.staticName();
@SuppressWarnings("deprecation")
boolean suppressConstructorProperties = ann.suppressConstructorProperties();
- if (level == AccessLevel.NONE) return true;
+ if (level == AccessLevel.NONE) return;
List fields = new ArrayList();
for (EclipseNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD) continue;
@@ -135,13 +133,12 @@ public class HandleConstructor {
if (!EclipseHandlerUtil.filterField(fieldDecl)) continue;
// Skip initialized final fields.
- if (((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0) && fieldDecl.initialization != null) return false;
+ if (((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0) && fieldDecl.initialization != null) return;
fields.add(child);
}
Annotation[] onConstructor = getAndRemoveAnnotationParameter(ast, "onConstructor");
new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, onConstructor, false, suppressConstructorProperties, ast);
- return true;
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleData.java b/src/core/lombok/eclipse/handlers/HandleData.java
index 0a28ccf4..9b3d7e51 100644
--- a/src/core/lombok/eclipse/handlers/HandleData.java
+++ b/src/core/lombok/eclipse/handlers/HandleData.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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,7 +37,7 @@ import org.mangosdk.spi.ProviderFor;
*/
@ProviderFor(EclipseAnnotationHandler.class)
public class HandleData implements EclipseAnnotationHandler {
- public boolean handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
+ public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
Data ann = annotation.getInstance();
EclipseNode typeNode = annotationNode.up();
@@ -49,7 +49,7 @@ public class HandleData implements EclipseAnnotationHandler {
if (typeDecl == null || notAClass) {
annotationNode.addError("@Data is only supported on a class.");
- return false;
+ return;
}
//Careful: Generate the public static constructor (if there is one) LAST, so that any attempt to
@@ -63,7 +63,5 @@ public class HandleData implements EclipseAnnotationHandler {
new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
new HandleToString().generateToStringForType(typeNode, annotationNode);
new HandleConstructor().generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), true, ast);
-
- return false;
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
index 8ee7272c..3be8fdfa 100644
--- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans.
+ * Copyright © 2009-2011 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
@@ -116,7 +116,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler annotation,
+ @Override public void handle(AnnotationValues annotation,
Annotation ast, EclipseNode annotationNode) {
EqualsAndHashCode ann = annotation.getInstance();
List excludes = Arrays.asList(ann.exclude());
@@ -137,10 +137,10 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler excludes, List includes,
+ public void generateMethods(EclipseNode typeNode, EclipseNode errorNode, List excludes, List includes,
Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) {
assert excludes == null || includes == null;
@@ -153,7 +153,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler fields, boolean callSuper, ASTNode source, FieldAccess fieldAccess) {
diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java
index f39e55b5..3af09afb 100644
--- a/src/core/lombok/eclipse/handlers/HandleGetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleGetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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
@@ -131,7 +131,7 @@ public class HandleGetter implements EclipseAnnotationHandler {
createGetterForField(level, fieldNode, fieldNode, pos, false, onMethod, lazy);
}
- public boolean handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
+ public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
EclipseNode node = annotationNode.up();
Getter annotationInstance = annotation.getInstance();
AccessLevel level = annotationInstance.value();
@@ -140,46 +140,46 @@ public class HandleGetter implements EclipseAnnotationHandler {
if (lazy) {
annotationNode.addWarning("'lazy' does not work with AccessLevel.NONE.");
}
- return true;
+ return;
}
- if (node == null) return false;
+ if (node == null) return;
Annotation[] onMethod = getAndRemoveAnnotationParameter(ast, "onMethod");
- if (node.getKind() == Kind.FIELD) {
- return createGetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod, lazy);
- }
- if (node.getKind() == Kind.TYPE) {
+ switch (node.getKind()) {
+ case FIELD:
+ createGetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod, lazy);
+ break;
+ case TYPE:
if (onMethod != null && onMethod.length != 0) annotationNode.addError("'onMethod' is not supported for @Getter on a type.");
if (lazy) annotationNode.addError("'lazy' is not supported for @Getter on a type.");
- return generateGetterForType(node, annotationNode, level, false);
+ generateGetterForType(node, annotationNode, level, false);
+ break;
}
- return false;
}
- private boolean createGetterForFields(AccessLevel level, Collection fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod, boolean lazy) {
+ private void createGetterForFields(AccessLevel level, Collection fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod, boolean lazy) {
for (EclipseNode fieldNode : fieldNodes) {
createGetterForField(level, fieldNode, errorNode, source, whineIfExists, onMethod, lazy);
}
- return true;
}
- private boolean createGetterForField(AccessLevel level,
+ private void createGetterForField(AccessLevel level,
EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod, boolean lazy) {
if (fieldNode.getKind() != Kind.FIELD) {
errorNode.addError("@Getter is only supported on a class or a field.");
- return true;
+ return;
}
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
if (lazy) {
if ((field.modifiers & ClassFileConstants.AccPrivate) == 0 || (field.modifiers & ClassFileConstants.AccFinal) == 0) {
errorNode.addError("'lazy' requires the field to be private and final.");
- return true;
+ return;
}
if (field.initialization == null) {
errorNode.addError("'lazy' requires field initialization.");
- return true;
+ return;
}
}
@@ -193,7 +193,7 @@ public class HandleGetter implements EclipseAnnotationHandler {
for (String altName : TransformationsUtil.toAllGetterNames(fieldName, isBoolean)) {
switch (methodExists(altName, fieldNode, false)) {
case EXISTS_BY_LOMBOK:
- return true;
+ return;
case EXISTS_BY_USER:
if (whineIfExists) {
String altNameExpl = "";
@@ -201,7 +201,7 @@ public class HandleGetter implements EclipseAnnotationHandler {
errorNode.addWarning(
String.format("Not generating %s(): A method with that name already exists%s", getterName, altNameExpl));
}
- return true;
+ return;
default:
case NOT_EXISTS:
//continue scanning the other alt names.
@@ -215,8 +215,6 @@ public class HandleGetter implements EclipseAnnotationHandler {
}
injectMethod(fieldNode.up(), method);
-
- return true;
}
private MethodDeclaration generateGetter(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source, boolean lazy) {
diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java
index be856208..a51d8e7e 100644
--- a/src/core/lombok/eclipse/handlers/HandleLog.java
+++ b/src/core/lombok/eclipse/handlers/HandleLog.java
@@ -51,7 +51,7 @@ public class HandleLog {
throw new UnsupportedOperationException();
}
- public static boolean processAnnotation(LoggingFramework framework, AnnotationValues extends java.lang.annotation.Annotation> annotation, Annotation source, EclipseNode annotationNode) {
+ public static void processAnnotation(LoggingFramework framework, AnnotationValues extends java.lang.annotation.Annotation> annotation, Annotation source, EclipseNode annotationNode) {
EclipseNode owner = annotationNode.up();
switch (owner.getKind()) {
case TYPE:
@@ -64,22 +64,22 @@ public class HandleLog {
if (typeDecl == null || notAClass) {
annotationNode.addError("@Log is legal only on classes and enums.");
- return false;
+ return;
}
if (fieldExists("log", owner) != MemberExistsResult.NOT_EXISTS) {
annotationNode.addWarning("Field 'log' already exists.");
- return true;
+ return;
}
ClassLiteralAccess loggingType = selfType(owner, source);
injectField(owner, createField(framework, source, loggingType));
owner.rebuild();
- return true;
+ break;
default:
annotationNode.addError("@Log is legal only on types.");
- return true;
+ break;
}
}
@@ -154,8 +154,8 @@ public class HandleLog {
*/
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleCommonsLog implements EclipseAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
- return processAnnotation(LoggingFramework.COMMONS, annotation, source, annotationNode);
+ @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
+ processAnnotation(LoggingFramework.COMMONS, annotation, source, annotationNode);
}
}
@@ -164,8 +164,8 @@ public class HandleLog {
*/
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleJulLog implements EclipseAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
- return processAnnotation(LoggingFramework.JUL, annotation, source, annotationNode);
+ @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
+ processAnnotation(LoggingFramework.JUL, annotation, source, annotationNode);
}
}
@@ -174,8 +174,8 @@ public class HandleLog {
*/
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleLog4jLog implements EclipseAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
- return processAnnotation(LoggingFramework.LOG4J, annotation, source, annotationNode);
+ @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
+ processAnnotation(LoggingFramework.LOG4J, annotation, source, annotationNode);
}
}
@@ -184,8 +184,8 @@ public class HandleLog {
*/
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleSlf4jLog implements EclipseAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
- return processAnnotation(LoggingFramework.SLF4J, annotation, source, annotationNode);
+ @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
+ processAnnotation(LoggingFramework.SLF4J, annotation, source, annotationNode);
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandlePrintAST.java b/src/core/lombok/eclipse/handlers/HandlePrintAST.java
index 580a54a2..be86a566 100644
--- a/src/core/lombok/eclipse/handlers/HandlePrintAST.java
+++ b/src/core/lombok/eclipse/handlers/HandlePrintAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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
@@ -40,8 +40,8 @@ import lombok.eclipse.EclipseNode;
*/
@ProviderFor(EclipseAnnotationHandler.class)
public class HandlePrintAST implements EclipseAnnotationHandler {
- public boolean handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
- if (!annotationNode.isCompleteParse()) return false;
+ public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
+ if (!annotationNode.isCompleteParse()) return;
PrintStream stream = System.out;
String fileName = annotation.getInstance().outfile();
@@ -52,6 +52,5 @@ public class HandlePrintAST implements EclipseAnnotationHandler {
}
annotationNode.up().traverse(new EclipseASTVisitor.Printer(annotation.getInstance().printContent(), stream));
- return true;
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java
index 945495c6..ac3ff2a2 100644
--- a/src/core/lombok/eclipse/handlers/HandleSetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleSetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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
@@ -120,40 +120,37 @@ public class HandleSetter implements EclipseAnnotationHandler {
createSetterForField(level, fieldNode, fieldNode, pos, false, onMethod, onParam);
}
- public boolean handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
+ public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
EclipseNode node = annotationNode.up();
AccessLevel level = annotation.getInstance().value();
- if (level == AccessLevel.NONE) return true;
-
- if (node == null) return false;
+ if (level == AccessLevel.NONE || node == null) return;
Annotation[] onMethod = getAndRemoveAnnotationParameter(ast, "onMethod");
Annotation[] onParam = getAndRemoveAnnotationParameter(ast, "onParam");
- if (node.getKind() == Kind.FIELD) {
- return createSetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod, onParam);
-
- }
- if (node.getKind() == Kind.TYPE) {
+ switch (node.getKind()) {
+ case FIELD:
+ createSetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod, onParam);
+ break;
+ case 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);
+ generateSetterForType(node, annotationNode, level, false);
+ break;
}
- return false;
}
- private boolean createSetterForFields(AccessLevel level, Collection fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod , Annotation[] onParam) {
+ private void createSetterForFields(AccessLevel level, Collection fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, Annotation[] onMethod , Annotation[] onParam) {
for (EclipseNode fieldNode : fieldNodes) {
createSetterForField(level, fieldNode, errorNode, source, whineIfExists, onMethod, onParam);
}
- return true;
}
- private boolean createSetterForField(AccessLevel level,
+ private void createSetterForField(AccessLevel level,
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;
+ return;
}
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
@@ -166,7 +163,7 @@ public class HandleSetter implements EclipseAnnotationHandler {
for (String altName : TransformationsUtil.toAllSetterNames(new String(field.name), isBoolean)) {
switch (methodExists(altName, fieldNode, false)) {
case EXISTS_BY_LOMBOK:
- return true;
+ return;
case EXISTS_BY_USER:
if (whineIfExists) {
String altNameExpl = "";
@@ -174,7 +171,7 @@ public class HandleSetter implements EclipseAnnotationHandler {
errorNode.addWarning(
String.format("Not generating %s(): A method with that name already exists%s", setterName, altNameExpl));
}
- return true;
+ return;
default:
case NOT_EXISTS:
//continue scanning the other alt names.
@@ -188,8 +185,6 @@ public class HandleSetter implements EclipseAnnotationHandler {
}
injectMethod(fieldNode.up(), method);
-
- return true;
}
private MethodDeclaration generateSetter(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source, Annotation[] onParam) {
diff --git a/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java b/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java
index 38f22b2a..4b36d688 100644
--- a/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java
+++ b/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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 HandleSneakyThrows implements EclipseAnnotationHandler annotation, Annotation source, EclipseNode annotationNode) {
+ @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
List exceptionNames = annotation.getRawExpressions("value");
List exceptions = new ArrayList();
@@ -101,10 +101,10 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler exceptions) {
+ private void handleMethod(EclipseNode annotation, AbstractMethodDeclaration method, List exceptions) {
if (method.isAbstract()) {
annotation.addError("@SneakyThrows can only be used on concrete methods.");
- return true;
+ return;
}
- if (method.statements == null) return false;
+ if (method.statements == null) return;
Statement[] contents = method.statements;
@@ -156,8 +156,6 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler annotation, Annotation source, EclipseNode annotationNode) {
+ @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
int p1 = source.sourceStart -1;
int p2 = source.sourceStart -2;
long pos = (((long)p1) << 32) | p2;
EclipseNode methodNode = annotationNode.up();
if (methodNode == null || methodNode.getKind() != Kind.METHOD || !(methodNode.get() instanceof MethodDeclaration)) {
annotationNode.addError("@Synchronized is legal only on methods.");
- return true;
+ return;
}
MethodDeclaration method = (MethodDeclaration)methodNode.get();
if (method.isAbstract()) {
annotationNode.addError("@Synchronized is legal only on concrete methods.");
- return true;
+ return;
}
char[] lockName = annotation.getInstance().value().toCharArray();
@@ -83,7 +83,7 @@ public class HandleSynchronized implements EclipseAnnotationHandler {
generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, FieldAccess.GETTER);
}
- public boolean handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
+ public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) {
ToString ann = annotation.getInstance();
List excludes = Arrays.asList(ann.exclude());
List includes = Arrays.asList(ann.of());
@@ -118,10 +118,10 @@ public class HandleToString implements EclipseAnnotationHandler {
FieldAccess fieldAccess = ann.doNotUseGetters() ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
- return generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true, fieldAccess);
+ generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true, fieldAccess);
}
- public boolean generateToString(EclipseNode typeNode, EclipseNode errorNode, List excludes, List includes,
+ public void generateToString(EclipseNode typeNode, EclipseNode errorNode, List excludes, List includes,
boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) {
TypeDeclaration typeDecl = null;
@@ -132,7 +132,6 @@ public class HandleToString implements EclipseAnnotationHandler {
if (typeDecl == null || notAClass) {
errorNode.addError("@ToString is only supported on a class or enum.");
- return false;
}
if (callSuper == null) {
@@ -165,15 +164,14 @@ public class HandleToString implements EclipseAnnotationHandler {
case NOT_EXISTS:
MethodDeclaration toString = createToString(typeNode, nodesForToString, includeFieldNames, callSuper, errorNode.get(), fieldAccess);
injectMethod(typeNode, toString);
- return true;
+ break;
case EXISTS_BY_LOMBOK:
- return true;
+ break;
default:
case EXISTS_BY_USER:
if (whineIfExists) {
errorNode.addWarning("Not generating toString(): A method with that name already exists");
}
- return true;
}
}
diff --git a/src/core/lombok/javac/HandlerLibrary.java b/src/core/lombok/javac/HandlerLibrary.java
index 12a5a370..0c753c02 100644
--- a/src/core/lombok/javac/HandlerLibrary.java
+++ b/src/core/lombok/javac/HandlerLibrary.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import java.util.WeakHashMap;
import javax.annotation.processing.Messager;
import javax.tools.Diagnostic;
@@ -37,6 +38,7 @@ import lombok.core.TypeLibrary;
import lombok.core.TypeResolver;
import lombok.core.AnnotationValues.AnnotationValueDecodeFail;
+import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
@@ -74,8 +76,8 @@ public class HandlerLibrary {
return handler.isResolutionBased();
}
- public boolean handle(final JavacNode node) {
- return handler.handle(Javac.createAnnotation(annotationClass, node), (JCAnnotation)node.get(), node);
+ public void handle(final JavacNode node) {
+ handler.handle(Javac.createAnnotation(annotationClass, node), (JCAnnotation)node.get(), node);
}
}
@@ -141,6 +143,15 @@ public class HandlerLibrary {
if (t != null) t.printStackTrace();
}
+ private static final Map handledMap = new WeakHashMap();
+ private static final Object MARKER = new Object();
+
+ private boolean checkAndSetHandled(JCTree node) {
+ synchronized (handledMap) {
+ return handledMap.put(node, MARKER) != MARKER;
+ }
+ }
+
/**
* Handles the provided annotation node by first finding a qualifying instance of
* {@link JavacAnnotationHandler} and if one exists, calling it with a freshly cooked up
@@ -158,10 +169,11 @@ public class HandlerLibrary {
* @param node The Lombok AST Node representing the Annotation AST Node.
* @param annotation 'node.get()' - convenience parameter.
*/
- public boolean handleAnnotation(JCCompilationUnit unit, JavacNode node, JCAnnotation annotation) {
+ public void handleAnnotation(JCCompilationUnit unit, JavacNode node, JCAnnotation annotation) {
+ if (!checkAndSetHandled(annotation)) return;
+
TypeResolver resolver = new TypeResolver(typeLibrary, node.getPackageDeclaration(), node.getImportStatements());
String rawType = annotation.annotationType.toString();
- boolean handled = false;
for (String fqn : resolver.findTypeMatches(node, rawType)) {
boolean isPrintAST = fqn.equals(PrintAST.class.getName());
if (isPrintAST && phase != 2) continue;
@@ -170,9 +182,9 @@ public class HandlerLibrary {
if (container == null) continue;
try {
- if (container.isResolutionBased() && phase == 1) handled |= container.handle(node);
- if (!container.isResolutionBased() && phase == 0) handled |= container.handle(node);
- if (container.annotationClass == PrintAST.class && phase == 2) handled |= container.handle(node);
+ if (container.isResolutionBased() && phase == 1) container.handle(node);
+ if (!container.isResolutionBased() && phase == 0) container.handle(node);
+ if (container.annotationClass == PrintAST.class && phase == 2) container.handle(node);
} catch (AnnotationValueDecodeFail fail) {
fail.owner.setError(fail.getMessage(), fail.idx);
} catch (Throwable t) {
@@ -181,8 +193,6 @@ public class HandlerLibrary {
javacError(String.format("Lombok annotation handler %s failed on " + sourceName, container.handler.getClass()), t);
}
}
-
- return handled;
}
/**
diff --git a/src/core/lombok/javac/Javac.java b/src/core/lombok/javac/Javac.java
index 8eb56e1d..64e8ee27 100644
--- a/src/core/lombok/javac/Javac.java
+++ b/src/core/lombok/javac/Javac.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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
@@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.WeakHashMap;
import lombok.Lombok;
import lombok.core.AST.Kind;
@@ -45,6 +46,7 @@ import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCLiteral;
import com.sun.tools.javac.tree.JCTree.JCNewArray;
+import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
/**
@@ -194,4 +196,44 @@ public class Javac {
throw Lombok.sneakyThrow(e);
}
}
+
+ private static class MarkingScanner extends TreeScanner {
+ private final JCTree source;
+
+ MarkingScanner(JCTree source) {
+ this.source = source;
+ }
+
+ @Override public void scan(JCTree tree) {
+ setGeneratedBy(tree, source);
+ super.scan(tree);
+ }
+ }
+
+ private static Map generatedNodes = new WeakHashMap();
+
+ public static JCTree getGeneratedBy(JCTree node) {
+ synchronized (generatedNodes) {
+ return generatedNodes.get(node);
+ }
+ }
+
+ public static boolean isGenerated(JCTree node) {
+ return getGeneratedBy(node) != null;
+ }
+
+ public static T recursiveSetGeneratedBy(T node, JCTree source) {
+ setGeneratedBy(node, source);
+ node.accept(new MarkingScanner(source));
+
+ return node;
+ }
+
+ public static T setGeneratedBy(T node, JCTree source) {
+ synchronized (generatedNodes) {
+ if (source == null) generatedNodes.remove(node);
+ else generatedNodes.put(node, source);
+ }
+ return node;
+ }
}
diff --git a/src/core/lombok/javac/JavacAnnotationHandler.java b/src/core/lombok/javac/JavacAnnotationHandler.java
index ee330ecb..3e9f6660 100644
--- a/src/core/lombok/javac/JavacAnnotationHandler.java
+++ b/src/core/lombok/javac/JavacAnnotationHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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
@@ -51,10 +51,8 @@ public interface JavacAnnotationHandler {
* @param annotationNode The Lombok AST wrapper around the 'ast' parameter. You can use this object
* to travel back up the chain (something javac AST can't do) to the parent of the annotation, as well
* as access useful methods such as generating warnings or errors focused on the annotation.
- * @return {@code true} if you don't want to be called again about this annotation during this
- * compile session (you've handled it), or {@code false} to indicate you aren't done yet.
*/
- boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode);
+ void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode);
/**
* Return true if this handler requires resolution.
diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java
index beef6924..7423d061 100644
--- a/src/core/lombok/javac/JavacTransformer.java
+++ b/src/core/lombok/javac/JavacTransformer.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans.
+ * Copyright © 2009-2011 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
@@ -88,38 +88,28 @@ public class JavacTransformer {
private class AnnotationVisitor extends JavacASTAdapter {
@Override public void visitAnnotationOnType(JCClassDecl type, JavacNode annotationNode, JCAnnotation annotation) {
- if (annotationNode.isHandled()) return;
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
- boolean handled = handlers.handleAnnotation(top, annotationNode, annotation);
- if (handled) annotationNode.setHandled();
+ handlers.handleAnnotation(top, annotationNode, annotation);
}
@Override public void visitAnnotationOnField(JCVariableDecl field, JavacNode annotationNode, JCAnnotation annotation) {
- if (annotationNode.isHandled()) return;
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
- boolean handled = handlers.handleAnnotation(top, annotationNode, annotation);
- if (handled) annotationNode.setHandled();
+ handlers.handleAnnotation(top, annotationNode, annotation);
}
@Override public void visitAnnotationOnMethod(JCMethodDecl method, JavacNode annotationNode, JCAnnotation annotation) {
- if (annotationNode.isHandled()) return;
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
- boolean handled = handlers.handleAnnotation(top, annotationNode, annotation);
- if (handled) annotationNode.setHandled();
+ handlers.handleAnnotation(top, annotationNode, annotation);
}
@Override public void visitAnnotationOnMethodArgument(JCVariableDecl argument, JCMethodDecl method, JavacNode annotationNode, JCAnnotation annotation) {
- if (annotationNode.isHandled()) return;
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
- boolean handled = handlers.handleAnnotation(top, annotationNode, annotation);
- if (handled) annotationNode.setHandled();
+ handlers.handleAnnotation(top, annotationNode, annotation);
}
@Override public void visitAnnotationOnLocal(JCVariableDecl local, JavacNode annotationNode, JCAnnotation annotation) {
- if (annotationNode.isHandled()) return;
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
- boolean handled = handlers.handleAnnotation(top, annotationNode, annotation);
- if (handled) annotationNode.setHandled();
+ handlers.handleAnnotation(top, annotationNode, annotation);
}
}
}
diff --git a/src/core/lombok/javac/handlers/HandleCleanup.java b/src/core/lombok/javac/handlers/HandleCleanup.java
index b681ab28..eb4b7987 100644
--- a/src/core/lombok/javac/handlers/HandleCleanup.java
+++ b/src/core/lombok/javac/handlers/HandleCleanup.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans.
+ * Copyright © 2009-2011 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
@@ -21,7 +21,7 @@
*/
package lombok.javac.handlers;
-import static lombok.javac.handlers.JavacHandlerUtil.markAnnotationAsProcessed;
+import static lombok.javac.handlers.JavacHandlerUtil.deleteAnnotationIfNeccessary;
import lombok.Cleanup;
import lombok.core.AnnotationValues;
import lombok.core.AST.Kind;
@@ -59,24 +59,24 @@ import com.sun.tools.javac.util.Name;
*/
@ProviderFor(JavacAnnotationHandler.class)
public class HandleCleanup implements JavacAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
- markAnnotationAsProcessed(annotationNode, Cleanup.class);
+ @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
+ deleteAnnotationIfNeccessary(annotationNode, Cleanup.class);
String cleanupName = annotation.getInstance().value();
if (cleanupName.length() == 0) {
annotationNode.addError("cleanupName cannot be the empty string.");
- return true;
+ return;
}
if (annotationNode.up().getKind() != Kind.LOCAL) {
annotationNode.addError("@Cleanup is legal only on local variable declarations.");
- return true;
+ return;
}
JCVariableDecl decl = (JCVariableDecl)annotationNode.up().get();
if (decl.init == null) {
annotationNode.addError("@Cleanup variable declarations need to be initialized.");
- return true;
+ return;
}
JavacNode ancestor = annotationNode.up().directUp();
@@ -91,7 +91,7 @@ public class HandleCleanup implements JavacAnnotationHandler {
statements = ((JCMethodDecl)blockNode).body.stats;
} else {
annotationNode.addError("@Cleanup is legal only on a local variable declaration inside a block.");
- return true;
+ return;
}
boolean seenDeclaration = false;
@@ -108,7 +108,7 @@ public class HandleCleanup implements JavacAnnotationHandler {
if (!seenDeclaration) {
annotationNode.addError("LOMBOK BUG: Can't find this local variable declaration inside its parent.");
- return true;
+ return;
}
doAssignmentCheck(annotationNode, tryBlock.toList(), decl.name);
@@ -122,9 +122,9 @@ public class HandleCleanup implements JavacAnnotationHandler {
JCIf ifNotNullCleanup = maker.If(isNull, maker.Block(0, cleanupCall), null);
- JCBlock finalizer = maker.Block(0, List.of(ifNotNullCleanup));
+ JCBlock finalizer = Javac.recursiveSetGeneratedBy(maker.Block(0, List.of(ifNotNullCleanup)), ast);
- newStatements.append(maker.Try(maker.Block(0, tryBlock.toList()), List.nil(), finalizer));
+ newStatements.append(Javac.setGeneratedBy(maker.Try(Javac.setGeneratedBy(maker.Block(0, tryBlock.toList()), ast), List.nil(), finalizer), ast));
if (blockNode instanceof JCBlock) {
((JCBlock)blockNode).stats = newStatements.toList();
@@ -135,8 +135,6 @@ public class HandleCleanup implements JavacAnnotationHandler {
} else throw new AssertionError("Should not get here");
ancestor.rebuild();
-
- return true;
}
private JCMethodInvocation preventNullAnalysis(TreeMaker maker, JavacNode node, JCExpression expression) {
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index 1497b1b4..fd7d5a9d 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -37,6 +37,7 @@ import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCAssign;
@@ -58,19 +59,18 @@ import com.sun.tools.javac.util.ListBuffer;
public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleNoArgsConstructor implements JavacAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
- markAnnotationAsProcessed(annotationNode, NoArgsConstructor.class);
+ @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
+ deleteAnnotationIfNeccessary(annotationNode, NoArgsConstructor.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
- if (!checkLegality(typeNode, annotationNode, NoArgsConstructor.class.getSimpleName())) return true;
+ if (!checkLegality(typeNode, annotationNode, NoArgsConstructor.class.getSimpleName())) return;
NoArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
String staticName = ann.staticName();
- if (level == AccessLevel.NONE) return true;
+ if (level == AccessLevel.NONE) return;
List fields = List.nil();
List onConstructor = getAndRemoveAnnotationParameter(ast, "onConstructor");
- new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, onConstructor, false, false);
- return true;
+ new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, onConstructor, false, false, annotationNode);
}
@Override public boolean isResolutionBased() {
@@ -80,20 +80,19 @@ public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleRequiredArgsConstructor implements JavacAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
- markAnnotationAsProcessed(annotationNode, RequiredArgsConstructor.class);
+ @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
+ deleteAnnotationIfNeccessary(annotationNode, RequiredArgsConstructor.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
- if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return true;
+ if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return;
RequiredArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
String staticName = ann.staticName();
@SuppressWarnings("deprecation")
boolean suppressConstructorProperties = ann.suppressConstructorProperties();
- if (level == AccessLevel.NONE) return true;
+ if (level == AccessLevel.NONE) return;
List onConstructor = getAndRemoveAnnotationParameter(ast, "onConstructor");
- new HandleConstructor().generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, onConstructor, false, suppressConstructorProperties);
- return true;
+ new HandleConstructor().generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, onConstructor, false, suppressConstructorProperties, annotationNode);
}
@Override public boolean isResolutionBased() {
@@ -120,17 +119,17 @@ public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleAllArgsConstructor implements JavacAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
- markAnnotationAsProcessed(annotationNode, AllArgsConstructor.class);
+ @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
+ deleteAnnotationIfNeccessary(annotationNode, AllArgsConstructor.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
- if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return true;
+ if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return;
AllArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
String staticName = ann.staticName();
@SuppressWarnings("deprecation")
boolean suppressConstructorProperties = ann.suppressConstructorProperties();
- if (level == AccessLevel.NONE) return true;
+ if (level == AccessLevel.NONE) return;
ListBuffer fields = ListBuffer.lb();
for (JavacNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD) continue;
@@ -145,8 +144,7 @@ public class HandleConstructor {
fields.append(child);
}
List onConstructor = getAndRemoveAnnotationParameter(ast, "onConstructor");
- new HandleConstructor().generateConstructor(typeNode, level, fields.toList(), staticName, onConstructor, false, suppressConstructorProperties);
- return true;
+ new HandleConstructor().generateConstructor(typeNode, level, fields.toList(), staticName, onConstructor, false, suppressConstructorProperties, annotationNode);
}
@Override public boolean isResolutionBased() {
@@ -168,11 +166,11 @@ public class HandleConstructor {
return true;
}
- public void generateRequiredArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists) {
- generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, List.nil(), skipIfConstructorExists, false);
+ public void generateRequiredArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists, JavacNode source) {
+ generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, List.nil(), skipIfConstructorExists, false, source);
}
- public void generateConstructor(JavacNode typeNode, AccessLevel level, List fields, String staticName, List onConstructor, boolean skipIfConstructorExists, boolean suppressConstructorProperties) {
+ public void generateConstructor(JavacNode typeNode, AccessLevel level, List fields, String staticName, List onConstructor, boolean skipIfConstructorExists, boolean suppressConstructorProperties, JavacNode source) {
if (skipIfConstructorExists && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return;
if (skipIfConstructorExists) {
for (JavacNode child : typeNode.down()) {
@@ -187,10 +185,10 @@ public class HandleConstructor {
boolean staticConstrRequired = staticName != null && !staticName.equals("");
- JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, onConstructor, suppressConstructorProperties);
+ JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, onConstructor, suppressConstructorProperties, source.get());
injectMethod(typeNode, constr);
if (staticConstrRequired) {
- JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, fields);
+ JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, fields, source.get());
injectMethod(typeNode, staticConstr);
}
}
@@ -208,7 +206,7 @@ public class HandleConstructor {
mods.annotations = mods.annotations.append(annotation);
}
- private JCMethodDecl createConstructor(AccessLevel level, JavacNode typeNode, List fields, List onConstructor, boolean suppressConstructorProperties) {
+ private JCMethodDecl createConstructor(AccessLevel level, JavacNode typeNode, List fields, List onConstructor, boolean suppressConstructorProperties, JCTree source) {
TreeMaker maker = typeNode.getTreeMaker();
boolean isEnum = (((JCClassDecl) typeNode.get()).mods.flags & Flags.ENUM) != 0;
@@ -239,8 +237,8 @@ public class HandleConstructor {
if (!suppressConstructorProperties && level != AccessLevel.PRIVATE && !isLocalType(typeNode)) {
addConstructorProperties(mods, typeNode, fields);
}
- return maker.MethodDef(mods, typeNode.toName(""),
- null, List.nil(), params.toList(), List.nil(), maker.Block(0L, nullChecks.appendList(assigns).toList()), null);
+ return Javac.recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName(""),
+ null, List.nil(), params.toList(), List.nil(), maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source);
}
private boolean isLocalType(JavacNode type) {
@@ -250,7 +248,7 @@ public class HandleConstructor {
return true;
}
- private JCMethodDecl createStaticConstructor(String name, AccessLevel level, JavacNode typeNode, List fields) {
+ private JCMethodDecl createStaticConstructor(String name, AccessLevel level, JavacNode typeNode, List fields, JCTree source) {
TreeMaker maker = typeNode.getTreeMaker();
JCClassDecl type = (JCClassDecl) typeNode.get();
@@ -298,6 +296,6 @@ public class HandleConstructor {
JCReturn returnStatement = maker.Return(maker.NewClass(null, List.nil(), constructorType, args.toList(), null));
JCBlock body = maker.Block(0, List.of(returnStatement));
- return maker.MethodDef(mods, typeNode.toName(name), returnType, typeParams.toList(), params.toList(), List.nil(), body, null);
+ return Javac.recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName(name), returnType, typeParams.toList(), params.toList(), List.nil(), body, null), source);
}
}
diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java
index 682b7fe4..b0490b35 100644
--- a/src/core/lombok/javac/handlers/HandleData.java
+++ b/src/core/lombok/javac/handlers/HandleData.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 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
@@ -21,7 +21,7 @@
*/
package lombok.javac.handlers;
-import static lombok.javac.handlers.JavacHandlerUtil.markAnnotationAsProcessed;
+import static lombok.javac.handlers.JavacHandlerUtil.deleteAnnotationIfNeccessary;
import lombok.AccessLevel;
import lombok.Data;
import lombok.core.AnnotationValues;
@@ -39,8 +39,8 @@ import com.sun.tools.javac.tree.JCTree.JCClassDecl;
*/
@ProviderFor(JavacAnnotationHandler.class)
public class HandleData implements JavacAnnotationHandler {
- @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
- markAnnotationAsProcessed(annotationNode, Data.class);
+ @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
+ deleteAnnotationIfNeccessary(annotationNode, Data.class);
JavacNode typeNode = annotationNode.up();
JCClassDecl typeDecl = null;
if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl)typeNode.get();
@@ -49,19 +49,17 @@ public class HandleData implements JavacAnnotationHandler {
if (typeDecl == null || notAClass) {
annotationNode.addError("@Data is only supported on a class.");
- return false;
+ return;
}
String staticConstructorName = annotation.getInstance().staticConstructor();
// TODO move this to the end OR move it to the top in eclipse.
- new HandleConstructor().generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, true);
+ new HandleConstructor().generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, true, annotationNode);
new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
new HandleSetter().generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
new HandleToString().generateToStringForType(typeNode, annotationNode);
-
- return true;
}
@Override public boolean isResolutionBased() {
diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java
index e333daa3..f1d872ae 100644
--- a/src/core/lombok/javac/handlers/HandleDelegate.java
+++ b/src/core/lombok/javac/handlers/HandleDelegate.java
@@ -21,7 +21,7 @@
*/
package lombok.javac.handlers;
-import static lombok.javac.handlers.JavacHandlerUtil.markAnnotationAsProcessed;
+import static lombok.javac.handlers.JavacHandlerUtil.deleteAnnotationIfNeccessary;
import java.util.ArrayList;
import java.util.Arrays;
@@ -43,6 +43,7 @@ import lombok.Delegate;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.javac.FindTypeVarScanner;
+import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacResolution;
@@ -91,11 +92,11 @@ public class HandleDelegate implements JavacAnnotationHandler {
"clone()",
"finalize()"));
- @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) {
- markAnnotationAsProcessed(annotationNode, Delegate.class);
+ @Override public void handle(AnnotationValues 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.
- return false;
+ return;
}
List