From 527b992a074c1c65727bc52c820d40340f074a6b Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 6 Jul 2009 05:48:42 +0200 Subject: Last massive documentation dump. All basic javadoc is now done, though especially the docs on the lombok annotations in the lombok package need far more massaging. Also added a feature to HandleSynchronized to not auto-generate the locker fields if a specific name is provided (because, imagine you typoed those. You'd never find it!) --- src/lombok/javac/JavacAST.java | 87 ++++++++++++++++++++++- src/lombok/javac/JavacASTAdapter.java | 65 +++++++++++++++++ src/lombok/javac/JavacASTVisitor.java | 45 ++++++++++-- src/lombok/javac/JavacAnnotationHandler.java | 2 +- src/lombok/javac/apt/Processor.java | 2 + src/lombok/javac/handlers/HandleCleanup.java | 24 +++++++ src/lombok/javac/handlers/HandleData.java | 24 +++++++ src/lombok/javac/handlers/HandleGetter.java | 36 ++++++++++ src/lombok/javac/handlers/HandlePrintAST.java | 24 +++++++ src/lombok/javac/handlers/HandleSetter.java | 36 ++++++++++ src/lombok/javac/handlers/HandleSneakyThrows.java | 24 +++++++ src/lombok/javac/handlers/HandleSynchronized.java | 34 ++++++++- src/lombok/javac/handlers/PKG.java | 80 ++++++++++++++++++++- 13 files changed, 473 insertions(+), 10 deletions(-) (limited to 'src/lombok/javac') diff --git a/src/lombok/javac/JavacAST.java b/src/lombok/javac/JavacAST.java index 4eecbc68..c68d3c19 100644 --- a/src/lombok/javac/JavacAST.java +++ b/src/lombok/javac/JavacAST.java @@ -1,3 +1,24 @@ +/* + * 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.lang.reflect.Field; @@ -30,6 +51,10 @@ import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +/** + * Wraps around javac's internal AST view to add useful features as well as the ability to visit parents from children, + * something javac's own AST system does not offer. + */ public class JavacAST extends AST { private final Messager messager; private final Name.Table nameTable; @@ -37,6 +62,14 @@ public class JavacAST extends AST { private final Symtab symtab; private final Log log; + /** + * Creates a new JavacAST of the provided Compilation Unit. + * + * @param trees The trees instance to use to inspect the compilation unit. Generate via: + * Trees.getInstance(env) + * @param env The ProcessingEnvironment object passed e.g. to an annotation processor. + * @param top The compilation unit, which serves as the top level node in the tree to be built. + */ public JavacAST(Trees trees, JavacProcessingEnvironment env, JCCompilationUnit top) { super(top.sourcefile == null ? null : top.sourcefile.toString()); setTop(buildCompilationUnit(top)); @@ -47,11 +80,13 @@ public class JavacAST extends AST { this.symtab = Symtab.instance(env.getContext()); } + /** {@inheritDoc} */ @Override public String getPackageDeclaration() { JCCompilationUnit unit = (JCCompilationUnit)top().get(); return unit.pid instanceof JCFieldAccess ? unit.pid.toString() : null; } + /** {@inheritDoc} */ @Override public Collection getImportStatements() { List imports = new ArrayList(); JCCompilationUnit unit = (JCCompilationUnit)top().get(); @@ -64,6 +99,10 @@ public class JavacAST extends AST { return imports; } + /** + * Runs through the entire AST, starting at the compilation unit, calling the provided visitor's visit methods + * for each node, depth first. + */ public void traverse(JavacASTVisitor visitor) { top().traverse(visitor); } @@ -74,26 +113,32 @@ public class JavacAST extends AST { } } + /** {@inheritDoc} */ @Override public Node top() { return (Node) super.top(); } + /** {@inheritDoc} */ @Override public Node get(JCTree astNode) { return (Node) super.get(astNode); } + /** @return A Name object generated for the proper name table belonging to this AST. */ public Name toName(String name) { return nameTable.fromString(name); } + /** @return A TreeMaker instance that you can use to create new AST nodes. */ public TreeMaker getTreeMaker() { return treeMaker; } + /** @return The symbol table used by this AST for symbols. */ public Symtab getSymbolTable() { return symtab; } + /** {@inheritDoc} */ @Override protected Node buildTree(JCTree node, Kind kind) { switch ( kind ) { case COMPILATION_UNIT: @@ -214,6 +259,7 @@ public class JavacAST extends AST { return putInMap(new Node(statement, childNodes, Kind.STATEMENT)); } + /** For javac, both JCExpression and JCStatement are considered as valid children types. */ protected Collection> getStatementTypes() { Collection> collection = new ArrayList>(2); collection.add(JCStatement.class); @@ -225,11 +271,20 @@ public class JavacAST extends AST { if ( node != null ) nodes.add(node); } + /** + * Javac specific version of the AST.Node class. + */ public class Node extends AST.Node { + /** + * See the {@link AST.Node} constructor for information. + */ public Node(JCTree node, List children, Kind kind) { super(node, children, kind); } + /** + * Visits this node and all child nodes depth-first, calling the provided visitor's visit methods. + */ public void traverse(JavacASTVisitor visitor) { switch ( this.getKind() ) { case COMPILATION_UNIT: @@ -301,6 +356,7 @@ public class JavacAST extends AST { } } + /** {@inheritDoc} */ @Override public String getName() { final Name n; @@ -312,6 +368,7 @@ public class JavacAST extends AST { return n == null ? null : n.toString(); } + /** {@inheritDoc} */ @Override protected boolean calculateIsStructurallySignificant() { if ( node instanceof JCClassDecl ) return true; if ( node instanceof JCMethodDecl ) return true; @@ -320,14 +377,29 @@ public class JavacAST extends AST { return false; } + /** + * Convenient shortcut to the owning JavacAST object's getTreeMaker method. + * + * @see JavacAST#getTreeMaker() + */ public TreeMaker getTreeMaker() { return treeMaker; } + /** + * Convenient shortcut to the owning JavacAST object's getSymbolTable method. + * + * @see JavacAST#getSymbolTable() + */ public Symtab getSymbolTable() { return symtab; } + /** + * Convenient shortcut to the owning JavacAST object's toName method. + * + * @see JavacAST#toName(String) + */ public Name toName(String name) { return JavacAST.this.toName(name); } @@ -358,18 +430,30 @@ public class JavacAST extends AST { return (Collection) super.down(); } + /** + * Generates an compiler error focused on the AST node represented by this node object. + */ public void addError(String message) { printMessage(Diagnostic.Kind.ERROR, message, this, null); } + /** + * Generates an compiler error focused on the AST node represented by this node object. + */ public void addError(String message, DiagnosticPosition pos) { printMessage(Diagnostic.Kind.ERROR, message, null, pos); } + /** + * Generates a compiler warning focused on the AST node represented by this node object. + */ public void addWarning(String message) { printMessage(Diagnostic.Kind.WARNING, message, this, null); } + /** + * Generates a compiler warning focused on the AST node represented by this node object. + */ public void addWarning(String message, DiagnosticPosition pos) { printMessage(Diagnostic.Kind.WARNING, message, null, pos); } @@ -409,6 +493,7 @@ public class JavacAST extends AST { } } + /** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override protected void setElementInASTCollection(Field field, Object refField, List> chain, Collection collection, int idx, JCTree newN) throws IllegalAccessException { com.sun.tools.javac.util.List list = setElementInConsList(chain, collection, ((List)collection).get(idx), newN); @@ -439,7 +524,7 @@ public class JavacAST extends AST { if ( repl ) return com.sun.tools.javac.util.List.from(a); else return oldL; } - + private void increaseErrorCount(Messager messager) { try { Field f = messager.getClass().getDeclaredField("errorCount"); diff --git a/src/lombok/javac/JavacASTAdapter.java b/src/lombok/javac/JavacASTAdapter.java index 5d678f44..b720ea32 100644 --- a/src/lombok/javac/JavacASTAdapter.java +++ b/src/lombok/javac/JavacASTAdapter.java @@ -1,3 +1,24 @@ +/* + * 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 lombok.javac.JavacAST.Node; @@ -10,26 +31,70 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +/** + * Standard adapter for the {@link JavacASTVisitor} interface. Every method on that interface + * has been implemented with an empty body. Override whichever methods you need. + */ public class JavacASTAdapter implements JavacASTVisitor { + /** {@inheritDoc} */ @Override public void visitCompilationUnit(Node top, JCCompilationUnit unit) {} + + /** {@inheritDoc} */ @Override public void endVisitCompilationUnit(Node top, JCCompilationUnit unit) {} + + /** {@inheritDoc} */ @Override public void visitType(Node typeNode, JCClassDecl type) {} + + /** {@inheritDoc} */ @Override public void visitAnnotationOnType(JCClassDecl type, Node annotationNode, JCAnnotation annotation) {} + + /** {@inheritDoc} */ @Override public void endVisitType(Node typeNode, JCClassDecl type) {} + + /** {@inheritDoc} */ @Override public void visitField(Node fieldNode, JCVariableDecl field) {} + + /** {@inheritDoc} */ @Override public void visitAnnotationOnField(JCVariableDecl field, Node annotationNode, JCAnnotation annotation) {} + + /** {@inheritDoc} */ @Override public void endVisitField(Node fieldNode, JCVariableDecl field) {} + + /** {@inheritDoc} */ @Override public void visitInitializer(Node initializerNode, JCBlock initializer) {} + + /** {@inheritDoc} */ @Override public void endVisitInitializer(Node initializerNode, JCBlock initializer) {} + + /** {@inheritDoc} */ @Override public void visitMethod(Node methodNode, JCMethodDecl method) {} + + /** {@inheritDoc} */ @Override public void visitAnnotationOnMethod(JCMethodDecl method, Node annotationNode, JCAnnotation annotation) {} + + /** {@inheritDoc} */ @Override public void endVisitMethod(Node methodNode, JCMethodDecl method) {} + + /** {@inheritDoc} */ @Override public void visitMethodArgument(Node argumentNode, JCVariableDecl argument, JCMethodDecl method) {} + + /** {@inheritDoc} */ @Override public void visitAnnotationOnMethodArgument(JCVariableDecl argument, JCMethodDecl method, Node annotationNode, JCAnnotation annotation) {} + /** {@inheritDoc} */ @Override public void endVisitMethodArgument(Node argumentNode, JCVariableDecl argument, JCMethodDecl method) {} + + /** {@inheritDoc} */ @Override public void visitLocal(Node localNode, JCVariableDecl local) {} + + /** {@inheritDoc} */ @Override public void visitAnnotationOnLocal(JCVariableDecl local, Node annotationNode, JCAnnotation annotation) {} + + /** {@inheritDoc} */ @Override public void endVisitLocal(Node localNode, JCVariableDecl local) {} + + /** {@inheritDoc} */ @Override public void visitStatement(Node statementNode, JCTree statement) {} + + /** {@inheritDoc} */ @Override public void endVisitStatement(Node statementNode, JCTree statement) {} } diff --git a/src/lombok/javac/JavacASTVisitor.java b/src/lombok/javac/JavacASTVisitor.java index 15d848dd..ac953974 100644 --- a/src/lombok/javac/JavacASTVisitor.java +++ b/src/lombok/javac/JavacASTVisitor.java @@ -1,7 +1,26 @@ +/* + * 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.io.File; -import java.io.FileNotFoundException; import java.io.PrintStream; import lombok.javac.JavacAST.Node; @@ -15,6 +34,10 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +/** + * Implement so you can ask any JavacAST.Node to traverse depth-first through all children, + * calling the appropriate visit and endVisit methods. + */ public interface JavacASTVisitor { /** * Called at the very beginning and end. @@ -71,20 +94,30 @@ public interface JavacASTVisitor { void visitStatement(Node statementNode, JCTree statement); void endVisitStatement(Node statementNode, JCTree statement); + /** + * Prints the structure of an AST. + */ public static class Printer implements JavacASTVisitor { private final PrintStream out; private final boolean printContent; private int disablePrinting = 0; private int indent = 0; + /** + * @param printContent if true, method and initializer bodies are printed directly, as java code, + * instead of a tree listing of every AST node inside it. + */ public Printer(boolean printContent) { this(printContent, System.out); } - public Printer(boolean printContent, File file) throws FileNotFoundException { - this(printContent, new PrintStream(file)); - } - + /** + * @param printContent if true, method and initializer bodies are printed directly, as java code, + * instead of a tree listing of every AST node inside it. + * @param PrintStream write output to this stream. You must close it yourself. flush() is called after every line. + * + * @see java.io.PrintStream#flush() + */ public Printer(boolean printContent, PrintStream out) { this.printContent = printContent; this.out = out; diff --git a/src/lombok/javac/JavacAnnotationHandler.java b/src/lombok/javac/JavacAnnotationHandler.java index 65832eab..fcd0cbba 100644 --- a/src/lombok/javac/JavacAnnotationHandler.java +++ b/src/lombok/javac/JavacAnnotationHandler.java @@ -50,7 +50,7 @@ public interface JavacAnnotationHandler { * @param ast The javac AST node representing the 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 focussed on the annotation. + * as access useful methods such as generating warnings or errors focused on the annotation. * @return true if you don't want to be called again about this annotation during this * compile session (you've handled it), or false to indicate you aren't done yet. */ diff --git a/src/lombok/javac/apt/Processor.java b/src/lombok/javac/apt/Processor.java index 7bffd33e..22daeab1 100644 --- a/src/lombok/javac/apt/Processor.java +++ b/src/lombok/javac/apt/Processor.java @@ -66,6 +66,7 @@ public class Processor extends AbstractProcessor { private HandlerLibrary handlers; private Trees trees; + /** {@inheritDoc} */ @Override public void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); if ( !(processingEnv instanceof JavacProcessingEnvironment) ) this.processingEnv = null; @@ -76,6 +77,7 @@ public class Processor extends AbstractProcessor { } } + /** {@inheritDoc} */ @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if ( processingEnv == null ) return false; diff --git a/src/lombok/javac/handlers/HandleCleanup.java b/src/lombok/javac/handlers/HandleCleanup.java index 39f2c242..04ed2ed6 100644 --- a/src/lombok/javac/handlers/HandleCleanup.java +++ b/src/lombok/javac/handlers/HandleCleanup.java @@ -1,3 +1,24 @@ +/* + * 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.handlers; import lombok.Cleanup; @@ -26,6 +47,9 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; +/** + * Handles the lombok.Cleanup annotation for javac. + */ @ProviderFor(JavacAnnotationHandler.class) public class HandleCleanup implements JavacAnnotationHandler { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, Node annotationNode) { diff --git a/src/lombok/javac/handlers/HandleData.java b/src/lombok/javac/handlers/HandleData.java index 5da08759..d3974c58 100644 --- a/src/lombok/javac/handlers/HandleData.java +++ b/src/lombok/javac/handlers/HandleData.java @@ -1,3 +1,24 @@ +/* + * 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.handlers; import java.lang.reflect.Modifier; @@ -37,6 +58,9 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; +/** + * Handles the lombok.Data annotation for javac. + */ @ProviderFor(JavacAnnotationHandler.class) public class HandleData implements JavacAnnotationHandler { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, Node annotationNode) { diff --git a/src/lombok/javac/handlers/HandleGetter.java b/src/lombok/javac/handlers/HandleGetter.java index f66247ff..18e02a58 100644 --- a/src/lombok/javac/handlers/HandleGetter.java +++ b/src/lombok/javac/handlers/HandleGetter.java @@ -1,3 +1,24 @@ +/* + * 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.handlers; import static lombok.javac.handlers.PKG.*; @@ -24,8 +45,23 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +/** + * Handles the lombok.Getter annotation for javac. + */ @ProviderFor(JavacAnnotationHandler.class) public class HandleGetter implements JavacAnnotationHandler { + /** + * Generates a getter on the stated field. + * + * Used by {@link HandleData}. + * + * The difference between this call and the handle method is as follows: + * + * If there is a lombok.Getter annotation on the field, it is used and the + * same rules apply (e.g. warning if the method already exists, stated access level applies). + * If not, the getter is still generated if it isn't already there, though there will not + * be a warning if its already there. The default access level is used. + */ public void generateGetterForField(Node fieldNode, DiagnosticPosition pos) { AccessLevel level = AccessLevel.PUBLIC; Node errorNode = fieldNode; diff --git a/src/lombok/javac/handlers/HandlePrintAST.java b/src/lombok/javac/handlers/HandlePrintAST.java index f2009c71..aa7b0ab9 100644 --- a/src/lombok/javac/handlers/HandlePrintAST.java +++ b/src/lombok/javac/handlers/HandlePrintAST.java @@ -1,3 +1,24 @@ +/* + * 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.handlers; import java.io.File; @@ -15,6 +36,9 @@ import lombok.javac.JavacASTVisitor; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacAST.Node; +/** + * Handles the lombok.core.PrintAST annotation for javac. + */ @ProviderFor(JavacAnnotationHandler.class) public class HandlePrintAST implements JavacAnnotationHandler { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, Node annotationNode) { diff --git a/src/lombok/javac/handlers/HandleSetter.java b/src/lombok/javac/handlers/HandleSetter.java index 2b766db1..817d3011 100644 --- a/src/lombok/javac/handlers/HandleSetter.java +++ b/src/lombok/javac/handlers/HandleSetter.java @@ -1,3 +1,24 @@ +/* + * 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.handlers; import static lombok.javac.handlers.PKG.*; @@ -27,8 +48,23 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +/** + * Handles the lombok.Setter annotation for javac. + */ @ProviderFor(JavacAnnotationHandler.class) public class HandleSetter implements JavacAnnotationHandler { + /** + * Generates a setter on the stated field. + * + * Used by {@link HandleData}. + * + * The difference between this call and the handle method is as follows: + * + * If there is a lombok.Setter annotation on the field, it is used and the + * same rules apply (e.g. warning if the method already exists, stated access level applies). + * If not, the setter is still generated if it isn't already there, though there will not + * be a warning if its already there. The default access level is used. + */ public void generateSetterForField(Node fieldNode, DiagnosticPosition pos) { AccessLevel level = AccessLevel.PUBLIC; Node errorNode = fieldNode; diff --git a/src/lombok/javac/handlers/HandleSneakyThrows.java b/src/lombok/javac/handlers/HandleSneakyThrows.java index b21468ee..4a4ab09b 100644 --- a/src/lombok/javac/handlers/HandleSneakyThrows.java +++ b/src/lombok/javac/handlers/HandleSneakyThrows.java @@ -1,3 +1,24 @@ +/* + * 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.handlers; import static lombok.javac.handlers.PKG.chainDots; @@ -24,6 +45,9 @@ import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; +/** + * Handles the lombok.SneakyThrows annotation for javac. + */ @ProviderFor(JavacAnnotationHandler.class) public class HandleSneakyThrows implements JavacAnnotationHandler { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, Node annotationNode) { diff --git a/src/lombok/javac/handlers/HandleSynchronized.java b/src/lombok/javac/handlers/HandleSynchronized.java index 84508171..efc6daf0 100644 --- a/src/lombok/javac/handlers/HandleSynchronized.java +++ b/src/lombok/javac/handlers/HandleSynchronized.java @@ -1,3 +1,24 @@ +/* + * 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.handlers; import static lombok.javac.handlers.PKG.*; @@ -21,6 +42,9 @@ import lombok.core.AST.Kind; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacAST.Node; +/** + * Handles the lombok.Synchronized annotation for javac. + */ @ProviderFor(JavacAnnotationHandler.class) public class HandleSynchronized implements JavacAnnotationHandler { private static final String INSTANCE_LOCK_NAME = "$lock"; @@ -42,11 +66,19 @@ public class HandleSynchronized implements JavacAnnotationHandler } boolean isStatic = (method.mods.flags & Flags.STATIC) != 0; String lockName = annotation.getInstance().value(); - if ( lockName.length() == 0 ) lockName = isStatic ? STATIC_LOCK_NAME : INSTANCE_LOCK_NAME; + boolean autoMake = false; + if ( lockName.length() == 0 ) { + autoMake = true; + lockName = isStatic ? STATIC_LOCK_NAME : INSTANCE_LOCK_NAME; + } TreeMaker maker = methodNode.getTreeMaker(); if ( fieldExists(lockName, methodNode) == MemberExistsResult.NOT_EXISTS ) { + if ( !autoMake ) { + annotationNode.addError("The field " + new String(lockName) + " does not exist."); + return true; + } JCExpression objectType = chainDots(maker, methodNode, "java", "lang", "Object"); //We use 'new Object[0];' because quite unlike 'new Object();', empty arrays *ARE* serializable! JCNewArray newObjectArray = maker.NewArray(chainDots(maker, methodNode, "java", "lang", "Object"), diff --git a/src/lombok/javac/handlers/PKG.java b/src/lombok/javac/handlers/PKG.java index b7a02985..ef6b3eba 100644 --- a/src/lombok/javac/handlers/PKG.java +++ b/src/lombok/javac/handlers/PKG.java @@ -1,3 +1,24 @@ +/* + * 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.handlers; import java.lang.reflect.Modifier; @@ -16,9 +37,17 @@ import lombok.core.TransformationsUtil; import lombok.core.AST.Kind; import lombok.javac.JavacAST; +/** + * Container for static utility methods relevant to this package. + */ class PKG { - private PKG() {} + private PKG() { + //Prevent instantiation + } + /** + * @return the likely getter name for the stated field. (e.g. private boolean foo; to isFoo). + */ static String toGetterName(JCVariableDecl field) { CharSequence fieldName = field.name; @@ -27,16 +56,26 @@ class PKG { return TransformationsUtil.toGetterName(fieldName, isBoolean); } + /** + * @return the likely setter name for the stated field. (e.g. private boolean foo; to setFoo). + */ static String toSetterName(JCVariableDecl field) { CharSequence fieldName = field.name; return TransformationsUtil.toSetterName(fieldName); } + /** Serves as return value for the methods that check for the existence of fields and methods. */ enum MemberExistsResult { NOT_EXISTS, EXISTS_BY_USER, EXISTS_BY_LOMBOK; } + /** + * Checks if there is a field with the provided name. + * + * @param fieldName the field name to check for. + * @param node Any node that represents the Type (JCClassDecl) to check for, or any child node thereof. + */ static MemberExistsResult fieldExists(String fieldName, JavacAST.Node node) { while ( node != null && !(node.get() instanceof JCClassDecl) ) { node = node.up(); @@ -57,6 +96,13 @@ class PKG { return MemberExistsResult.NOT_EXISTS; } + /** + * Checks if there is a method with the provided name. In case of multiple methods (overloading), only + * the first method decides if EXISTS_BY_USER or EXISTS_BY_LOMBOK is returned. + * + * @param methodName the method name to check for. + * @param node Any node that represents the Type (JCClassDecl) to check for, or any child node thereof. + */ static MemberExistsResult methodExists(String methodName, JavacAST.Node node) { while ( node != null && !(node.get() instanceof JCClassDecl) ) { node = node.up(); @@ -77,6 +123,12 @@ class PKG { return MemberExistsResult.NOT_EXISTS; } + /** + * Checks if there is a (non-default) constructor. In case of multiple constructors (overloading), only + * the first constructor decides if EXISTS_BY_USER or EXISTS_BY_LOMBOK is returned. + * + * @param node Any node that represents the Type (JCClassDecl) to check for, or any child node thereof. + */ static MemberExistsResult constructorExists(JavacAST.Node node) { while ( node != null && !(node.get() instanceof JCClassDecl) ) { node = node.up(); @@ -98,6 +150,11 @@ class PKG { return MemberExistsResult.NOT_EXISTS; } + /** + * Turns an AccessLevel instance into the flag bit used by javac. + * + * @see java.lang.Modifier + */ static int toJavacModifier(AccessLevel accessLevel) { switch ( accessLevel ) { case MODULE: @@ -113,6 +170,11 @@ class PKG { } } + /** + * Adds the given new field declaration to the provided type AST Node. + * + * Also takes care of updating the JavacAST. + */ static void injectField(JavacAST.Node typeNode, JCVariableDecl field) { JCClassDecl type = (JCClassDecl) typeNode.get(); @@ -121,6 +183,12 @@ class PKG { typeNode.add(field, Kind.FIELD).recursiveSetHandled(); } + /** + * Adds the given new method declaration to the provided type AST Node. + * Can also inject constructors. + * + * Also takes care of updating the JavacAST. + */ static void injectMethod(JavacAST.Node typeNode, JCMethodDecl method) { JCClassDecl type = (JCClassDecl) typeNode.get(); @@ -154,6 +222,16 @@ class PKG { return out; } + /** + * In javac, dotted access of any kind, from java.lang.String to var.methodName + * is represented by a fold-left of Select nodes with the leftmost string represented by + * a Ident node. This method generates such an expression. + * + * For example, maker.Select(maker.Select(maker.Ident(NAME[java]), NAME[lang]), NAME[String]). + * + * @see com.sun.tools.javac.tree.JCTree.JCIdent + * @see com.sun.tools.javac.tree.JCTree.JCFieldAccess + */ static JCExpression chainDots(TreeMaker maker, JavacAST.Node node, String... elems) { assert elems != null; assert elems.length > 0; -- cgit