diff options
author | Reinier Zwitserloot <reinier@tipit.to> | 2009-11-27 09:53:08 +0100 |
---|---|---|
committer | Reinier Zwitserloot <reinier@tipit.to> | 2009-11-27 09:53:08 +0100 |
commit | 9678c58ec86a18605e62ff813005fddb1cefb392 (patch) | |
tree | 1aec17de05371b3a5ca02e25793e43e33c70e9b3 /src/core/lombok | |
parent | 6838c6be2f8bd8935fa6853067183cf11c013fcd (diff) | |
parent | 2b61c2534b22f07a13d8cb4c97c2ad323c6c4597 (diff) | |
download | lombok-9678c58ec86a18605e62ff813005fddb1cefb392.tar.gz lombok-9678c58ec86a18605e62ff813005fddb1cefb392.tar.bz2 lombok-9678c58ec86a18605e62ff813005fddb1cefb392.zip |
Merge branch 'delombok'
Diffstat (limited to 'src/core/lombok')
-rw-r--r-- | src/core/lombok/core/AST.java | 13 | ||||
-rw-r--r-- | src/core/lombok/core/LombokNode.java | 6 | ||||
-rw-r--r-- | src/core/lombok/eclipse/EclipseAST.java | 3 | ||||
-rw-r--r-- | src/core/lombok/javac/JavacAST.java | 6 | ||||
-rw-r--r-- | src/core/lombok/javac/JavacTransformer.java | 103 | ||||
-rw-r--r-- | src/core/lombok/javac/apt/Processor.java | 67 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleCleanup.java | 2 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleData.java | 1 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java | 1 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleGetter.java | 2 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSetter.java | 2 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSneakyThrows.java | 2 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSynchronized.java | 3 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleToString.java | 2 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacHandlerUtil.java | 51 |
15 files changed, 197 insertions, 67 deletions
diff --git a/src/core/lombok/core/AST.java b/src/core/lombok/core/AST.java index 6d786d1e..e769ce34 100644 --- a/src/core/lombok/core/AST.java +++ b/src/core/lombok/core/AST.java @@ -54,11 +54,24 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, private final String fileName; Map<N, Void> identityDetector = new IdentityHashMap<N, Void>(); private Map<N, L> nodeMap = new IdentityHashMap<N, L>(); + private boolean changed = false; protected AST(String fileName) { this.fileName = fileName == null ? "(unknown).java" : fileName; } + protected void setChanged() { + this.changed = true; + } + + protected void clearChanged() { + this.changed = false; + } + + public boolean isChanged() { + return changed; + } + /** Set the node object that wraps the internal Compilation Unit node. */ protected void setTop(L top) { this.top = top; diff --git a/src/core/lombok/core/LombokNode.java b/src/core/lombok/core/LombokNode.java index c8ee4c00..95c5a0cb 100644 --- a/src/core/lombok/core/LombokNode.java +++ b/src/core/lombok/core/LombokNode.java @@ -126,6 +126,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A, */ @SuppressWarnings("unchecked") public L replaceWith(N newN, Kind newNodeKind) { + ast.setChanged(); L newNode = ast.buildTree(newN, newNodeKind); newNode.parent = parent; for (int i = 0; i < parent.children.size(); i++) { @@ -142,6 +143,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A, * Also affects the underlying (Eclipse/javac) AST. */ public void replaceChildNode(N oldN, N newN) { + ast.setChanged(); ast.replaceStatementInNode(get(), oldN, newN); } @@ -228,6 +230,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A, */ @SuppressWarnings("unchecked") public L add(N newChild, Kind newChildKind) { + ast.setChanged(); L n = ast.buildTree(newChild, newChildKind); if (n == null) return null; n.parent = (L) this; @@ -247,6 +250,8 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A, L newNode = ast.buildTree(get(), kind); + ast.setChanged(); + ast.replaceNewWithExistingOld(oldNodes, newNode); } @@ -265,6 +270,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A, * Does not change the underlying (javac/Eclipse) AST, only the wrapped view. */ public void removeChild(L child) { + ast.setChanged(); children.remove(child); } diff --git a/src/core/lombok/eclipse/EclipseAST.java b/src/core/lombok/eclipse/EclipseAST.java index e42e5de2..7f436ddf 100644 --- a/src/core/lombok/eclipse/EclipseAST.java +++ b/src/core/lombok/eclipse/EclipseAST.java @@ -60,6 +60,7 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> { this.compilationUnitDeclaration = ast; setTop(buildCompilationUnit(ast)); this.completeParse = isComplete(ast); + clearChanged(); } /** {@inheritDoc} */ @@ -201,12 +202,14 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> { public void reparse() { propagateProblems(); if (completeParse) return; + boolean changed = isChanged(); boolean newCompleteParse = isComplete(compilationUnitDeclaration); if (!newCompleteParse) return; top().rebuild(); this.completeParse = true; + if (!changed) clearChanged(); } private static boolean isComplete(CompilationUnitDeclaration unit) { diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index f2c83fb8..93e3f3dc 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -32,7 +32,6 @@ import javax.tools.JavaFileObject; import lombok.core.AST; -import com.sun.source.util.Trees; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.TreeMaker; @@ -66,13 +65,11 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { /** * Creates a new JavacAST of the provided Compilation Unit. * - * @param trees The trees instance to use to inspect the compilation unit. Generate via: - * {@code Trees.getInstance(env)} * @param messager A Messager for warning and error reporting. * @param context A Context object for interfacing with the compiler. * @param top The compilation unit, which serves as the top level node in the tree to be built. */ - public JavacAST(Trees trees, Messager messager, Context context, JCCompilationUnit top) { + public JavacAST(Messager messager, Context context, JCCompilationUnit top) { super(top.sourcefile == null ? null : top.sourcefile.toString()); setTop(buildCompilationUnit(top)); this.context = context; @@ -81,6 +78,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { this.nameTable = Name.Table.instance(context); this.treeMaker = TreeMaker.instance(context); this.symtab = Symtab.instance(context); + clearChanged(); } public Context getContext() { diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java new file mode 100644 index 00000000..5f145460 --- /dev/null +++ b/src/core/lombok/javac/JavacTransformer.java @@ -0,0 +1,103 @@ +/* + * Copyright © 2009 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 + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.javac; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.processing.Messager; + +import com.sun.tools.javac.tree.JCTree.JCAnnotation; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.util.Context; + +public class JavacTransformer { + private final HandlerLibrary handlers; + private final Messager messager; + + public JavacTransformer(Messager messager) { + this.messager = messager; + this.handlers = HandlerLibrary.load(messager); + } + + public boolean transform(Context context, Iterable<JCCompilationUnit> compilationUnits) { + List<JavacAST> asts = new ArrayList<JavacAST>(); + + for (JCCompilationUnit unit : compilationUnits) asts.add(new JavacAST(messager, context, unit)); + + handlers.skipPrintAST(); + for (JavacAST ast : asts) { + ast.traverse(new AnnotationVisitor()); + handlers.callASTVisitors(ast); + } + + handlers.skipAllButPrintAST(); + for (JavacAST ast : asts) { + ast.traverse(new AnnotationVisitor()); + } + + for (JavacAST ast : asts) { + if (ast.isChanged()) return true; + } + return false; + } + + 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(); + } + + @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(); + } + + @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(); + } + + @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(); + } + + @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(); + } + } +} diff --git a/src/core/lombok/javac/apt/Processor.java b/src/core/lombok/javac/apt/Processor.java index 9c851762..b779a680 100644 --- a/src/core/lombok/javac/apt/Processor.java +++ b/src/core/lombok/javac/apt/Processor.java @@ -21,9 +21,7 @@ */ package lombok.javac.apt; -import java.util.ArrayList; import java.util.IdentityHashMap; -import java.util.List; import java.util.Set; import javax.annotation.processing.AbstractProcessor; @@ -36,19 +34,12 @@ import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic.Kind; -import lombok.javac.HandlerLibrary; -import lombok.javac.JavacAST; -import lombok.javac.JavacASTAdapter; -import lombok.javac.JavacNode; +import lombok.javac.JavacTransformer; import com.sun.source.util.TreePath; import com.sun.source.util.Trees; import com.sun.tools.javac.processing.JavacProcessingEnvironment; -import com.sun.tools.javac.tree.JCTree.JCAnnotation; -import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; -import com.sun.tools.javac.tree.JCTree.JCMethodDecl; -import com.sun.tools.javac.tree.JCTree.JCVariableDecl; /** @@ -66,7 +57,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; public class Processor extends AbstractProcessor { private ProcessingEnvironment rawProcessingEnv; private JavacProcessingEnvironment processingEnv; - private HandlerLibrary handlers; + private JavacTransformer transformer; private Trees trees; private String errorToShow; @@ -86,7 +77,7 @@ public class Processor extends AbstractProcessor { this.errorToShow = null; } else { this.processingEnv = (JavacProcessingEnvironment) procEnv; - handlers = HandlerLibrary.load(procEnv.getMessager()); + transformer = new JavacTransformer(procEnv.getMessager()); trees = Trees.instance(procEnv); this.errorToShow = null; } @@ -111,61 +102,11 @@ public class Processor extends AbstractProcessor { if (unit != null) units.put(unit, null); } - List<JavacAST> asts = new ArrayList<JavacAST>(); + transformer.transform(processingEnv.getContext(), units.keySet()); - for (JCCompilationUnit unit : units.keySet()) asts.add( - new JavacAST(trees, processingEnv.getMessager(), processingEnv.getContext(), unit)); - - handlers.skipPrintAST(); - for (JavacAST ast : asts) { - ast.traverse(new AnnotationVisitor()); - handlers.callASTVisitors(ast); - } - - handlers.skipAllButPrintAST(); - for (JavacAST ast : asts) { - ast.traverse(new AnnotationVisitor()); - } return false; } - 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(); - } - - @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(); - } - - @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(); - } - - @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(); - } - - @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(); - } - } - private JCCompilationUnit toUnit(Element element) { TreePath path = trees == null ? null : trees.getPath(element); if (path == null) return null; diff --git a/src/core/lombok/javac/handlers/HandleCleanup.java b/src/core/lombok/javac/handlers/HandleCleanup.java index 88a8e1d7..2c89d9ad 100644 --- a/src/core/lombok/javac/handlers/HandleCleanup.java +++ b/src/core/lombok/javac/handlers/HandleCleanup.java @@ -21,6 +21,7 @@ */ package lombok.javac.handlers; +import static lombok.javac.handlers.JavacHandlerUtil.markAnnotationAsProcessed; import lombok.Cleanup; import lombok.core.AnnotationValues; import lombok.core.AST.Kind; @@ -53,6 +54,7 @@ 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); String cleanupName = annotation.getInstance().value(); if (cleanupName.length() == 0) { annotationNode.addError("cleanupName cannot be the empty string."); diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java index eef7f78d..a0315d08 100644 --- a/src/core/lombok/javac/handlers/HandleData.java +++ b/src/core/lombok/javac/handlers/HandleData.java @@ -59,6 +59,7 @@ import com.sun.tools.javac.util.List; @ProviderFor(JavacAnnotationHandler.class) public class HandleData implements JavacAnnotationHandler<Data> { @Override public boolean handle(AnnotationValues<Data> annotation, JCAnnotation ast, JavacNode annotationNode) { + markAnnotationAsProcessed(annotationNode, Data.class); JavacNode typeNode = annotationNode.up(); JCClassDecl typeDecl = null; if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl)typeNode.get(); diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index 61a4ef63..f388336d 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -72,6 +72,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd } @Override public boolean handle(AnnotationValues<EqualsAndHashCode> annotation, JCAnnotation ast, JavacNode annotationNode) { + markAnnotationAsProcessed(annotationNode, EqualsAndHashCode.class); EqualsAndHashCode ann = annotation.getInstance(); List<String> excludes = List.from(ann.exclude()); List<String> includes = List.from(ann.of()); diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index e60e426d..b0343eaf 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -80,8 +80,10 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { } @Override public boolean handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) { + markAnnotationAsProcessed(annotationNode, Getter.class); JavacNode fieldNode = annotationNode.up(); AccessLevel level = annotation.getInstance().value(); + if (level == AccessLevel.NONE) return true; return createGetterForField(level, fieldNode, annotationNode, true); diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 84032e9c..1d029f33 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -82,8 +82,10 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { } @Override public boolean handle(AnnotationValues<Setter> annotation, JCAnnotation ast, JavacNode annotationNode) { + markAnnotationAsProcessed(annotationNode, Setter.class); JavacNode fieldNode = annotationNode.up(); AccessLevel level = annotation.getInstance().value(); + if (level == AccessLevel.NONE) return true; return createSetterForField(level, fieldNode, annotationNode, true); diff --git a/src/core/lombok/javac/handlers/HandleSneakyThrows.java b/src/core/lombok/javac/handlers/HandleSneakyThrows.java index e7879dd1..8a185e87 100644 --- a/src/core/lombok/javac/handlers/HandleSneakyThrows.java +++ b/src/core/lombok/javac/handlers/HandleSneakyThrows.java @@ -22,6 +22,7 @@ package lombok.javac.handlers; import static lombok.javac.handlers.JavacHandlerUtil.chainDots; +import static lombok.javac.handlers.JavacHandlerUtil.markAnnotationAsProcessed; import java.util.ArrayList; import java.util.Collection; @@ -49,6 +50,7 @@ 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); Collection<String> exceptionNames = annotation.getRawExpressions("value"); List<JCExpression> memberValuePairs = ast.getArguments(); diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java index c86d99c6..eaa0ad6d 100644 --- a/src/core/lombok/javac/handlers/HandleSynchronized.java +++ b/src/core/lombok/javac/handlers/HandleSynchronized.java @@ -51,10 +51,12 @@ public class HandleSynchronized implements JavacAnnotationHandler<Synchronized> private static final String STATIC_LOCK_NAME = "$LOCK"; @Override public boolean handle(AnnotationValues<Synchronized> annotation, JCAnnotation ast, JavacNode annotationNode) { + markAnnotationAsProcessed(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; } @@ -62,6 +64,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; } boolean isStatic = (method.mods.flags & Flags.STATIC) != 0; diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index f7251ab8..dd3df620 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -68,6 +68,8 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { } @Override public boolean handle(AnnotationValues<ToString> annotation, JCAnnotation ast, JavacNode annotationNode) { + markAnnotationAsProcessed(annotationNode, ToString.class); + ToString ann = annotation.getInstance(); List<String> excludes = List.from(ann.exclude()); List<String> includes = List.from(ann.of()); diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 34d8b849..caa8a998 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -21,6 +21,7 @@ */ package lombok.javac.handlers; +import java.lang.annotation.Annotation; import java.util.regex.Pattern; import lombok.AccessLevel; @@ -34,7 +35,9 @@ 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; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCImport; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; @@ -58,6 +61,54 @@ public class JavacHandlerUtil { } /** + * Removes the annotation from javac's AST, then removes it from lombok's AST, + * then removes any import statement that imports this exact annotation (not star imports). + */ + public static void markAnnotationAsProcessed(JavacNode annotation, Class<? extends Annotation> annotationType) { + JavacNode parentNode = annotation.directUp(); + switch (parentNode.getKind()) { + case FIELD: + case ARGUMENT: + case LOCAL: + JCVariableDecl variable = (JCVariableDecl) parentNode.get(); + variable.mods.annotations = filterList(variable.mods.annotations, annotation.get()); + break; + case METHOD: + JCMethodDecl method = (JCMethodDecl) parentNode.get(); + method.mods.annotations = filterList(method.mods.annotations, annotation.get()); + break; + default: + throw new IllegalStateException("Don't know how to remove annotations from: " + parentNode.getKind()); + } + parentNode.removeChild(annotation); + + JCCompilationUnit unit = (JCCompilationUnit) annotation.top().get(); + deleteImportFromCompilationUnit(unit, annotationType.getName()); + } + + private static void deleteImportFromCompilationUnit(JCCompilationUnit unit, String name) { + List<JCTree> newDefs = List.nil(); + + for (JCTree def : unit.defs) { + boolean delete = false; + if (def instanceof JCImport) { + JCImport imp0rt = (JCImport)def; + delete = (!imp0rt.staticImport && imp0rt.qualid.toString().equals(name)); + } + if (!delete) newDefs = newDefs.append(def); + } + unit.defs = newDefs; + } + + private static List<JCAnnotation> filterList(List<JCAnnotation> annotations, JCTree jcTree) { + List<JCAnnotation> newAnnotations = List.nil(); + for (JCAnnotation ann : annotations) { + if (jcTree != ann) newAnnotations = newAnnotations.append(ann); + } + return newAnnotations; + } + + /** * Translates the given field into all possible getter names. * Convenient wrapper around {@link TransformationsUtil#toAllGetterNames(CharSequence, boolean)}. */ |