diff options
author | Reinier Zwitserloot <reinier@zwitserloot.com> | 2011-05-30 22:04:46 +0200 |
---|---|---|
committer | Reinier Zwitserloot <reinier@zwitserloot.com> | 2011-05-30 22:08:12 +0200 |
commit | aa8a627349bb68f376b98847b6f73c2c89e989fd (patch) | |
tree | 70df1fa6ba0f8e3c34a45d868d7f763e5b7ccbf9 /src/core/lombok/javac | |
parent | daf84dd00ed5059710acf9f40b4663ba7fed06e0 (diff) | |
download | lombok-aa8a627349bb68f376b98847b6f73c2c89e989fd.tar.gz lombok-aa8a627349bb68f376b98847b6f73c2c89e989fd.tar.bz2 lombok-aa8a627349bb68f376b98847b6f73c2c89e989fd.zip |
tracking if an annotation has been handled or not is now no longer done
via the LombokAST object. Instead its tracked more directly in an attempt
to avoid having to write all handlers as idempotent, and just in case
issue #164 is a race condition (the handled-or-not is a synchronized CAS check).
This does break API for other plugins, but the fix is trivial: Just make your
'handle' method return void. That 'we won't call you again' business in the decks
never quite worked right anyway.
Also, you might want to call Javac.(recursive)setHandledBy when you generate nodes, now.
Diffstat (limited to 'src/core/lombok/javac')
18 files changed, 302 insertions, 277 deletions
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<JCTree, Object> handledMap = new WeakHashMap<JCTree, Object>(); + 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<JCTree, JCTree> generatedNodes = new WeakHashMap<JCTree, JCTree>(); + + 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 extends JCTree> T recursiveSetGeneratedBy(T node, JCTree source) { + setGeneratedBy(node, source); + node.accept(new MarkingScanner(source)); + + return node; + } + + public static <T extends JCTree> 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<T extends Annotation> { * @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<T> annotation, JCAnnotation ast, JavacNode annotationNode); + void handle(AnnotationValues<T> 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<Cleanup> { - @Override public boolean handle(AnnotationValues<Cleanup> annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, Cleanup.class); + @Override public void handle(AnnotationValues<Cleanup> 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<Cleanup> { 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<Cleanup> { 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<Cleanup> { JCIf ifNotNullCleanup = maker.If(isNull, maker.Block(0, cleanupCall), null); - JCBlock finalizer = maker.Block(0, List.<JCStatement>of(ifNotNullCleanup)); + JCBlock finalizer = Javac.recursiveSetGeneratedBy(maker.Block(0, List.<JCStatement>of(ifNotNullCleanup)), ast); - newStatements.append(maker.Try(maker.Block(0, tryBlock.toList()), List.<JCCatch>nil(), finalizer)); + newStatements.append(Javac.setGeneratedBy(maker.Try(Javac.setGeneratedBy(maker.Block(0, tryBlock.toList()), ast), List.<JCCatch>nil(), finalizer), ast)); if (blockNode instanceof JCBlock) { ((JCBlock)blockNode).stats = newStatements.toList(); @@ -135,8 +135,6 @@ public class HandleCleanup implements JavacAnnotationHandler<Cleanup> { } 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<NoArgsConstructor> { - @Override public boolean handle(AnnotationValues<NoArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, NoArgsConstructor.class); + @Override public void handle(AnnotationValues<NoArgsConstructor> 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<JavacNode> fields = List.nil(); List<JCExpression> 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<RequiredArgsConstructor> { - @Override public boolean handle(AnnotationValues<RequiredArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, RequiredArgsConstructor.class); + @Override public void handle(AnnotationValues<RequiredArgsConstructor> 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<JCExpression> 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<AllArgsConstructor> { - @Override public boolean handle(AnnotationValues<AllArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, AllArgsConstructor.class); + @Override public void handle(AnnotationValues<AllArgsConstructor> 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<JavacNode> 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<JCExpression> 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.<JCExpression>nil(), skipIfConstructorExists, false); + public void generateRequiredArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists, JavacNode source) { + generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, List.<JCExpression>nil(), skipIfConstructorExists, false, source); } - public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JavacNode> fields, String staticName, List<JCExpression> onConstructor, boolean skipIfConstructorExists, boolean suppressConstructorProperties) { + public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JavacNode> fields, String staticName, List<JCExpression> 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<JavacNode> fields, List<JCExpression> onConstructor, boolean suppressConstructorProperties) { + private JCMethodDecl createConstructor(AccessLevel level, JavacNode typeNode, List<JavacNode> fields, List<JCExpression> 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("<init>"), - null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(), maker.Block(0L, nullChecks.appendList(assigns).toList()), null); + return Javac.recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"), + null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>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<JavacNode> fields) { + private JCMethodDecl createStaticConstructor(String name, AccessLevel level, JavacNode typeNode, List<JavacNode> 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.<JCExpression>nil(), constructorType, args.toList(), null)); JCBlock body = maker.Block(0, List.<JCStatement>of(returnStatement)); - return maker.MethodDef(mods, typeNode.toName(name), returnType, typeParams.toList(), params.toList(), List.<JCExpression>nil(), body, null); + return Javac.recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName(name), returnType, typeParams.toList(), params.toList(), List.<JCExpression>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<Data> { - @Override public boolean handle(AnnotationValues<Data> annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, Data.class); + @Override public void handle(AnnotationValues<Data> 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<Data> { 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<Delegate> { "clone()", "finalize()")); - @Override public boolean handle(AnnotationValues<Delegate> annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, Delegate.class); + @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. - return false; + return; } List<Object> delegateTypes = annotation.getActualExpressions("types"); @@ -148,7 +149,7 @@ public class HandleDelegate implements JavacAnnotationHandler<Delegate> { addMethodBindings(signaturesToExclude, ct, annotationNode, banList); } else { annotationNode.addError("@Delegate can only use concrete class types, not wildcards, arrays, type variables, or primitives."); - return false; + return; } } @@ -162,15 +163,13 @@ public class HandleDelegate implements JavacAnnotationHandler<Delegate> { addMethodBindings(signaturesToDelegate, ct, annotationNode, banList); } else { annotationNode.addError("@Delegate can only use concrete class types, not wildcards, arrays, type variables, or primitives."); - return false; + return; } } Name delegateFieldName = annotationNode.toName(annotationNode.up().getName()); for (MethodSig sig : signaturesToDelegate) generateAndAdd(sig, annotationNode, delegateFieldName); - - return false; } private void generateAndAdd(MethodSig sig, JavacNode annotation, Name delegateFieldName) { @@ -295,7 +294,7 @@ public class HandleDelegate implements JavacAnnotationHandler<Delegate> { JCStatement body = useReturn ? maker.Return(delegateCall) : maker.Exec(delegateCall); JCBlock bodyBlock = maker.Block(0, com.sun.tools.javac.util.List.of(body)); - return maker.MethodDef(mods, sig.name, returnType, toList(typeParams), toList(params), toList(thrown), bodyBlock, null); + return Javac.recursiveSetGeneratedBy(maker.MethodDef(mods, sig.name, returnType, toList(typeParams), toList(params), toList(thrown), bodyBlock, null), annotation.get()); } private static <T> com.sun.tools.javac.util.List<T> toList(ListBuffer<T> collection) { diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index 78ecbd9c..1172e3ab 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/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 @@ -72,8 +72,8 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd } } - @Override public boolean handle(AnnotationValues<EqualsAndHashCode> annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, EqualsAndHashCode.class); + @Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, JCAnnotation ast, JavacNode annotationNode) { + deleteAnnotationIfNeccessary(annotationNode, EqualsAndHashCode.class); EqualsAndHashCode ann = annotation.getInstance(); List<String> excludes = List.from(ann.exclude()); List<String> includes = List.from(ann.of()); @@ -93,10 +93,10 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd FieldAccess fieldAccess = ann.doNotUseGetters() ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER; - return generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true, fieldAccess); + generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true, fieldAccess); } - public void generateEqualsAndHashCodeForType(JavacNode typeNode, JavacNode errorNode) { + public void generateEqualsAndHashCodeForType(JavacNode typeNode, JavacNode source) { for (JavacNode child : typeNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (Javac.annotationTypeMatches(EqualsAndHashCode.class, child)) { @@ -106,10 +106,10 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd } } - generateMethods(typeNode, errorNode, null, null, null, false, FieldAccess.GETTER); + generateMethods(typeNode, source, null, null, null, false, FieldAccess.GETTER); } - private boolean generateMethods(JavacNode typeNode, JavacNode errorNode, List<String> excludes, List<String> includes, + private void generateMethods(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) { boolean notAClass = true; if (typeNode.get() instanceof JCClassDecl) { @@ -118,8 +118,8 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd } if (notAClass) { - errorNode.addError("@EqualsAndHashCode is only supported on a class."); - return false; + source.addError("@EqualsAndHashCode is only supported on a class."); + return; } boolean isDirectDescendantOfObject = true; @@ -139,12 +139,12 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd } if (isDirectDescendantOfObject && callSuper) { - errorNode.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless."); - return true; + source.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless."); + return; } if (!isDirectDescendantOfObject && !callSuper && implicitCallSuper) { - errorNode.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type."); + source.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type."); } ListBuffer<JavacNode> nodesForEquality = ListBuffer.lb(); @@ -176,7 +176,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd boolean isFinal = (((JCClassDecl)typeNode.get()).mods.flags & Flags.FINAL) != 0; needsCanEqual = !isFinal || !isDirectDescendantOfObject; - JCMethodDecl method = createEquals(typeNode, nodesForEquality.toList(), callSuper, fieldAccess, needsCanEqual); + JCMethodDecl method = createEquals(typeNode, nodesForEquality.toList(), callSuper, fieldAccess, needsCanEqual, source.get()); injectMethod(typeNode, method); break; case EXISTS_BY_LOMBOK: @@ -184,7 +184,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd default: case EXISTS_BY_USER: if (whineIfExists) { - errorNode.addWarning("Not generating equals(Object other): A method with that name already exists"); + source.addWarning("Not generating equals(Object other): A method with that name already exists"); } break; } @@ -192,7 +192,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd if (needsCanEqual) { switch (methodExists("canEqual", typeNode)) { case NOT_EXISTS: - JCMethodDecl method = createCanEqual(typeNode); + JCMethodDecl method = createCanEqual(typeNode, source.get()); injectMethod(typeNode, method); break; case EXISTS_BY_LOMBOK: @@ -203,7 +203,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd } switch (methodExists("hashCode", typeNode)) { case NOT_EXISTS: - JCMethodDecl method = createHashCode(typeNode, nodesForEquality.toList(), callSuper, fieldAccess); + JCMethodDecl method = createHashCode(typeNode, nodesForEquality.toList(), callSuper, fieldAccess, source.get()); injectMethod(typeNode, method); break; case EXISTS_BY_LOMBOK: @@ -211,14 +211,13 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd default: case EXISTS_BY_USER: if (whineIfExists) { - errorNode.addWarning("Not generating hashCode(): A method with that name already exists"); + source.addWarning("Not generating hashCode(): A method with that name already exists"); } break; } - return true; } - private JCMethodDecl createHashCode(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess) { + private JCMethodDecl createHashCode(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, JCTree source) { TreeMaker maker = typeNode.getTreeMaker(); JCAnnotation overrideAnnotation = maker.Annotation(chainDots(maker, typeNode, "java", "lang", "Override"), List.<JCExpression>nil()); @@ -320,8 +319,8 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd } JCBlock body = maker.Block(0, statements.toList()); - return maker.MethodDef(mods, typeNode.toName("hashCode"), returnType, - List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + return Javac.recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("hashCode"), returnType, + List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null), source); } /** The 2 references must be clones of each other. */ @@ -332,7 +331,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd return maker.TypeCast(maker.TypeIdent(Javac.getCTCint(TypeTags.class, "INT")), xorBits); } - private JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual) { + private JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source) { TreeMaker maker = typeNode.getTreeMaker(); JCClassDecl type = (JCClassDecl) typeNode.get(); @@ -451,10 +450,10 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd } JCBlock body = maker.Block(0, statements.toList()); - return maker.MethodDef(mods, typeNode.toName("equals"), returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null); + return Javac.recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("equals"), returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source); } - private JCMethodDecl createCanEqual(JavacNode typeNode) { + private JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source) { /* public boolean canEqual(final java.lang.Object other) { * return other instanceof MyType; * } @@ -472,7 +471,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd JCBlock body = maker.Block(0, List.<JCStatement>of( maker.Return(maker.TypeTest(maker.Ident(otherName), maker.Ident(type.name))))); - return maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null); + return Javac.recursiveSetGeneratedBy(maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source); } private JCStatement generateCompareFloatOrDouble(JCExpression thisDotField, JCExpression otherDotField, diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 8a1f7eed..83b6a898 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/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 @@ -70,13 +70,13 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; */ @ProviderFor(JavacAnnotationHandler.class) public class HandleGetter implements JavacAnnotationHandler<Getter> { - public boolean generateGetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelGetter) { + public void generateGetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelGetter) { if (checkForTypeLevelGetter) { if (typeNode != null) for (JavacNode child : typeNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (Javac.annotationTypeMatches(Getter.class, child)) { //The annotation will make it happen, so we can skip it. - return true; + return; } } } @@ -89,14 +89,12 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { if (typeDecl == null || notAClass) { errorNode.addError("@Getter is only supported on a class, an enum, or a field."); - return false; + return; } for (JavacNode field : typeNode.down()) { if (fieldQualifiesForGetterGeneration(field)) generateGetterForField(field, errorNode.get(), level, List.<JCExpression>nil(), false); } - - return true; } public boolean fieldQualifiesForGetterGeneration(JavacNode field) { @@ -123,7 +121,6 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { * * @param fieldNode The node representing the field you want a getter for. * @param pos The node responsible for generating the getter (the {@code @Data} or {@code @Getter} annotation). - * @param lazy */ public void generateGetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, List<JCExpression> onMethod, boolean lazy) { for (JavacNode child : fieldNode.down()) { @@ -138,9 +135,9 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { createGetterForField(level, fieldNode, fieldNode, false, onMethod, lazy); } - @Override public boolean handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) { + @Override public void handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) { Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields(); - markAnnotationAsProcessed(annotationNode, Getter.class); + deleteAnnotationIfNeccessary(annotationNode, Getter.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode node = annotationNode.up(); Getter annotationInstance = annotation.getInstance(); @@ -150,48 +147,47 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { if (lazy) { annotationNode.addWarning("'lazy' does not work with AccessLevel.NONE."); } - return true; + return; } - if (node == null) return false; + if (node == null) return; List<JCExpression> onMethod = getAndRemoveAnnotationParameter(ast, "onMethod"); - if (node.getKind() == Kind.FIELD) { - return createGetterForFields(level, fields, annotationNode, true, onMethod, lazy); - } - if (node.getKind() == Kind.TYPE) { + switch (node.getKind()) { + case FIELD: + createGetterForFields(level, fields, annotationNode, true, onMethod, lazy); + break; + case TYPE: if (!onMethod.isEmpty()) 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<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod, boolean lazy) { + private void createGetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod, boolean lazy) { for (JavacNode fieldNode : fieldNodes) { createGetterForField(level, fieldNode, errorNode, whineIfExists, onMethod, lazy); } - - return true; } - private boolean createGetterForField(AccessLevel level, - JavacNode fieldNode, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod, boolean lazy) { + private void createGetterForField(AccessLevel level, + JavacNode fieldNode, JavacNode source, boolean whineIfExists, List<JCExpression> onMethod, boolean lazy) { if (fieldNode.getKind() != Kind.FIELD) { - errorNode.addError("@Getter is only supported on a class or a field."); - return true; + source.addError("@Getter is only supported on a class or a field."); + return; } JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get(); if (lazy) { if ((fieldDecl.mods.flags & Flags.PRIVATE) == 0 || (fieldDecl.mods.flags & Flags.FINAL) == 0) { - errorNode.addError("'lazy' requires the field to be private and final."); - return true; + source.addError("'lazy' requires the field to be private and final."); + return; } if (fieldDecl.init == null) { - errorNode.addError("'lazy' requires field initialization."); - return true; + source.addError("'lazy' requires field initialization."); + return; } } @@ -200,15 +196,15 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { for (String altName : toAllGetterNames(fieldDecl)) { switch (methodExists(altName, fieldNode, false)) { case EXISTS_BY_LOMBOK: - return true; + return; case EXISTS_BY_USER: if (whineIfExists) { String altNameExpl = ""; if (!altName.equals(methodName)) altNameExpl = String.format(" (%s)", altName); - errorNode.addWarning( + source.addWarning( String.format("Not generating %s(): A method with that name already exists%s", methodName, altNameExpl)); } - return true; + return; default: case NOT_EXISTS: //continue scanning the other alt names. @@ -217,20 +213,20 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC); - injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), onMethod, lazy)); - - return true; + injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), onMethod, lazy, source.get())); } - private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker, List<JCExpression> onMethod, boolean lazy) { + private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker, List<JCExpression> onMethod, boolean lazy, JCTree source) { JCVariableDecl fieldNode = (JCVariableDecl) field.get(); // Remember the type; lazy will change it; JCExpression methodType = copyType(treeMaker, fieldNode); List<JCStatement> statements; + JCTree toClearOfMarkers = null; if (lazy) { - statements = createLazyGetterBody(treeMaker, field); + toClearOfMarkers = fieldNode.init; + statements = createLazyGetterBody(treeMaker, field, source); } else { statements = createSimpleGetterBody(treeMaker, field); } @@ -248,8 +244,12 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod).appendList(nonNulls).appendList(nullables); - return treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType, - methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue); + JCMethodDecl decl = Javac.recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType, + methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source); + + if (toClearOfMarkers != null) Javac.recursiveSetGeneratedBy(toClearOfMarkers, null); + + return decl; } private List<JCStatement> createSimpleGetterBody(TreeMaker treeMaker, JavacNode field) { @@ -273,7 +273,7 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { TYPE_MAP = Collections.unmodifiableMap(m); } - private List<JCStatement> createLazyGetterBody(TreeMaker maker, JavacNode fieldNode) { + private List<JCStatement> createLazyGetterBody(TreeMaker maker, JavacNode fieldNode, JCTree source) { /* java.util.concurrent.atomic.AtomicReference<ValueType> value = this.fieldName.get(); if (value == null) { @@ -318,7 +318,7 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { /* if (value == null) { */ { ListBuffer<JCStatement> innerIfStatements = ListBuffer.lb(); /* value = new java.util.concurrent.atomic.AtomicReference<ValueType>(new ValueType());*/ { - JCTypeApply valueVarType = maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.of(copyType(maker, field))); + JCTypeApply valueVarType = maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.of(copyType(maker, field))); JCNewClass newInstance = maker.NewClass(null, NIL_EXPRESSION, valueVarType, List.<JCExpression>of(field.init), null); JCStatement statement = maker.Exec(maker.Assign(maker.Ident(valueName), newInstance)); @@ -347,8 +347,10 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { // update the field type and init last /* private final java.util.concurrent.atomic.AtomicReference<java.util.concurrent.atomic.AtomicReference<ValueType> fieldName = new java.util.concurrent.atomic.AtomicReference<java.util.concurrent.atomic.AtomicReference<ValueType>>(); */ { - field.vartype = maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.<JCExpression>of(maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.of(copyType(maker, field))))); - field.init = maker.NewClass(null, NIL_EXPRESSION, copyType(maker, field), NIL_EXPRESSION, null); + field.vartype = Javac.recursiveSetGeneratedBy( + maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.<JCExpression>of(maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.of(copyType(maker, field))))), + source); + field.init = Javac.recursiveSetGeneratedBy(maker.NewClass(null, NIL_EXPRESSION, copyType(maker, field), NIL_EXPRESSION, null), source); } return statements.toList(); diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 53d327af..f4a4dead 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -1,5 +1,5 @@ /* - * Copyright © 2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans. + * Copyright © 2010-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 @@ -26,6 +26,7 @@ import static lombok.javac.handlers.JavacHandlerUtil.*; import java.lang.annotation.Annotation; import lombok.core.AnnotationValues; +import lombok.javac.Javac; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult; @@ -33,6 +34,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.JCClassDecl; @@ -49,28 +51,28 @@ public class HandleLog { throw new UnsupportedOperationException(); } - public static boolean processAnnotation(LoggingFramework framework, AnnotationValues<?> annotation, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, framework.getAnnotationClass()); + public static void processAnnotation(LoggingFramework framework, AnnotationValues<?> annotation, JavacNode annotationNode) { + deleteAnnotationIfNeccessary(annotationNode, framework.getAnnotationClass()); JavacNode typeNode = annotationNode.up(); switch (typeNode.getKind()) { case TYPE: if ((((JCClassDecl)typeNode.get()).mods.flags & Flags.INTERFACE)!= 0) { annotationNode.addError("@Log is legal only on classes and enums."); - return true; + return; } if (fieldExists("log", typeNode)!= MemberExistsResult.NOT_EXISTS) { annotationNode.addWarning("Field 'log' already exists."); - return true; + return; } - + JCFieldAccess loggingType = selfType(typeNode); - createField(framework, typeNode, loggingType); - return true; + createField(framework, typeNode, loggingType, annotationNode.get()); + break; default: annotationNode.addError("@Log is legal only on types."); - return true; + break; } } @@ -80,7 +82,7 @@ public class HandleLog { return maker.Select(maker.Ident(name), typeNode.toName("class")); } - private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType) { + private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source) { TreeMaker maker = typeNode.getTreeMaker(); // private static final <loggerType> log = <factoryMethod>(<parameter>); @@ -90,9 +92,9 @@ public class HandleLog { JCExpression loggerName = framework.createFactoryParameter(typeNode, loggingType); JCMethodInvocation factoryMethodCall = maker.Apply(List.<JCExpression>nil(), factoryMethod, List.<JCExpression>of(loggerName)); - JCVariableDecl fieldDecl = maker.VarDef( + JCVariableDecl fieldDecl = Javac.recursiveSetGeneratedBy(maker.VarDef( maker.Modifiers(Flags.PRIVATE | Flags.FINAL | Flags.STATIC), - typeNode.toName("log"), loggerType, factoryMethodCall); + typeNode.toName("log"), loggerType, factoryMethodCall), source); injectField(typeNode, fieldDecl); return true; @@ -103,8 +105,8 @@ public class HandleLog { */ @ProviderFor(JavacAnnotationHandler.class) public static class HandleCommonsLog implements JavacAnnotationHandler<lombok.extern.apachecommons.CommonsLog> { - @Override public boolean handle(AnnotationValues<lombok.extern.apachecommons.CommonsLog> annotation, JCAnnotation ast, JavacNode annotationNode) { - return processAnnotation(LoggingFramework.COMMONS, annotation, annotationNode); + @Override public void handle(AnnotationValues<lombok.extern.apachecommons.CommonsLog> annotation, JCAnnotation ast, JavacNode annotationNode) { + processAnnotation(LoggingFramework.COMMONS, annotation, annotationNode); } @Override public boolean isResolutionBased() { @@ -117,8 +119,8 @@ public class HandleLog { */ @ProviderFor(JavacAnnotationHandler.class) public static class HandleJulLog implements JavacAnnotationHandler<lombok.extern.java.Log> { - @Override public boolean handle(AnnotationValues<lombok.extern.java.Log> annotation, JCAnnotation ast, JavacNode annotationNode) { - return processAnnotation(LoggingFramework.JUL, annotation, annotationNode); + @Override public void handle(AnnotationValues<lombok.extern.java.Log> annotation, JCAnnotation ast, JavacNode annotationNode) { + processAnnotation(LoggingFramework.JUL, annotation, annotationNode); } @Override public boolean isResolutionBased() { @@ -131,8 +133,8 @@ public class HandleLog { */ @ProviderFor(JavacAnnotationHandler.class) public static class HandleLog4jLog implements JavacAnnotationHandler<lombok.extern.log4j.Log4j> { - @Override public boolean handle(AnnotationValues<lombok.extern.log4j.Log4j> annotation, JCAnnotation ast, JavacNode annotationNode) { - return processAnnotation(LoggingFramework.LOG4J, annotation, annotationNode); + @Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j> annotation, JCAnnotation ast, JavacNode annotationNode) { + processAnnotation(LoggingFramework.LOG4J, annotation, annotationNode); } @Override public boolean isResolutionBased() { @@ -145,8 +147,8 @@ public class HandleLog { */ @ProviderFor(JavacAnnotationHandler.class) public static class HandleSlf4jLog implements JavacAnnotationHandler<lombok.extern.slf4j.Slf4j> { - @Override public boolean handle(AnnotationValues<lombok.extern.slf4j.Slf4j> annotation, JCAnnotation ast, JavacNode annotationNode) { - return processAnnotation(LoggingFramework.SLF4J, annotation, annotationNode); + @Override public void handle(AnnotationValues<lombok.extern.slf4j.Slf4j> annotation, JCAnnotation ast, JavacNode annotationNode) { + processAnnotation(LoggingFramework.SLF4J, annotation, annotationNode); } @Override public boolean isResolutionBased() { diff --git a/src/core/lombok/javac/handlers/HandlePrintAST.java b/src/core/lombok/javac/handlers/HandlePrintAST.java index 61b877d6..8e7612c4 100644 --- a/src/core/lombok/javac/handlers/HandlePrintAST.java +++ b/src/core/lombok/javac/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 @@ -41,7 +41,7 @@ import lombok.javac.JavacNode; */ @ProviderFor(JavacAnnotationHandler.class) public class HandlePrintAST implements JavacAnnotationHandler<PrintAST> { - @Override public boolean handle(AnnotationValues<PrintAST> annotation, JCAnnotation ast, JavacNode annotationNode) { + @Override public void handle(AnnotationValues<PrintAST> annotation, JCAnnotation ast, JavacNode annotationNode) { PrintStream stream = System.out; String fileName = annotation.getInstance().outfile(); if (fileName.length() > 0) try { @@ -51,8 +51,6 @@ public class HandlePrintAST implements JavacAnnotationHandler<PrintAST> { } annotationNode.up().traverse(new JavacASTVisitor.Printer(annotation.getInstance().printContent(), stream)); - - return true; } @Override public boolean isResolutionBased() { diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index ec5195ac..957b02ef 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/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 @@ -44,6 +44,7 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.TypeTags; +import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; import com.sun.tools.javac.tree.JCTree.JCBlock; @@ -63,13 +64,13 @@ import com.sun.tools.javac.util.Name; */ @ProviderFor(JavacAnnotationHandler.class) public class HandleSetter implements JavacAnnotationHandler<Setter> { - public boolean generateSetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelSetter) { + public void generateSetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelSetter) { if (checkForTypeLevelSetter) { if (typeNode != null) for (JavacNode child : typeNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (Javac.annotationTypeMatches(Setter.class, child)) { //The annotation will make it happen, so we can skip it. - return true; + return; } } } @@ -82,7 +83,7 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { if (typeDecl == null || notAClass) { errorNode.addError("@Setter is only supported on a class or a field."); - return false; + return; } for (JavacNode field : typeNode.down()) { @@ -97,7 +98,6 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { generateSetterForField(field, errorNode.get(), level, List.<JCExpression>nil(), List.<JCExpression>nil()); } - return true; } /** @@ -128,47 +128,45 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { createSetterForField(level, fieldNode, fieldNode, false, onMethod, onParam); } - @Override public boolean handle(AnnotationValues<Setter> annotation, JCAnnotation ast, JavacNode annotationNode) { + @Override public void handle(AnnotationValues<Setter> annotation, JCAnnotation ast, JavacNode annotationNode) { Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields(); - markAnnotationAsProcessed(annotationNode, Setter.class); + deleteAnnotationIfNeccessary(annotationNode, Setter.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode 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; List<JCExpression> onParamList = getAndRemoveAnnotationParameter(ast, "onParam"); List<JCExpression> onMethodList = getAndRemoveAnnotationParameter(ast, "onMethod"); - if (node.getKind() == Kind.FIELD) { - return createSetterForFields(level, fields, annotationNode, true, onMethodList, onParamList); - } - if (node.getKind() == Kind.TYPE) { + switch (node.getKind()) { + case FIELD: + createSetterForFields(level, fields, annotationNode, true, onMethodList, onParamList); + break; + case TYPE: if (!onMethodList.isEmpty()) annotationNode.addError("'onMethod' is not supported for @Setter on a type."); if (!onParamList.isEmpty()) annotationNode.addError("'onParam' is not supported for @Setter on a type."); - return generateSetterForType(node, annotationNode, level, false); + generateSetterForType(node, annotationNode, level, false); + break; } - return false; } - private boolean createSetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, + private void createSetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod, List<JCExpression> onParam) { for (JavacNode fieldNode : fieldNodes) { createSetterForField(level, fieldNode, errorNode, whineIfExists, onMethod, onParam); } - - return true; } - private boolean createSetterForField(AccessLevel level, - JavacNode fieldNode, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod, List<JCExpression> onParam) { + private void createSetterForField(AccessLevel level, + JavacNode fieldNode, JavacNode source, boolean whineIfExists, List<JCExpression> onMethod, List<JCExpression> onParam) { if (fieldNode.getKind() != Kind.FIELD) { fieldNode.addError("@Setter is only supported on a class or a field."); - return true; + return; } JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get(); @@ -177,15 +175,15 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { for (String altName : toAllSetterNames(fieldDecl)) { switch (methodExists(altName, fieldNode, false)) { case EXISTS_BY_LOMBOK: - return true; + return; case EXISTS_BY_USER: if (whineIfExists) { String altNameExpl = ""; if (!altName.equals(methodName)) altNameExpl = String.format(" (%s)", altName); - errorNode.addWarning( + source.addWarning( String.format("Not generating %s(): A method with that name already exists%s", methodName, altNameExpl)); } - return true; + return; default: case NOT_EXISTS: //continue scanning the other alt names. @@ -194,12 +192,10 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC); - injectMethod(fieldNode.up(), createSetter(access, fieldNode, fieldNode.getTreeMaker(), onMethod, onParam)); - - return true; + injectMethod(fieldNode.up(), createSetter(access, fieldNode, fieldNode.getTreeMaker(), onMethod, onParam, source.get())); } - private JCMethodDecl createSetter(long access, JavacNode field, TreeMaker treeMaker, List<JCExpression> onMethod, List<JCExpression> onParam) { + private JCMethodDecl createSetter(long access, JavacNode field, TreeMaker treeMaker, List<JCExpression> onMethod, List<JCExpression> onParam, JCTree source) { JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); JCExpression fieldRef = createFieldAccessor(treeMaker, field, FieldAccess.ALWAYS_FIELD); @@ -230,8 +226,8 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { List<JCExpression> throwsClauses = List.nil(); JCExpression annotationMethodDefaultValue = null; - return treeMaker.MethodDef(treeMaker.Modifiers(access, copyAnnotations(onMethod)), methodName, methodType, - methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue); + return Javac.recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, copyAnnotations(onMethod)), methodName, methodType, + methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source); } private static class JCNoType extends Type implements NoType { diff --git a/src/core/lombok/javac/handlers/HandleSneakyThrows.java b/src/core/lombok/javac/handlers/HandleSneakyThrows.java index 0f37a80e..3f1e1f0e 100644 --- a/src/core/lombok/javac/handlers/HandleSneakyThrows.java +++ b/src/core/lombok/javac/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 @@ -22,7 +22,7 @@ package lombok.javac.handlers; import static lombok.javac.handlers.JavacHandlerUtil.chainDots; -import static lombok.javac.handlers.JavacHandlerUtil.markAnnotationAsProcessed; +import static lombok.javac.handlers.JavacHandlerUtil.deleteAnnotationIfNeccessary; import java.util.ArrayList; import java.util.Collection; @@ -30,12 +30,14 @@ import java.util.Collections; import lombok.SneakyThrows; import lombok.core.AnnotationValues; +import lombok.javac.Javac; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; 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.JCBlock; @@ -50,8 +52,8 @@ import com.sun.tools.javac.util.List; */ @ProviderFor(JavacAnnotationHandler.class) public class HandleSneakyThrows implements JavacAnnotationHandler<SneakyThrows> { - @Override public boolean handle(AnnotationValues<SneakyThrows> annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, SneakyThrows.class); + @Override public void handle(AnnotationValues<SneakyThrows> annotation, JCAnnotation ast, JavacNode annotationNode) { + deleteAnnotationIfNeccessary(annotationNode, SneakyThrows.class); Collection<String> exceptionNames = annotation.getRawExpressions("value"); if (exceptionNames.isEmpty()) { exceptionNames = Collections.singleton("java.lang.Throwable"); @@ -66,39 +68,38 @@ public class HandleSneakyThrows implements JavacAnnotationHandler<SneakyThrows> JavacNode owner = annotationNode.up(); switch (owner.getKind()) { case METHOD: - return handleMethod(annotationNode, (JCMethodDecl)owner.get(), exceptions); + handleMethod(annotationNode, (JCMethodDecl)owner.get(), exceptions); + break; default: annotationNode.addError("@SneakyThrows is legal only on methods and constructors."); - return true; + break; } } - private boolean handleMethod(JavacNode annotation, JCMethodDecl method, Collection<String> exceptions) { + private void handleMethod(JavacNode annotation, JCMethodDecl method, Collection<String> exceptions) { JavacNode methodNode = annotation.up(); if ( (method.mods.flags & Flags.ABSTRACT) != 0) { annotation.addError("@SneakyThrows can only be used on concrete methods."); - return true; + return; } - if (method.body == null) return false; + if (method.body == null) return; List<JCStatement> contents = method.body.stats; for (String exception : exceptions) { - contents = List.of(buildTryCatchBlock(methodNode, contents, exception)); + contents = List.of(buildTryCatchBlock(methodNode, contents, exception, annotation.get())); } method.body.stats = contents; methodNode.rebuild(); - - return true; } - private JCStatement buildTryCatchBlock(JavacNode node, List<JCStatement> contents, String exception) { + private JCStatement buildTryCatchBlock(JavacNode node, List<JCStatement> contents, String exception, JCTree source) { TreeMaker maker = node.getTreeMaker(); - JCBlock tryBlock = maker.Block(0, contents); + JCBlock tryBlock = Javac.setGeneratedBy(maker.Block(0, contents), source); JCExpression varType = chainDots(maker, node, exception.split("\\.")); @@ -108,7 +109,7 @@ public class HandleSneakyThrows implements JavacAnnotationHandler<SneakyThrows> List.<JCExpression>nil(), lombokLombokSneakyThrowNameRef, List.<JCExpression>of(maker.Ident(node.toName("$ex"))))))); - return maker.Try(tryBlock, List.of(maker.Catch(catchParam, catchBody)), null); + return Javac.setGeneratedBy(maker.Try(tryBlock, List.of(Javac.recursiveSetGeneratedBy(maker.Catch(catchParam, catchBody), source)), null), source); } @Override public boolean isResolutionBased() { diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java index 42e29239..c8e9e79d 100644 --- a/src/core/lombok/javac/handlers/HandleSynchronized.java +++ b/src/core/lombok/javac/handlers/HandleSynchronized.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,14 +51,14 @@ public class HandleSynchronized implements JavacAnnotationHandler<Synchronized> private static final String INSTANCE_LOCK_NAME = "$lock"; private static final String STATIC_LOCK_NAME = "$LOCK"; - @Override public boolean handle(AnnotationValues<Synchronized> annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, Synchronized.class); + @Override public void handle(AnnotationValues<Synchronized> annotation, JCAnnotation ast, JavacNode annotationNode) { + deleteAnnotationIfNeccessary(annotationNode, Synchronized.class); JavacNode methodNode = annotationNode.up(); if (methodNode == null || methodNode.getKind() != Kind.METHOD || !(methodNode.get() instanceof JCMethodDecl)) { annotationNode.addError("@Synchronized is legal only on methods."); - return true; + return; } JCMethodDecl method = (JCMethodDecl)methodNode.get(); @@ -66,7 +66,7 @@ public class HandleSynchronized implements JavacAnnotationHandler<Synchronized> if ((method.mods.flags & Flags.ABSTRACT) != 0) { annotationNode.addError("@Synchronized is legal only on concrete methods."); - return true; + return; } boolean isStatic = (method.mods.flags & Flags.STATIC) != 0; String lockName = annotation.getInstance().value(); @@ -81,19 +81,19 @@ public class HandleSynchronized implements JavacAnnotationHandler<Synchronized> if (fieldExists(lockName, methodNode) == MemberExistsResult.NOT_EXISTS) { if (!autoMake) { annotationNode.addError("The field " + lockName + " does not exist."); - return true; + return; } JCExpression objectType = chainDots(maker, methodNode, "java", "lang", "Object"); - //We use 'new Object[0];' because quite unlike 'new Object();', empty arrays *ARE* serializable! + //We use 'new Object[0];' because unlike 'new Object();', empty arrays *ARE* serializable! JCNewArray newObjectArray = maker.NewArray(chainDots(maker, methodNode, "java", "lang", "Object"), List.<JCExpression>of(maker.Literal(Javac.getCTCint(TypeTags.class, "INT"), 0)), null); - JCVariableDecl fieldDecl = maker.VarDef( + JCVariableDecl fieldDecl = Javac.recursiveSetGeneratedBy(maker.VarDef( maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (isStatic ? Flags.STATIC : 0)), - methodNode.toName(lockName), objectType, newObjectArray); + methodNode.toName(lockName), objectType, newObjectArray), ast); injectFieldSuppressWarnings(methodNode.up(), fieldDecl); } - if (method.body == null) return false; + if (method.body == null) return; JCExpression lockNode; if (isStatic) { @@ -102,11 +102,10 @@ public class HandleSynchronized implements JavacAnnotationHandler<Synchronized> lockNode = maker.Select(maker.Ident(methodNode.toName("this")), methodNode.toName(lockName)); } - method.body = maker.Block(0, List.<JCStatement>of(maker.Synchronized(lockNode, method.body))); + Javac.recursiveSetGeneratedBy(lockNode, ast); + method.body = Javac.setGeneratedBy(maker.Block(0, List.<JCStatement>of(Javac.setGeneratedBy(maker.Synchronized(lockNode, method.body), ast))), ast); methodNode.rebuild(); - - return true; } @Override public boolean isResolutionBased() { diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index 8bc8036f..48fc90dc 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.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 @@ -69,8 +69,8 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { } } - @Override public boolean handle(AnnotationValues<ToString> annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, ToString.class); + @Override public void handle(AnnotationValues<ToString> annotation, JCAnnotation ast, JavacNode annotationNode) { + deleteAnnotationIfNeccessary(annotationNode, ToString.class); ToString ann = annotation.getInstance(); List<String> excludes = List.from(ann.exclude()); @@ -92,7 +92,7 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { 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 void generateToStringForType(JavacNode typeNode, JavacNode errorNode) { @@ -112,7 +112,7 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, FieldAccess.GETTER); } - private boolean generateToString(JavacNode typeNode, JavacNode errorNode, List<String> excludes, List<String> includes, + private void generateToString(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes, boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) { boolean notAClass = true; if (typeNode.get() instanceof JCClassDecl) { @@ -127,8 +127,8 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { } if (notAClass) { - errorNode.addError("@ToString is only supported on a class or enum."); - return false; + source.addError("@ToString is only supported on a class or enum."); + return; } ListBuffer<JavacNode> nodesForToString = ListBuffer.lb(); @@ -154,22 +154,21 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { switch (methodExists("toString", typeNode)) { case NOT_EXISTS: - JCMethodDecl method = createToString(typeNode, nodesForToString.toList(), includeFieldNames, callSuper, fieldAccess); + JCMethodDecl method = createToString(typeNode, nodesForToString.toList(), includeFieldNames, callSuper, fieldAccess, source.get()); injectMethod(typeNode, method); - 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"); + source.addWarning("Not generating toString(): A method with that name already exists"); } - return true; + break; } - } - private JCMethodDecl createToString(JavacNode typeNode, List<JavacNode> fields, boolean includeFieldNames, boolean callSuper, FieldAccess fieldAccess) { + private JCMethodDecl createToString(JavacNode typeNode, List<JavacNode> fields, boolean includeFieldNames, boolean callSuper, FieldAccess fieldAccess, JCTree source) { TreeMaker maker = typeNode.getTreeMaker(); JCAnnotation overrideAnnotation = maker.Annotation(chainDots(maker, typeNode, "java", "lang", "Override"), List.<JCExpression>nil()); @@ -238,8 +237,8 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { JCBlock body = maker.Block(0, List.of(returnStatement)); - return maker.MethodDef(mods, typeNode.toName("toString"), returnType, - List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + return Javac.recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("toString"), returnType, + List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null), source); } private String getTypeName(JavacNode typeNode) { diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index b21137f7..4dafa360 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -1,5 +1,5 @@ /* - * Copyright © 2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans. + * Copyright © 2010-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 @@ -49,6 +49,8 @@ public class HandleVal extends JavacASTAdapter { @Override public void visitLocal(JavacNode localNode, JCVariableDecl local) { if (local.vartype == null || (!local.vartype.toString().equals("val") && !local.vartype.toString().equals("lombok.val"))) return; + JCTree source = local.vartype; + if (!Javac.typeMatches(val.class, localNode, local.vartype)) return; JCExpression rhsOfEnhancedForLoop = null; @@ -75,7 +77,7 @@ public class HandleVal extends JavacASTAdapter { local.mods.flags |= Flags.FINAL; if (!localNode.shouldDeleteLombokAnnotations()) { - JCAnnotation valAnnotation = localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()); + JCAnnotation valAnnotation = Javac.recursiveSetGeneratedBy(localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()), source); local.mods.annotations = local.mods.annotations == null ? List.of(valAnnotation) : local.mods.annotations.append(valAnnotation); } @@ -118,11 +120,13 @@ public class HandleVal extends JavacASTAdapter { localNode.getAst().setChanged(); } catch (JavacResolution.TypeNotConvertibleException e) { localNode.addError("Cannot use 'val' here because initializer expression does not have a representable type: " + e.getMessage()); - local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst());; + local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst()); } } catch (RuntimeException e) { - local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst());; + local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst()); throw e; + } finally { + Javac.recursiveSetGeneratedBy(local.vartype, source); } } } diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 1fb72dfa..1f0da79a 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009-2010 Reinier Zwitserloot, 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 @@ -78,7 +78,7 @@ public class JavacHandlerUtil { * then removes any import statement that imports this exact annotation (not star imports). * Only does this if the DeleteLombokAnnotations class is in the context. */ - public static void markAnnotationAsProcessed(JavacNode annotation, Class<? extends Annotation> annotationType) { + public static void deleteAnnotationIfNeccessary(JavacNode annotation, Class<? extends Annotation> annotationType) { if (!annotation.shouldDeleteLombokAnnotations()) return; JavacNode parentNode = annotation.directUp(); switch (parentNode.getKind()) { @@ -203,9 +203,7 @@ public class JavacHandlerUtil { for (JCTree def : ((JCClassDecl)node.get()).defs) { if (def instanceof JCVariableDecl) { if (((JCVariableDecl)def).name.contentEquals(fieldName)) { - JavacNode existing = node.getNodeFor(def); - if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER; - return MemberExistsResult.EXISTS_BY_LOMBOK; + return Javac.getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK; } } } @@ -236,11 +234,7 @@ public class JavacHandlerUtil { if (def instanceof JCMethodDecl) { String name = ((JCMethodDecl)def).name.toString(); boolean matches = caseSensitive ? name.equals(methodName) : name.equalsIgnoreCase(methodName); - if (matches) { - JavacNode existing = node.getNodeFor(def); - if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER; - return MemberExistsResult.EXISTS_BY_LOMBOK; - } + if (matches) return Javac.getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK; } } } @@ -264,9 +258,7 @@ public class JavacHandlerUtil { if (def instanceof JCMethodDecl) { if (((JCMethodDecl)def).name.contentEquals("<init>")) { if ((((JCMethodDecl)def).mods.flags & Flags.GENERATEDCONSTR) != 0) continue; - JavacNode existing = node.getNodeFor(def); - if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER; - return MemberExistsResult.EXISTS_BY_LOMBOK; + return Javac.getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK; } } } @@ -448,10 +440,10 @@ public class JavacHandlerUtil { private static void injectField(JavacNode typeNode, JCVariableDecl field, boolean addSuppressWarnings) { JCClassDecl type = (JCClassDecl) typeNode.get(); - if (addSuppressWarnings) addSuppressWarningsAll(field.mods, typeNode, field.pos); + if (addSuppressWarnings) addSuppressWarningsAll(field.mods, typeNode, field.pos, Javac.getGeneratedBy(field)); type.defs = type.defs.append(field); - typeNode.add(field, Kind.FIELD).recursiveSetHandled(); + typeNode.add(field, Kind.FIELD); } /** @@ -479,19 +471,19 @@ public class JavacHandlerUtil { } } - addSuppressWarningsAll(method.mods, typeNode, method.pos); + addSuppressWarningsAll(method.mods, typeNode, method.pos, Javac.getGeneratedBy(method)); type.defs = type.defs.append(method); - typeNode.add(method, Kind.METHOD).recursiveSetHandled(); + typeNode.add(method, Kind.METHOD); } - private static void addSuppressWarningsAll(JCModifiers mods, JavacNode node, int pos) { + private static void addSuppressWarningsAll(JCModifiers mods, JavacNode node, int pos, JCTree source) { TreeMaker maker = node.getTreeMaker(); JCExpression suppressWarningsType = chainDots(maker, node, "java", "lang", "SuppressWarnings"); JCLiteral allLiteral = maker.Literal("all"); suppressWarningsType.pos = pos; allLiteral.pos = pos; - JCAnnotation annotation = maker.Annotation(suppressWarningsType, List.<JCExpression>of(allLiteral)); + JCAnnotation annotation = Javac.recursiveSetGeneratedBy(maker.Annotation(suppressWarningsType, List.<JCExpression>of(allLiteral)), source); annotation.pos = pos; mods.annotations = mods.annotations.append(annotation); } |