From 17bcfda43b9e939ac22d5247ef98905741650432 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Tue, 2 Nov 2010 20:39:58 +0100 Subject: Issue 154: Add null-check to @Cleanup --- src/core/lombok/javac/handlers/HandleCleanup.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleCleanup.java b/src/core/lombok/javac/handlers/HandleCleanup.java index 2c89d9ad..779dd3ea 100644 --- a/src/core/lombok/javac/handlers/HandleCleanup.java +++ b/src/core/lombok/javac/handlers/HandleCleanup.java @@ -30,10 +30,12 @@ import lombok.javac.JavacNode; import org.mangosdk.spi.ProviderFor; +import com.sun.tools.javac.code.TypeTags; 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; +import com.sun.tools.javac.tree.JCTree.JCBinary; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCCase; import com.sun.tools.javac.tree.JCTree.JCCatch; @@ -41,6 +43,7 @@ import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCExpressionStatement; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; +import com.sun.tools.javac.tree.JCTree.JCIf; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeCast; @@ -108,11 +111,16 @@ public class HandleCleanup implements JavacAnnotationHandler { doAssignmentCheck(annotationNode, tryBlock, decl.name); TreeMaker maker = annotationNode.getTreeMaker(); - JCFieldAccess cleanupCall = maker.Select(maker.Ident(decl.name), annotationNode.toName(cleanupName)); - List finalizerBlock = List.of(maker.Exec( - maker.Apply(List.nil(), cleanupCall, List.nil()))); + JCFieldAccess cleanupMethod = maker.Select(maker.Ident(decl.name), annotationNode.toName(cleanupName)); + List cleanupCall = List.of(maker.Exec( + maker.Apply(List.nil(), cleanupMethod, List.nil()))); + + JCBinary isNull = maker.Binary(JCTree.NE, maker.Ident(decl.name), maker.Literal(TypeTags.BOT, null)); + + JCIf ifNotNullCleanup = maker.If(isNull, maker.Block(0, cleanupCall), null); + + JCBlock finalizer = maker.Block(0, List.of(ifNotNullCleanup)); - JCBlock finalizer = maker.Block(0, finalizerBlock); newStatements = newStatements.append(maker.Try(maker.Block(0, tryBlock), List.nil(), finalizer)); if (blockNode instanceof JCBlock) { -- cgit From f1cf083890c223bf7245190264438740ee724bc9 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 3 Nov 2010 00:42:58 +0100 Subject: val in java, including tests and javac resolution utilities. --- src/core/lombok/javac/handlers/HandleVal.java | 104 ++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/core/lombok/javac/handlers/HandleVal.java (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java new file mode 100644 index 00000000..a6f22093 --- /dev/null +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -0,0 +1,104 @@ +/* + * Copyright © 2010 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.javac.JavacASTAdapter; +import lombok.javac.JavacASTVisitor; +import lombok.javac.JavacNode; +import lombok.javac.JavacResolution; + +import org.mangosdk.spi.ProviderFor; + +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; +import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; + +@ProviderFor(JavacASTVisitor.class) +public class HandleVal extends JavacASTAdapter { + @Override public boolean isResolutionBased() { + return true; + } + + @Override public void visitLocal(JavacNode localNode, JCVariableDecl local) { + if (local.vartype != null && local.vartype.toString().equals("val")) { + JCExpression rhsOfEnhancedForLoop = null; + if (local.init == null) { + JCTree parentRaw = localNode.directUp().get(); + if (parentRaw instanceof JCEnhancedForLoop) { + JCEnhancedForLoop efl = (JCEnhancedForLoop) parentRaw; + if (efl.var == local) rhsOfEnhancedForLoop = efl.expr; + } + } + + if (rhsOfEnhancedForLoop == null && local.init == null) { + localNode.addError("'val' on a local variable requires an initializer expression"); + return; + } + + local.mods.flags |= Flags.FINAL; + JCExpression oldVarType = local.vartype; + local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst()); + + Type type; + try { + if (rhsOfEnhancedForLoop == null) { + if (local.init.type == null) { + JavacResolution resolver = new JavacResolution(localNode.getContext()); + type = ((JCExpression) resolver.resolve(localNode).get(local.init)).type; + } else { + type = local.init.type; + } + } else { + if (rhsOfEnhancedForLoop.type == null) { + JavacResolution resolver = new JavacResolution(localNode.getContext()); + type = ((JCExpression) resolver.resolve(localNode.directUp()).get(rhsOfEnhancedForLoop)).type; + } else { + type = rhsOfEnhancedForLoop.type; + } + } + + try { + JCExpression replacement; + + if (rhsOfEnhancedForLoop != null) { + localNode.addError("For now 'val' cannot be used in enhanced for loops. Fixing this is a high priority lombok issue though!"); + return; + // TODO: Fix enhanced for loops - then uncomment a bunch of lines in test/transform/resource/*/ValInFor.java + } + replacement = JavacResolution.typeToJCTree(type, localNode.getTreeMaker(), localNode.getAst()); + if (replacement != null) local.vartype = replacement; + else local.vartype = oldVarType; + } catch (JavacResolution.TypeNotConvertibleException e) { + localNode.addError("Cannot use 'val' here because initializer expression does not have a representable type: " + e.getMessage()); + local.vartype = oldVarType; + } + } catch (RuntimeException e) { + local.vartype = oldVarType; + throw e; + } + } + // TODO search for val decls in either kind of for. + } +} -- cgit From f6b60b0cae7f8af2e4598f2bbbd72839e193a36b Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Wed, 3 Nov 2010 02:13:28 +0100 Subject: Intial support for @Log, for now only slf4j --- src/core/lombok/javac/handlers/HandleSlf4jLog.java | 114 +++++++++++++++++++++ .../lombok/javac/handlers/HandleSynchronized.java | 2 +- .../lombok/javac/handlers/JavacHandlerUtil.java | 15 ++- 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/core/lombok/javac/handlers/HandleSlf4jLog.java (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleSlf4jLog.java b/src/core/lombok/javac/handlers/HandleSlf4jLog.java new file mode 100644 index 00000000..01e0b69e --- /dev/null +++ b/src/core/lombok/javac/handlers/HandleSlf4jLog.java @@ -0,0 +1,114 @@ +/* + * Copyright © 2010 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 + * 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.JavacHandlerUtil.*; +import lombok.core.AnnotationValues; +import lombok.core.AST.Kind; +import lombok.javac.JavacAnnotationHandler; +import lombok.javac.JavacNode; +import lombok.slf4j.Log; + +import org.mangosdk.spi.ProviderFor; + +import com.sun.tools.javac.code.Flags; +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.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.util.List; + +/** + * Handles the {@code lombok.slf4j.Log} annotation for javac. + */ +@ProviderFor(JavacAnnotationHandler.class) +public class HandleSlf4jLog implements JavacAnnotationHandler { + @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + markAnnotationAsProcessed(annotationNode, Log.class); + + String loggingClassName = annotation.getRawExpression("value"); + if (loggingClassName == null) loggingClassName = "void.class"; + if (!loggingClassName.endsWith(".class")) loggingClassName = loggingClassName + ".class"; + + + JavacNode owner = annotationNode.up(); + switch (owner.getKind()) { + case TYPE: + if ((((JCClassDecl)owner.get()).mods.flags & Flags.INTERFACE)!= 0) { + annotationNode.addError("@Log is legal only on classes and enums."); + return true; + } + + if (loggingClassName.equals("void.class")) { + loggingClassName = getSelfName(owner); + } + return handleType(annotationNode, loggingClassName); + default: + annotationNode.addError("@Log is legal only on types."); + return true; + } + } + + private String getSelfName(JavacNode typeNode) { + String typeName = ((JCClassDecl) typeNode.get()).name.toString(); + JavacNode upType = typeNode.up(); + while (upType.getKind() == Kind.TYPE) { + typeName = ((JCClassDecl) upType.get()).name.toString() + "." + typeName; + upType = upType.up(); + } + + String packageDeclaration = typeNode.getPackageDeclaration(); + if (packageDeclaration != null) { + typeName = packageDeclaration + "." + typeName; + } + return typeName + ".class"; + } + + private boolean handleType(JavacNode annotation, String loggerClassName) { + JavacNode typeNode = annotation.up(); + + TreeMaker maker = typeNode.getTreeMaker(); + + switch (fieldExists("log", typeNode)) { + case NOT_EXISTS: + // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerLog4j.class); + JCExpression loggerType = chainDots(maker, typeNode, "org", "slf4j", "Logger"); + JCExpression factoryMethod = chainDots(maker, typeNode, "org", "slf4j", "LoggerFactory", "getLogger"); + + JCExpression loggerName = chainDots(maker, typeNode, loggerClassName.split("\\.")); + JCMethodInvocation factoryMethodCall = maker.Apply(List.nil(), factoryMethod, List.of(loggerName)); + + JCVariableDecl fieldDecl = maker.VarDef( + maker.Modifiers(Flags.PRIVATE | Flags.FINAL | Flags.STATIC), + typeNode.toName("log"), loggerType, factoryMethodCall); + + injectField(typeNode, fieldDecl); + return true; + case EXISTS_BY_USER: + annotation.addWarning("Field 'log' already exists."); + } + + return true; + } +} diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java index 2f900eb8..a095aaf1 100644 --- a/src/core/lombok/javac/handlers/HandleSynchronized.java +++ b/src/core/lombok/javac/handlers/HandleSynchronized.java @@ -89,7 +89,7 @@ public class HandleSynchronized implements JavacAnnotationHandler JCVariableDecl fieldDecl = maker.VarDef( maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (isStatic ? Flags.STATIC : 0)), methodNode.toName(lockName), objectType, newObjectArray); - injectField(methodNode.up(), fieldDecl); + injectFieldSuppressWarnings(methodNode.up(), fieldDecl); } if (method.body == null) return false; diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 79436327..3e734f8b 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -390,15 +390,28 @@ public class JavacHandlerUtil { return call; } + /** + * Adds the given new field declaration to the provided type AST Node. + * The field carries the @{@link SuppressWarnings}("all") annotation. + * Also takes care of updating the JavacAST. + */ + public static void injectFieldSuppressWarnings(JavacNode typeNode, JCVariableDecl field) { + injectField(typeNode, field, true); + } + /** * Adds the given new field declaration to the provided type AST Node. * * Also takes care of updating the JavacAST. */ public static void injectField(JavacNode typeNode, JCVariableDecl field) { + injectField(typeNode, field, false); + } + + private static void injectField(JavacNode typeNode, JCVariableDecl field, boolean addSuppressWarnings) { JCClassDecl type = (JCClassDecl) typeNode.get(); - addSuppressWarningsAll(field.mods, typeNode, field.pos); + if (addSuppressWarnings) addSuppressWarningsAll(field.mods, typeNode, field.pos); type.defs = type.defs.append(field); typeNode.add(field, Kind.FIELD).recursiveSetHandled(); -- cgit From c3eddf66cfb16d5d27c7a9562ea539344bfcb2d6 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Sat, 6 Nov 2010 13:30:22 +0100 Subject: Added support for Log4J, Commons and JUL in the javac handler --- src/core/lombok/javac/handlers/HandleLog.java | 236 +++++++++++++++++++++ src/core/lombok/javac/handlers/HandleSlf4jLog.java | 114 ---------- .../lombok/javac/handlers/JavacHandlerUtil.java | 15 ++ 3 files changed, 251 insertions(+), 114 deletions(-) create mode 100644 src/core/lombok/javac/handlers/HandleLog.java delete mode 100644 src/core/lombok/javac/handlers/HandleSlf4jLog.java (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java new file mode 100644 index 00000000..abeca18e --- /dev/null +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -0,0 +1,236 @@ +/* + * Copyright © 2010 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 + * 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.JavacHandlerUtil.*; + +import java.lang.annotation.Annotation; + +import lombok.core.AnnotationValues; +import lombok.core.AST.Kind; +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.TreeMaker; +import com.sun.tools.javac.tree.JCTree.JCAnnotation; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.util.List; + +public class HandleLog { + + private HandleLog() { + throw new UnsupportedOperationException(); + } + + public static boolean processAnnotation(LoggingFramework framework, AnnotationValues annotation, JavacNode annotationNode) { + markAnnotationAsProcessed(annotationNode, framework.getAnnotationClass()); + + String loggingClassName = annotation.getRawExpression("value"); + if (loggingClassName == null) loggingClassName = "void"; + if (loggingClassName.endsWith(".class")) loggingClassName = loggingClassName.substring(0, loggingClassName.length() - 6); + + 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; + } + + if (fieldExists("log", typeNode)!= MemberExistsResult.NOT_EXISTS) { + annotationNode.addWarning("Field 'log' already exists."); + return true; + } + + if (loggingClassName.equals("void")) { + loggingClassName = getSelfName(typeNode); + } + createField(typeNode, loggingClassName, framework); + return true; + default: + annotationNode.addError("@Log is legal only on types."); + return true; + } + } + + private static String getSelfName(JavacNode typeNode) { + String typeName = ((JCClassDecl) typeNode.get()).name.toString(); + JavacNode upType = typeNode.up(); + while (upType.getKind() == Kind.TYPE) { + typeName = ((JCClassDecl) upType.get()).name.toString() + "." + typeName; + upType = upType.up(); + } + + String packageDeclaration = typeNode.getPackageDeclaration(); + if (packageDeclaration != null) { + typeName = packageDeclaration + "." + typeName; + } + return typeName; + } + + private static boolean createField(JavacNode typeNode, String loggerClassName, LoggingFramework framework) { + TreeMaker maker = typeNode.getTreeMaker(); + + // private static final log = (); + JCExpression loggerType = chainDotsString(maker, typeNode, framework.getLoggerTypeName()); + JCExpression factoryMethod = chainDotsString(maker, typeNode, framework.getLoggerFactoryMethodName()); + + JCExpression loggerName = framework.createFactoryParameter(typeNode, loggerClassName); + JCMethodInvocation factoryMethodCall = maker.Apply(List.nil(), factoryMethod, List.of(loggerName)); + + JCVariableDecl fieldDecl = maker.VarDef( + maker.Modifiers(Flags.PRIVATE | Flags.FINAL | Flags.STATIC), + typeNode.toName("log"), loggerType, factoryMethodCall); + + injectField(typeNode, fieldDecl); + return true; + } + + static interface LoggingFramework { + Class getAnnotationClass(); + String getLoggerTypeName(); + String getLoggerFactoryMethodName(); + JCExpression createFactoryParameter(JavacNode typeNode, String typeName); + } + + // private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(TargetType.class); + private static LoggingFramework COMMONS = new LoggingFramework() { + @Override public Class getAnnotationClass() { + return lombok.jul.Log.class; + } + + @Override public String getLoggerTypeName() { + return "org.apache.commons.logging.Log"; + } + + @Override public String getLoggerFactoryMethodName() { + return "org.apache.commons.logging.LogFactory.getLog"; + } + + @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { + return chainDotsString(typeNode.getTreeMaker(), typeNode, typeName + ".class"); + } + }; + + /** + * Handles the {@link lombok.commons.Log} annotation for javac. + */ + @ProviderFor(JavacAnnotationHandler.class) + public static class HandleCommonsLog implements JavacAnnotationHandler { + @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + return processAnnotation(COMMONS, annotation, annotationNode); + } + } + + // private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger("TargetType"); + private static LoggingFramework JUL = new LoggingFramework() { + @Override public Class getAnnotationClass() { + return lombok.jul.Log.class; + } + + @Override public String getLoggerTypeName() { + return "java.util.logging.Logger"; + } + + @Override public String getLoggerFactoryMethodName() { + return "java.util.logging.Logger.getLogger"; + } + + @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { + return typeNode.getTreeMaker().Literal(typeName); + } + }; + + /** + * Handles the {@link lombok.jul.Log} annotation for javac. + */ + @ProviderFor(JavacAnnotationHandler.class) + public static class HandleJulLog implements JavacAnnotationHandler { + @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + return processAnnotation(JUL, annotation, annotationNode); + } + } + + // private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TargetType.class); + private static LoggingFramework LOG4J = new LoggingFramework() { + @Override public Class getAnnotationClass() { + return lombok.jul.Log.class; + } + + @Override public String getLoggerTypeName() { + return "org.apache.log4j.Logger"; + } + + @Override public String getLoggerFactoryMethodName() { + return "org.apache.log4j.Logger.getLogger"; + } + + @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { + return chainDotsString(typeNode.getTreeMaker(), typeNode, typeName + ".class"); + } + }; + + /** + * Handles the {@link lombok.log4j.Log} annotation for javac. + */ + @ProviderFor(JavacAnnotationHandler.class) + public static class HandleLog4jLog implements JavacAnnotationHandler { + @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + return processAnnotation(LOG4J, annotation, annotationNode); + } + } + + // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TargetType.class); + private static LoggingFramework SLF4J = new LoggingFramework() { + @Override public Class getAnnotationClass() { + return lombok.slf4j.Log.class; + } + + @Override public String getLoggerTypeName() { + return "org.slf4j.Logger"; + } + + @Override public String getLoggerFactoryMethodName() { + return "org.slf4j.LoggerFactory.getLogger"; + } + + @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { + return chainDotsString(typeNode.getTreeMaker(), typeNode, typeName + ".class"); + } + }; + + /** + * Handles the {@link lombok.slf4j.Log} annotation for javac. + */ + @ProviderFor(JavacAnnotationHandler.class) + public static class HandleSlf4jLog implements JavacAnnotationHandler { + @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + return processAnnotation(SLF4J, annotation, annotationNode); + } + } +} diff --git a/src/core/lombok/javac/handlers/HandleSlf4jLog.java b/src/core/lombok/javac/handlers/HandleSlf4jLog.java deleted file mode 100644 index 01e0b69e..00000000 --- a/src/core/lombok/javac/handlers/HandleSlf4jLog.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright © 2010 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 - * 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.JavacHandlerUtil.*; -import lombok.core.AnnotationValues; -import lombok.core.AST.Kind; -import lombok.javac.JavacAnnotationHandler; -import lombok.javac.JavacNode; -import lombok.slf4j.Log; - -import org.mangosdk.spi.ProviderFor; - -import com.sun.tools.javac.code.Flags; -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.JCExpression; -import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; -import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.util.List; - -/** - * Handles the {@code lombok.slf4j.Log} annotation for javac. - */ -@ProviderFor(JavacAnnotationHandler.class) -public class HandleSlf4jLog implements JavacAnnotationHandler { - @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { - markAnnotationAsProcessed(annotationNode, Log.class); - - String loggingClassName = annotation.getRawExpression("value"); - if (loggingClassName == null) loggingClassName = "void.class"; - if (!loggingClassName.endsWith(".class")) loggingClassName = loggingClassName + ".class"; - - - JavacNode owner = annotationNode.up(); - switch (owner.getKind()) { - case TYPE: - if ((((JCClassDecl)owner.get()).mods.flags & Flags.INTERFACE)!= 0) { - annotationNode.addError("@Log is legal only on classes and enums."); - return true; - } - - if (loggingClassName.equals("void.class")) { - loggingClassName = getSelfName(owner); - } - return handleType(annotationNode, loggingClassName); - default: - annotationNode.addError("@Log is legal only on types."); - return true; - } - } - - private String getSelfName(JavacNode typeNode) { - String typeName = ((JCClassDecl) typeNode.get()).name.toString(); - JavacNode upType = typeNode.up(); - while (upType.getKind() == Kind.TYPE) { - typeName = ((JCClassDecl) upType.get()).name.toString() + "." + typeName; - upType = upType.up(); - } - - String packageDeclaration = typeNode.getPackageDeclaration(); - if (packageDeclaration != null) { - typeName = packageDeclaration + "." + typeName; - } - return typeName + ".class"; - } - - private boolean handleType(JavacNode annotation, String loggerClassName) { - JavacNode typeNode = annotation.up(); - - TreeMaker maker = typeNode.getTreeMaker(); - - switch (fieldExists("log", typeNode)) { - case NOT_EXISTS: - // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerLog4j.class); - JCExpression loggerType = chainDots(maker, typeNode, "org", "slf4j", "Logger"); - JCExpression factoryMethod = chainDots(maker, typeNode, "org", "slf4j", "LoggerFactory", "getLogger"); - - JCExpression loggerName = chainDots(maker, typeNode, loggerClassName.split("\\.")); - JCMethodInvocation factoryMethodCall = maker.Apply(List.nil(), factoryMethod, List.of(loggerName)); - - JCVariableDecl fieldDecl = maker.VarDef( - maker.Modifiers(Flags.PRIVATE | Flags.FINAL | Flags.STATIC), - typeNode.toName("log"), loggerType, factoryMethodCall); - - injectField(typeNode, fieldDecl); - return true; - case EXISTS_BY_USER: - annotation.addWarning("Field 'log' already exists."); - } - - return true; - } -} diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 3e734f8b..5dacf2ca 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -489,6 +489,21 @@ public class JavacHandlerUtil { return e; } + + + /** + * In javac, dotted access of any kind, from {@code java.lang.String} to {@code var.methodName} + * is represented by a fold-left of {@code Select} nodes with the leftmost string represented by + * a {@code 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 + */ + public static JCExpression chainDotsString(TreeMaker maker, JavacNode node, String elems) { + return chainDots(maker, node, elems.split("\\.")); + } /** * Searches the given field node for annotations and returns each one that matches the provided regular expression pattern. -- cgit From f6bbebfbd200fab85a637e3b7939a9c1444332a3 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Sat, 6 Nov 2010 14:17:22 +0100 Subject: Use an annotation instead of implementations of interfaces --- src/core/lombok/javac/handlers/HandleLog.java | 135 ++++++++++---------------- 1 file changed, 49 insertions(+), 86 deletions(-) (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index abeca18e..652fbae0 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -111,126 +111,89 @@ public class HandleLog { return true; } - static interface LoggingFramework { - Class getAnnotationClass(); - String getLoggerTypeName(); - String getLoggerFactoryMethodName(); - JCExpression createFactoryParameter(JavacNode typeNode, String typeName); - } - - // private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(TargetType.class); - private static LoggingFramework COMMONS = new LoggingFramework() { - @Override public Class getAnnotationClass() { - return lombok.jul.Log.class; - } - - @Override public String getLoggerTypeName() { - return "org.apache.commons.logging.Log"; - } - - @Override public String getLoggerFactoryMethodName() { - return "org.apache.commons.logging.LogFactory.getLog"; - } - - @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { - return chainDotsString(typeNode.getTreeMaker(), typeNode, typeName + ".class"); - } - }; - /** * Handles the {@link lombok.commons.Log} annotation for javac. */ @ProviderFor(JavacAnnotationHandler.class) public static class HandleCommonsLog implements JavacAnnotationHandler { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { - return processAnnotation(COMMONS, annotation, annotationNode); + return processAnnotation(LoggingFramework.COMMONS, annotation, annotationNode); } } - // private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger("TargetType"); - private static LoggingFramework JUL = new LoggingFramework() { - @Override public Class getAnnotationClass() { - return lombok.jul.Log.class; - } - - @Override public String getLoggerTypeName() { - return "java.util.logging.Logger"; - } - - @Override public String getLoggerFactoryMethodName() { - return "java.util.logging.Logger.getLogger"; - } - - @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { - return typeNode.getTreeMaker().Literal(typeName); - } - }; - /** * Handles the {@link lombok.jul.Log} annotation for javac. */ @ProviderFor(JavacAnnotationHandler.class) public static class HandleJulLog implements JavacAnnotationHandler { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { - return processAnnotation(JUL, annotation, annotationNode); + return processAnnotation(LoggingFramework.JUL, annotation, annotationNode); } } - // private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TargetType.class); - private static LoggingFramework LOG4J = new LoggingFramework() { - @Override public Class getAnnotationClass() { - return lombok.jul.Log.class; - } - - @Override public String getLoggerTypeName() { - return "org.apache.log4j.Logger"; - } - - @Override public String getLoggerFactoryMethodName() { - return "org.apache.log4j.Logger.getLogger"; - } - - @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { - return chainDotsString(typeNode.getTreeMaker(), typeNode, typeName + ".class"); - } - }; - /** * Handles the {@link lombok.log4j.Log} annotation for javac. */ @ProviderFor(JavacAnnotationHandler.class) public static class HandleLog4jLog implements JavacAnnotationHandler { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { - return processAnnotation(LOG4J, annotation, annotationNode); + return processAnnotation(LoggingFramework.LOG4J, annotation, annotationNode); } } - // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TargetType.class); - private static LoggingFramework SLF4J = new LoggingFramework() { - @Override public Class getAnnotationClass() { - return lombok.slf4j.Log.class; + /** + * Handles the {@link lombok.slf4j.Log} annotation for javac. + */ + @ProviderFor(JavacAnnotationHandler.class) + public static class HandleSlf4jLog implements JavacAnnotationHandler { + @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + return processAnnotation(LoggingFramework.SLF4J, annotation, annotationNode); + } + } + + enum LoggingFramework { + // private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(TargetType.class); + COMMONS(lombok.jul.Log.class, "org.apache.commons.logging.Log", "org.apache.commons.logging.LogFactory.getLog"), + + // private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger("TargetType"); + JUL(lombok.jul.Log.class, "java.util.logging.Logger", "java.util.logging.Logger.getLogger") { + @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { + return typeNode.getTreeMaker().Literal(typeName); + } + }, + + // private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TargetType.class); + LOG4J(lombok.jul.Log.class, "org.apache.log4j.Logger", "org.apache.log4j.Logger.getLogger"), + + // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TargetType.class); + SLF4J(lombok.slf4j.Log.class, "org.slf4j.Logger", "org.slf4j.LoggerFactory.getLogger"), + + ; + + private final Class annotationClass; + private final String loggerTypeName; + private final String loggerFactoryName; + + LoggingFramework(Class annotationClass, String loggerTypeName, String loggerFactoryName) { + this.annotationClass = annotationClass; + this.loggerTypeName = loggerTypeName; + this.loggerFactoryName = loggerFactoryName; } - @Override public String getLoggerTypeName() { - return "org.slf4j.Logger"; + final Class getAnnotationClass() { + return annotationClass; } - @Override public String getLoggerFactoryMethodName() { - return "org.slf4j.LoggerFactory.getLogger"; + final String getLoggerTypeName() { + return loggerTypeName; } - @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { - return chainDotsString(typeNode.getTreeMaker(), typeNode, typeName + ".class"); + final String getLoggerFactoryMethodName() { + return loggerFactoryName; } - }; - - /** - * Handles the {@link lombok.slf4j.Log} annotation for javac. - */ - @ProviderFor(JavacAnnotationHandler.class) - public static class HandleSlf4jLog implements JavacAnnotationHandler { - @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { - return processAnnotation(SLF4J, annotation, annotationNode); + + JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { + return chainDotsString(typeNode.getTreeMaker(), typeNode, typeName + ".class"); } } } -- cgit From 66661b63c8becd7a9c1813815fdb09efefbf334a Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Sat, 6 Nov 2010 15:36:45 +0100 Subject: Reorder parameters --- src/core/lombok/javac/handlers/HandleLog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 652fbae0..52a308ab 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -70,7 +70,7 @@ public class HandleLog { if (loggingClassName.equals("void")) { loggingClassName = getSelfName(typeNode); } - createField(typeNode, loggingClassName, framework); + createField(framework, typeNode, loggingClassName); return true; default: annotationNode.addError("@Log is legal only on types."); @@ -93,7 +93,7 @@ public class HandleLog { return typeName; } - private static boolean createField(JavacNode typeNode, String loggerClassName, LoggingFramework framework) { + private static boolean createField(LoggingFramework framework, JavacNode typeNode, String loggerClassName) { TreeMaker maker = typeNode.getTreeMaker(); // private static final log = (); -- cgit From 59150328992339ec64ae015e2d1d73c109c4d322 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Sat, 6 Nov 2010 20:41:36 +0100 Subject: Have j.u.l. be invoked with TargetType.class.getName() instead of "TargetType" --- src/core/lombok/javac/handlers/HandleLog.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 52a308ab..014895a1 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -155,10 +155,13 @@ public class HandleLog { // private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(TargetType.class); COMMONS(lombok.jul.Log.class, "org.apache.commons.logging.Log", "org.apache.commons.logging.LogFactory.getLog"), - // private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger("TargetType"); + // private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(TargetType.class.getName()); JUL(lombok.jul.Log.class, "java.util.logging.Logger", "java.util.logging.Logger.getLogger") { @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { - return typeNode.getTreeMaker().Literal(typeName); + TreeMaker maker = typeNode.getTreeMaker(); + JCExpression classAccess = super.createFactoryParameter(typeNode, typeName); + JCExpression method = maker.Select(classAccess, typeNode.toName("getName")); + return maker.Apply(List.nil(), method, List.nil()); } }, -- cgit From 8e7334a50535ef33189c3e71fcab0d9e625c6534 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Sat, 6 Nov 2010 23:29:43 +0100 Subject: Updated documentation on @Log and moved them all to lombok.extern.* --- src/core/lombok/javac/handlers/HandleLog.java | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 014895a1..771f6a2b 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -112,51 +112,51 @@ public class HandleLog { } /** - * Handles the {@link lombok.commons.Log} annotation for javac. + * Handles the {@link lombok.extern.apachecommons.Log} annotation for javac. */ @ProviderFor(JavacAnnotationHandler.class) - public static class HandleCommonsLog implements JavacAnnotationHandler { - @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + public static class HandleCommonsLog implements JavacAnnotationHandler { + @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { return processAnnotation(LoggingFramework.COMMONS, annotation, annotationNode); } } /** - * Handles the {@link lombok.jul.Log} annotation for javac. + * Handles the {@link lombok.extern.jul.Log} annotation for javac. */ @ProviderFor(JavacAnnotationHandler.class) - public static class HandleJulLog implements JavacAnnotationHandler { - @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + public static class HandleJulLog implements JavacAnnotationHandler { + @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { return processAnnotation(LoggingFramework.JUL, annotation, annotationNode); } } /** - * Handles the {@link lombok.log4j.Log} annotation for javac. + * Handles the {@link lombok.extern.log4j.Log} annotation for javac. */ @ProviderFor(JavacAnnotationHandler.class) - public static class HandleLog4jLog implements JavacAnnotationHandler { - @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + public static class HandleLog4jLog implements JavacAnnotationHandler { + @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { return processAnnotation(LoggingFramework.LOG4J, annotation, annotationNode); } } /** - * Handles the {@link lombok.slf4j.Log} annotation for javac. + * Handles the {@link lombok.extern.slf4j.Log} annotation for javac. */ @ProviderFor(JavacAnnotationHandler.class) - public static class HandleSlf4jLog implements JavacAnnotationHandler { - @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + public static class HandleSlf4jLog implements JavacAnnotationHandler { + @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { return processAnnotation(LoggingFramework.SLF4J, annotation, annotationNode); } } enum LoggingFramework { // private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(TargetType.class); - COMMONS(lombok.jul.Log.class, "org.apache.commons.logging.Log", "org.apache.commons.logging.LogFactory.getLog"), + COMMONS(lombok.extern.jul.Log.class, "org.apache.commons.logging.Log", "org.apache.commons.logging.LogFactory.getLog"), // private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(TargetType.class.getName()); - JUL(lombok.jul.Log.class, "java.util.logging.Logger", "java.util.logging.Logger.getLogger") { + JUL(lombok.extern.jul.Log.class, "java.util.logging.Logger", "java.util.logging.Logger.getLogger") { @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { TreeMaker maker = typeNode.getTreeMaker(); JCExpression classAccess = super.createFactoryParameter(typeNode, typeName); @@ -166,10 +166,10 @@ public class HandleLog { }, // private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TargetType.class); - LOG4J(lombok.jul.Log.class, "org.apache.log4j.Logger", "org.apache.log4j.Logger.getLogger"), + LOG4J(lombok.extern.jul.Log.class, "org.apache.log4j.Logger", "org.apache.log4j.Logger.getLogger"), // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TargetType.class); - SLF4J(lombok.slf4j.Log.class, "org.slf4j.Logger", "org.slf4j.LoggerFactory.getLogger"), + SLF4J(lombok.extern.slf4j.Log.class, "org.slf4j.Logger", "org.slf4j.LoggerFactory.getLogger"), ; -- cgit From 1f0db1191a7fcc35aaeab1481a806201a450d797 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Sun, 7 Nov 2010 02:49:01 +0100 Subject: Use the actual annotation value to process the @Log annotations instead of their String representations. --- src/core/lombok/javac/handlers/HandleLog.java | 55 ++++++++++++++------------- 1 file changed, 28 insertions(+), 27 deletions(-) (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 771f6a2b..03e40d7f 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -26,9 +26,9 @@ import static lombok.javac.handlers.JavacHandlerUtil.*; import java.lang.annotation.Annotation; import lombok.core.AnnotationValues; -import lombok.core.AST.Kind; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult; import org.mangosdk.spi.ProviderFor; @@ -37,9 +37,11 @@ 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.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.Name; public class HandleLog { @@ -50,9 +52,18 @@ public class HandleLog { public static boolean processAnnotation(LoggingFramework framework, AnnotationValues annotation, JavacNode annotationNode) { markAnnotationAsProcessed(annotationNode, framework.getAnnotationClass()); - String loggingClassName = annotation.getRawExpression("value"); - if (loggingClassName == null) loggingClassName = "void"; - if (loggingClassName.endsWith(".class")) loggingClassName = loggingClassName.substring(0, loggingClassName.length() - 6); +// String loggingClassName = annotation.getRawExpression("value"); +// if (loggingClassName == null) loggingClassName = "void"; +// if (loggingClassName.endsWith(".class")) loggingClassName = loggingClassName.substring(0, loggingClassName.length() - 6); + + JCExpression annotationValue = (JCExpression) annotation.getActualExpression("value"); + JCFieldAccess loggingType = null; + if (annotationValue != null) { + if (!(annotationValue instanceof JCFieldAccess)) return true; + loggingType = (JCFieldAccess) annotationValue; + if (!loggingType.name.contentEquals("class")) return true; + } + JavacNode typeNode = annotationNode.up(); switch (typeNode.getKind()) { @@ -67,10 +78,10 @@ public class HandleLog { return true; } - if (loggingClassName.equals("void")) { - loggingClassName = getSelfName(typeNode); + if (loggingType == null) { + loggingType = selfType(typeNode); } - createField(framework, typeNode, loggingClassName); + createField(framework, typeNode, loggingType); return true; default: annotationNode.addError("@Log is legal only on types."); @@ -78,29 +89,20 @@ public class HandleLog { } } - private static String getSelfName(JavacNode typeNode) { - String typeName = ((JCClassDecl) typeNode.get()).name.toString(); - JavacNode upType = typeNode.up(); - while (upType.getKind() == Kind.TYPE) { - typeName = ((JCClassDecl) upType.get()).name.toString() + "." + typeName; - upType = upType.up(); - } - - String packageDeclaration = typeNode.getPackageDeclaration(); - if (packageDeclaration != null) { - typeName = packageDeclaration + "." + typeName; - } - return typeName; + private static JCFieldAccess selfType(JavacNode typeNode) { + TreeMaker maker = typeNode.getTreeMaker(); + Name name = ((JCClassDecl) typeNode.get()).name; + return maker.Select(maker.Ident(name), typeNode.toName("class")); } - private static boolean createField(LoggingFramework framework, JavacNode typeNode, String loggerClassName) { + private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType) { TreeMaker maker = typeNode.getTreeMaker(); // private static final log = (); JCExpression loggerType = chainDotsString(maker, typeNode, framework.getLoggerTypeName()); JCExpression factoryMethod = chainDotsString(maker, typeNode, framework.getLoggerFactoryMethodName()); - JCExpression loggerName = framework.createFactoryParameter(typeNode, loggerClassName); + JCExpression loggerName = framework.createFactoryParameter(typeNode, loggingType); JCMethodInvocation factoryMethodCall = maker.Apply(List.nil(), factoryMethod, List.of(loggerName)); JCVariableDecl fieldDecl = maker.VarDef( @@ -157,10 +159,9 @@ public class HandleLog { // private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(TargetType.class.getName()); JUL(lombok.extern.jul.Log.class, "java.util.logging.Logger", "java.util.logging.Logger.getLogger") { - @Override public JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { + @Override public JCExpression createFactoryParameter(JavacNode typeNode, JCFieldAccess loggingType) { TreeMaker maker = typeNode.getTreeMaker(); - JCExpression classAccess = super.createFactoryParameter(typeNode, typeName); - JCExpression method = maker.Select(classAccess, typeNode.toName("getName")); + JCExpression method = maker.Select(loggingType, typeNode.toName("getName")); return maker.Apply(List.nil(), method, List.nil()); } }, @@ -195,8 +196,8 @@ public class HandleLog { return loggerFactoryName; } - JCExpression createFactoryParameter(JavacNode typeNode, String typeName) { - return chainDotsString(typeNode.getTreeMaker(), typeNode, typeName + ".class"); + JCExpression createFactoryParameter(JavacNode typeNode, JCFieldAccess loggingType) { + return loggingType; } } } -- cgit From 6e5acaca49bff5af2b174078fb18b9015ae1bb71 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Mon, 8 Nov 2010 02:57:01 +0100 Subject: Added support for canEquals in javac --- .../javac/handlers/HandleEqualsAndHashCode.java | 85 ++++++++++++++++------ 1 file changed, 61 insertions(+), 24 deletions(-) (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index ee049f1f..b2d64f05 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -167,9 +167,13 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler fields, boolean callSuper, boolean useFieldsDirectly) { + private JCMethodDecl createEquals(JavacNode typeNode, List fields, boolean callSuper, boolean useFieldsDirectly, boolean needsCanEqual) { TreeMaker maker = typeNode.getTreeMaker(); JCClassDecl type = (JCClassDecl) typeNode.get(); @@ -335,27 +350,9 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler exprNil = List.nil(); - JCExpression oGetClass = maker.Apply(exprNil, maker.Select(maker.Ident(oName), getClass), exprNil); - JCExpression thisGetClass = maker.Apply(exprNil, maker.Select(maker.Ident(thisName), getClass), exprNil); - statements = statements.append( - maker.If(maker.Binary(JCTree.NE, oGetClass, thisGetClass), returnBool(maker, false), null)); - } - - /* if (!super.equals(o)) return false; */ - if (callSuper) { - JCMethodInvocation callToSuper = maker.Apply(List.nil(), - maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("equals")), - List.of(maker.Ident(oName))); - JCUnary superNotEqual = maker.Unary(JCTree.NOT, callToSuper); - statements = statements.append(maker.If(superNotEqual, returnBool(maker, false), null)); + /* if (!(o instanceof MyType) return false; */ { + JCUnary notInstanceOf = maker.Unary(JCTree.NOT, maker.TypeTest(maker.Ident(oName), maker.Ident(type.name))); + statements = statements.append(maker.If(notInstanceOf, returnBool(maker, false), null)); } /* MyType other = (MyType) o; */ { @@ -379,6 +376,25 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler exprNil = List.nil(); + JCExpression equalityCheck = maker.Apply(exprNil, + maker.Select(maker.Ident(otherName), typeNode.toName("canEqual")), + List.of(maker.Ident(thisName))); + statements = statements.append(maker.If(maker.Unary(JCTree.NOT, equalityCheck), returnBool(maker, false), null)); + } + } + + /* if (!super.equals(o)) return false; */ + if (callSuper) { + JCMethodInvocation callToSuper = maker.Apply(List.nil(), + maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("equals")), + List.of(maker.Ident(oName))); + JCUnary superNotEqual = maker.Unary(JCTree.NOT, callToSuper); + statements = statements.append(maker.If(superNotEqual, returnBool(maker, false), null)); + } + for (JavacNode fieldNode : fields) { JCExpression fType = getFieldType(fieldNode, useFieldsDirectly); JCExpression thisFieldAccessor = createFieldAccessor(maker, fieldNode, useFieldsDirectly); @@ -428,6 +444,27 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandlernil(), params, List.nil(), body, null); } + + private JCMethodDecl createCanEqual(JavacNode typeNode) { + /* public boolean canEquals(final java.lang.Object other) { + * return other instanceof MyType; + * } + */ + TreeMaker maker = typeNode.getTreeMaker(); + JCClassDecl type = (JCClassDecl) typeNode.get(); + + JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.nil()); + JCExpression returnType = maker.TypeIdent(TypeTags.BOOLEAN); + Name canEqualName = typeNode.toName("canEqual"); + JCExpression objectType = chainDots(maker, typeNode, "java", "lang", "Object"); + Name otherName = typeNode.toName("other"); + List params = List.of(maker.VarDef(maker.Modifiers(Flags.FINAL), otherName, objectType, null)); + + JCBlock body = maker.Block(0, List.of( + maker.Return(maker.TypeTest(maker.Ident(otherName), maker.Ident(type.name))))); + + return maker.MethodDef(mods, canEqualName, returnType, List.nil(), params, List.nil(), body, null); + } private JCStatement generateCompareFloatOrDouble(JCExpression thisDotField, JCExpression otherDotField, TreeMaker maker, JavacNode node, boolean isDouble) { -- cgit From 09cebbdc59c118bb31f7e2fdf328ed60a03385c7 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 8 Nov 2010 15:30:51 +0100 Subject: 'val' in javac now errors out with an appropriate message on val x = { .. }, and arrays no longer cause "Symbol not found: Array" errors. --- src/core/lombok/javac/handlers/HandleVal.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index a6f22093..f806ae6c 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -33,6 +33,7 @@ import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCNewArray; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; @ProviderFor(JavacASTVisitor.class) @@ -57,6 +58,11 @@ public class HandleVal extends JavacASTAdapter { return; } + if (local.init instanceof JCNewArray && ((JCNewArray)local.init).elemtype == null) { + localNode.addError("'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })"); + return; + } + local.mods.flags |= Flags.FINAL; JCExpression oldVarType = local.vartype; local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst()); -- cgit From 3855a2171bbcb1c256f67ddd815526797364219c Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 8 Nov 2010 16:01:19 +0100 Subject: Delombok on files with only 'val' in them, without --force, didn't do anything. Fixed. --- src/core/lombok/javac/handlers/HandleVal.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index f806ae6c..7161a7c3 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -94,7 +94,10 @@ public class HandleVal extends JavacASTAdapter { // TODO: Fix enhanced for loops - then uncomment a bunch of lines in test/transform/resource/*/ValInFor.java } replacement = JavacResolution.typeToJCTree(type, localNode.getTreeMaker(), localNode.getAst()); - if (replacement != null) local.vartype = replacement; + if (replacement != null) { + local.vartype = replacement; + localNode.getAst().setChanged(); + } else local.vartype = oldVarType; } catch (JavacResolution.TypeNotConvertibleException e) { localNode.addError("Cannot use 'val' here because initializer expression does not have a representable type: " + e.getMessage()); -- cgit From dee834a39780f61a0357c42f61592cd3c3598bd3 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Mon, 8 Nov 2010 22:00:06 +0100 Subject: Added support for canEqual in ecj --- src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core/lombok/javac/handlers') diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index b2d64f05..c5475fb1 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -479,5 +479,4 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler Date: M