diff options
-rw-r--r-- | doc/changelog.markdown | 2 | ||||
-rw-r--r-- | src/core/lombok/ConfigurationKeys.java | 25 | ||||
-rw-r--r-- | src/core/lombok/CustomLog.java | 11 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/ConfigurationDataType.java | 10 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/ConfigurationValueType.java | 3 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/IdentifierName.java | 11 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/LogDeclaration.java | 28 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/TypeName.java | 11 | ||||
-rw-r--r-- | src/core/lombok/core/handlers/LoggingFramework.java | 23 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleLog.java | 28 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleSynchronized.java | 2 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleLog.java | 18 | ||||
-rw-r--r-- | website/templates/features/log.html | 45 |
13 files changed, 127 insertions, 90 deletions
diff --git a/doc/changelog.markdown b/doc/changelog.markdown index e0e3d49a..a1bbd8ab 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -2,7 +2,7 @@ Lombok Changelog ---------------- ### v1.18.9 "Edgy Guinea Pig" -* Nothing yet. +* FEATURE: You can now configure a custom logger framework using the new `@CustomLog` annotation in combination with the `lombok.log.custom.declaration` configuration key. See the [log documentation](https://projectlombok.org/features/Log) for more information. [Pullrequest #2086](https://github.com/rzwitserloot/lombok/pull/2086) with thanks to Adam Juraszek. ### v1.18.8 (May 7th, 2019) * FEATURE: You can now configure `@FieldNameConstants` to `CONSTANT_CASE` the generated constants, using a `lombok.config` option. See the [FieldNameConstants documentation](https://projectlombok.org/features/experimental/FieldNameConstants). [Issue #2092](https://github.com/rzwitserloot/lombok/issues/2092). diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 951b2893..ecfddb2a 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -304,17 +304,16 @@ public class ConfigurationKeys { // ----- NonNull ----- /** - * lombok configuration: {@code lombok.nonNull.exceptionType} = <String: <em>a java exception type</em>; either [{@code IllegalArgumentException} or: {@code NullPointerException}]. + * lombok configuration: {@code lombok.nonNull.exceptionType} = one of: [{@code IllegalArgumentException}, {@code NullPointerException}, or {@code Assertion}]. * - * Sets the exception to throw if {@code @NonNull} is applied to a method parameter, and a caller passes in {@code null}. + * Sets the exception to throw if {@code @NonNull} is applied to a method parameter, and a caller passes in {@code null}. If the chosen configuration is {@code Assertion}, an assertion is generated instead, + * which would mean your code throws an {@code AssertionError} if assertions are enabled, and does nothing if assertions are not enabled. */ public static final ConfigurationKey<NullCheckExceptionType> NON_NULL_EXCEPTION_TYPE = new ConfigurationKey<NullCheckExceptionType>("lombok.nonNull.exceptionType", "The type of the exception to throw if a passed-in argument is null (Default: NullPointerException).") {}; /** * lombok configuration: {@code lombok.nonNull.flagUsage} = {@code WARNING} | {@code ERROR}. * - * <em>Implementation note: This field is supposed to be lombok.NonNull itself, but jdk6 and 7 have bugs where fields in annotations don't work well.</em> - * * If set, <em>any</em> usage of {@code @NonNull} results in a warning / error. */ public static final ConfigurationKey<FlagUsageType> NON_NULL_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.nonNull.flagUsage", "Emit a warning or error if @NonNull is used.") {}; @@ -439,7 +438,7 @@ public class ConfigurationKeys { public static final ConfigurationKey<FlagUsageType> LOG_CUSTOM_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.custom.flagUsage", "Emit a warning or error if @CustomLog is used.") {}; /** - * lombok configuration: {@code lombok.log.custom.declaration} = <String: logDeclaration>. + * lombok configuration: {@code lombok.log.custom.declaration} = <logDeclaration string>. * * The log declaration must follow the pattern: * <br> @@ -447,15 +446,19 @@ public class ConfigurationKeys { * <br> * It consists of: * <ul> - * <li>Optional fully qualified logger type, e.g. {@code my.cool.Logger}, followed by space. If not specified, it defaults to the logger factory type. + * <li>Optional fully qualified logger type, e.g. {@code my.cool.Logger}, followed by space. If not specified, it defaults to the <em>LoggerFactoryType</em>. * <li>Fully qualified logger factory type, e.g. {@code my.cool.LoggerFactory}, followed by dot. - * <li>Factory method, e.g. {@code createLogger}. The method must be defined on the logger factory type and must be static. - * <li>At least one definition of factory method parameters, e.g. {@code ()} or {@code (TOPIC,TYPE)}. The format is comma-separated list of parameters wrapped in parentheses. - * The allowed parameters are: {@code TYPE} | {@code NAME} | {@code TOPIC} | {@code NULL}. - * There can be at most one parameter definition with {@code TOPIC} and at most one without {@code TOPIC}. + * <li>Factory method, e.g. {@code createLogger}. This must be a {@code public static} method in the <em>LoggerFactoryType</em>. + * <li>At least one definition of factory method parameters, e.g. {@code ()} or {@code (TOPIC,TYPE)}. The format inside the parentheses is a comma-separated list of parameter kinds.<br> + * The allowed parameters are: {@code TYPE} | {@code NAME} | {@code TOPIC} | {@code NULL}.<br> + * There can be at most one parameter definition with {@code TOPIC} and at most one without {@code TOPIC}. You can specify both. * </ul> * - * If not set, any usage of {@code @CustomLog} will result in an error. + * An example: {@code my.cool.Logger my.cool.LoggerFactory.createLogger(TYPE)(TYPE,TOPIC)}<br> + * If no topic is provided in the usage of {@code @CustomLog}, the above will invoke {@code LoggerFactory}'s {@code createLogger} method, passing in the type as a {@code java.lang.Class} variable.<br> + * If a topic is provided, the overload of that method is invoked with 2 parameters: First the type (as {@code Class}), then the topic (as {@code String}). + * <p> + * If this configuration key is not set, any usage of {@code @CustomLog} will result in an error. */ public static final ConfigurationKey<LogDeclaration> LOG_CUSTOM_DECLARATION = new ConfigurationKey<LogDeclaration>("lombok.log.custom.declaration", "Define the generated custom logger field.") {}; diff --git a/src/core/lombok/CustomLog.java b/src/core/lombok/CustomLog.java index 48c9f2ab..d1f45f7c 100644 --- a/src/core/lombok/CustomLog.java +++ b/src/core/lombok/CustomLog.java @@ -27,7 +27,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Causes lombok to generate a logger field. + * Causes lombok to generate a logger field based on a custom logger implementation. * <p> * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>. * <p> @@ -50,7 +50,7 @@ import java.lang.annotation.Target; * } * </pre> * <p> - * Configuration must be provided in lombok.config, otherwise any usage will lead to errors. + * Configuration must be provided in lombok.config, otherwise any usage of this annotation will result in a compile-time error. * * This annotation is valid for classes and enumerations.<br> * @see lombok.extern.java.Log @Log @@ -65,6 +65,11 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface CustomLog { - /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */ + /** + * + * Sets a custom topic/category. Note that this requires you to specify a parameter configuration for your custom logger that includes {@code TOPIC}. + * + * @return The topic/category of the constructed Logger. By default (or for the empty string as topic), the parameter configuration without {@code TOPIC} is invoked. + */ String topic() default ""; } diff --git a/src/core/lombok/core/configuration/ConfigurationDataType.java b/src/core/lombok/core/configuration/ConfigurationDataType.java index 7dc77301..50b47a2e 100644 --- a/src/core/lombok/core/configuration/ConfigurationDataType.java +++ b/src/core/lombok/core/configuration/ConfigurationDataType.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 The Project Lombok Authors. + * Copyright (C) 2013-2019 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -143,16 +143,16 @@ public final class ConfigurationDataType { @Override public Object parse(String value) { return invokeStaticMethod(valueOfMethod, value); } - + @Override public String description() { return invokeStaticMethod(descriptionMethod); } - + @Override public String exampleValue() { return invokeStaticMethod(exampleValueMethod); } - @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") private <R> R invokeStaticMethod(Method method, Object... arguments) { try { return (R) method.invoke(null, arguments); @@ -237,7 +237,7 @@ public final class ConfigurationDataType { try { return argumentType.getMethod(name, parameterTypes); } catch (NoSuchMethodException e) { - throw new IllegalStateException("Method " + name + " with parameters " + Arrays.toString(parameterTypes) + "was not found.", e); + throw new IllegalStateException("Method " + name + " with parameters " + Arrays.toString(parameterTypes) + " was not found.", e); } catch (SecurityException e) { throw new IllegalStateException("Cannot inspect methods of type " + argumentType, e); } diff --git a/src/core/lombok/core/configuration/ConfigurationValueType.java b/src/core/lombok/core/configuration/ConfigurationValueType.java index f287f62a..a44a5a83 100644 --- a/src/core/lombok/core/configuration/ConfigurationValueType.java +++ b/src/core/lombok/core/configuration/ConfigurationValueType.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Project Lombok Authors. + * Copyright (C) 2019 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +29,7 @@ package lombok.core.configuration; * <li><code>public static String description()</code> * <li><code>public static String exampleValue()</code> * </ul> + * None of them should throw checked exceptions. * Based on these methods, an instance of {@link ConfigurationValueParser} is created * and used by the configuration system. */ diff --git a/src/core/lombok/core/configuration/IdentifierName.java b/src/core/lombok/core/configuration/IdentifierName.java index 52e51bd7..db83c2cc 100644 --- a/src/core/lombok/core/configuration/IdentifierName.java +++ b/src/core/lombok/core/configuration/IdentifierName.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Project Lombok Authors. + * Copyright (C) 2019 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,13 +31,10 @@ public final class IdentifierName implements ConfigurationValueType { } public static IdentifierName valueOf(String name) { - if (name == null || name.trim().isEmpty()) { - return null; - } + if (name == null || name.trim().isEmpty()) return null; + String trimmedName = name.trim(); - if (!JavaIdentifiers.isValidJavaIdentifier(trimmedName)) { - throw new IllegalArgumentException("Invalid identifier " + trimmedName); - } + if (!JavaIdentifiers.isValidJavaIdentifier(trimmedName)) throw new IllegalArgumentException("Invalid identifier " + trimmedName); return new IdentifierName(trimmedName); } diff --git a/src/core/lombok/core/configuration/LogDeclaration.java b/src/core/lombok/core/configuration/LogDeclaration.java index 36f280e2..ad4102d4 100644 --- a/src/core/lombok/core/configuration/LogDeclaration.java +++ b/src/core/lombok/core/configuration/LogDeclaration.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Project Lombok Authors. + * Copyright (C) 2019 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -49,14 +49,11 @@ public final class LogDeclaration implements ConfigurationValueType { } public static LogDeclaration valueOf(String declaration) { - if (declaration == null) { - return null; - } + if (declaration == null) return null; Matcher matcher = DECLARATION_PATTERN.matcher(declaration); - if (!matcher.matches()) { - throw new IllegalArgumentException("The declaration must follow the pattern: [LoggerType ]LoggerFactoryType.loggerFactoryMethod(loggerFactoryMethodParams)[(loggerFactoryMethodParams)]"); - } + if (!matcher.matches()) throw new IllegalArgumentException("The declaration must follow the pattern: [LoggerType ]LoggerFactoryType.loggerFactoryMethod(loggerFactoryMethodParams)[(loggerFactoryMethodParams)]"); + TypeName loggerFactoryType = TypeName.valueOf(matcher.group(2)); TypeName loggerType = TypeName.valueOf(matcher.group(1)); if (loggerType == null) loggerType = loggerFactoryType; @@ -67,21 +64,16 @@ public final class LogDeclaration implements ConfigurationValueType { List<LogFactoryParameter> parametersWithTopic = null; for (List<LogFactoryParameter> parameters: allParameters) { if (parameters.contains(LogFactoryParameter.TOPIC)) { - if (parametersWithTopic != null) { - throw new IllegalArgumentException("There are too many parameters with TOPIC: " + parametersWithTopic + " and " + parameters); - } + if (parametersWithTopic != null) throw new IllegalArgumentException("There is more than one parameter definition that includes TOPIC: " + parametersWithTopic + " and " + parameters); parametersWithTopic = parameters; } else { - if (parametersWithoutTopic != null) { - throw new IllegalArgumentException("There are too many parameters without TOPIC: " + parametersWithoutTopic + " and " + parameters); - } + if (parametersWithoutTopic != null) throw new IllegalArgumentException("There is more than one parmaeter definition that does not include TOPIC: " + parametersWithoutTopic + " and " + parameters); parametersWithoutTopic = parameters; } } - if (parametersWithoutTopic == null && parametersWithTopic == null) { - // shouldn't happen the pattern does not allow it - throw new IllegalArgumentException("No logger factory method parameters specified."); - } + + // sanity check (the pattern should disallow this situation + if (parametersWithoutTopic == null && parametersWithTopic == null) throw new IllegalArgumentException("No logger factory method parameters specified."); return new LogDeclaration(loggerType, loggerFactoryType, loggerFactoryMethod, parametersWithoutTopic, parametersWithTopic); } @@ -103,7 +95,7 @@ public final class LogDeclaration implements ConfigurationValueType { } public static String description() { - return "custom-log-declartation"; + return "custom-log-declaration"; } public static String exampleValue() { diff --git a/src/core/lombok/core/configuration/TypeName.java b/src/core/lombok/core/configuration/TypeName.java index a3128527..4ac072dc 100644 --- a/src/core/lombok/core/configuration/TypeName.java +++ b/src/core/lombok/core/configuration/TypeName.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Project Lombok Authors. + * Copyright (C) 2013-2019 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,14 +31,11 @@ public final class TypeName implements ConfigurationValueType { } public static TypeName valueOf(String name) { - if (name == null || name.trim().isEmpty()) { - return null; - } + if (name == null || name.trim().isEmpty()) return null; + String trimmedName = name.trim(); for (String identifier : trimmedName.split(".")) { - if (!JavaIdentifiers.isValidJavaIdentifier(identifier)) { - throw new IllegalArgumentException("Invalid type name " + trimmedName + " (part " + identifier + ")"); - } + if (!JavaIdentifiers.isValidJavaIdentifier(identifier)) throw new IllegalArgumentException("Invalid type name " + trimmedName + " (part " + identifier + ")"); } return new TypeName(trimmedName); } diff --git a/src/core/lombok/core/handlers/LoggingFramework.java b/src/core/lombok/core/handlers/LoggingFramework.java index 38eadd17..88c0317b 100644 --- a/src/core/lombok/core/handlers/LoggingFramework.java +++ b/src/core/lombok/core/handlers/LoggingFramework.java @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2019 The Project Lombok Authors. + * + * 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.core.handlers; import java.lang.annotation.Annotation; @@ -56,7 +77,7 @@ public class LoggingFramework { private final Class<? extends Annotation> annotationClass; private final String annotationAsString; private final LogDeclaration declaration; - + public LoggingFramework(Class<? extends Annotation> annotationClass, LogDeclaration declaration) { this.annotationClass = annotationClass; this.annotationAsString = "@" + annotationClass.getSimpleName(); diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java index e445685d..3dc9536d 100644 --- a/src/core/lombok/eclipse/handlers/HandleLog.java +++ b/src/core/lombok/eclipse/handlers/HandleLog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2014 The Project Lombok Authors. + * Copyright (C) 2010-2019 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -51,7 +51,6 @@ import lombok.core.configuration.LogDeclaration.LogFactoryParameter; import lombok.core.handlers.LoggingFramework; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; -import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult; public class HandleLog { private static final IdentifierName LOG = IdentifierName.valueOf("log"); @@ -74,8 +73,7 @@ public class HandleLog { if (owner.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) owner.get(); int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - boolean notAClass = (modifiers & - (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0; + boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0; if (typeDecl == null || notAClass) { annotationNode.addError(framework.getAnnotationAsString() + " is legal only on classes and enums."); @@ -89,13 +87,13 @@ public class HandleLog { if (loggerTopic != null && loggerTopic.trim().isEmpty()) loggerTopic = null; if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) { - annotationNode.addError(framework.getAnnotationAsString() + " does not allow to set a topic."); + annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic."); } ClassLiteralAccess loggingType = selfType(owner, source); FieldDeclaration fieldDeclaration = createField(framework, source, loggingType, logFieldName.getName(), useStatic, loggerTopic); fieldDeclaration.traverse(new SetGeneratedByVisitor(source), typeDecl.staticInitializerScope); - // TODO temporary workaround for issue 217. http://code.google.com/p/projectlombok/issues/detail?id=217 + // TODO temporary workaround for issue 290. https://github.com/rzwitserloot/lombok/issues/290 // injectFieldSuppressWarnings(owner, fieldDeclaration); injectField(owner, fieldDeclaration); owner.rebuild(); @@ -107,12 +105,12 @@ public class HandleLog { public static ClassLiteralAccess selfType(EclipseNode type, Annotation source) { int pS = source.sourceStart, pE = source.sourceEnd; - long p = (long)pS << 32 | pE; - + long p = (long) pS << 32 | pE; + TypeDeclaration typeDeclaration = (TypeDeclaration)type.get(); TypeReference typeReference = new SingleTypeReference(typeDeclaration.name, p); setGeneratedBy(typeReference, source); - + ClassLiteralAccess result = new ClassLiteralAccess(source.sourceEnd, typeReference); setGeneratedBy(result, source); @@ -123,7 +121,7 @@ public class HandleLog { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; - // private static final <loggerType> log = <factoryMethod>(<parameter>); + // private static final <loggerType> log = <factoryMethod>(<parameter>); FieldDeclaration fieldDecl = new FieldDeclaration(logFieldName.toCharArray(), 0, -1); setGeneratedBy(fieldDecl, source); fieldDecl.declarationSourceEnd = -1; @@ -134,7 +132,7 @@ public class HandleLog { MessageSend factoryMethodCall = new MessageSend(); setGeneratedBy(factoryMethodCall, source); - + factoryMethodCall.receiver = createNameReference(logDeclaration.getLoggerFactoryType().getName(), source); factoryMethodCall.selector = logDeclaration.getLoggerFactoryMethod().getCharArray(); @@ -151,7 +149,7 @@ public class HandleLog { public static TypeReference createTypeReference(String typeName, Annotation source) { int pS = source.sourceStart, pE = source.sourceEnd; - long p = (long)pS << 32 | pE; + long p = (long) pS << 32 | pE; char[][] typeNameTokens = fromQualifiedName(typeName); long[] pos = new long[typeNameTokens.length]; @@ -161,7 +159,7 @@ public class HandleLog { setGeneratedBy(typeReference, source); return typeReference; } - + private static final Expression[] createFactoryParameters(ClassLiteralAccess loggingType, Annotation source, List<LogFactoryParameter> parameters, String loggerTopic) { Expression[] expressions = new Expression[parameters.size()]; int pS = source.sourceStart, pE = source.sourceEnd; @@ -174,7 +172,7 @@ public class HandleLog { expressions[i] = createFactoryTypeParameter(loggingType, source); break; case NAME: - long p = (long)pS << 32 | pE; + long p = (long) pS << 32 | pE; MessageSend factoryParameterCall = new MessageSend(); setGeneratedBy(factoryParameterCall, source); @@ -306,7 +304,7 @@ public class HandleLog { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_CUSTOM_FLAG_USAGE, "@CustomLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); LogDeclaration logDeclaration = annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_CUSTOM_DECLARATION); if (logDeclaration == null) { - annotationNode.addError("The @CustomLog is not configured; please set log.custom.declaration in lombok.config."); + annotationNode.addError("The @CustomLog annotation is not configured; please set log.custom.declaration in lombok.config."); return; } LoggingFramework framework = new LoggingFramework(lombok.CustomLog.class, logDeclaration); diff --git a/src/core/lombok/eclipse/handlers/HandleSynchronized.java b/src/core/lombok/eclipse/handlers/HandleSynchronized.java index a45a499c..22f7f967 100644 --- a/src/core/lombok/eclipse/handlers/HandleSynchronized.java +++ b/src/core/lombok/eclipse/handlers/HandleSynchronized.java @@ -98,7 +98,7 @@ public class HandleSynchronized extends EclipseAnnotationHandler<Synchronized> { fieldDecl.type = new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] { 0, 0, 0 }); setGeneratedBy(fieldDecl.type, source); fieldDecl.initialization = arrayAlloc; - // TODO temporary workaround for issue 217. http://code.google.com/p/projectlombok/issues/detail?id=217 + // TODO temporary workaround for issue 290. https://github.com/rzwitserloot/lombok/issues/290 // injectFieldSuppressWarnings(annotationNode.up().up(), fieldDecl); injectField(annotationNode.up().up(), fieldDecl); } diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index a00cc496..5f0f8c90 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2014 The Project Lombok Authors. + * Copyright (C) 2010-2019 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -51,14 +51,14 @@ import com.sun.tools.javac.util.Name; public class HandleLog { private static final IdentifierName LOG = IdentifierName.valueOf("log"); - + private HandleLog() { throw new UnsupportedOperationException(); } - + public static void processAnnotation(LoggingFramework framework, AnnotationValues<?> annotation, JavacNode annotationNode, String loggerTopic) { deleteAnnotationIfNeccessary(annotationNode, framework.getAnnotationClass()); - + JavacNode typeNode = annotationNode.up(); switch (typeNode.getKind()) { case TYPE: @@ -67,7 +67,7 @@ public class HandleLog { boolean useStatic = !Boolean.FALSE.equals(annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_IS_STATIC)); - if ((((JCClassDecl)typeNode.get()).mods.flags & Flags.INTERFACE) != 0) { + if ((((JCClassDecl) typeNode.get()).mods.flags & Flags.INTERFACE) != 0) { annotationNode.addError(framework.getAnnotationAsString() + " is legal only on classes and enums."); return; } @@ -78,9 +78,9 @@ public class HandleLog { if (loggerTopic != null && loggerTopic.trim().isEmpty()) loggerTopic = null; if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) { - annotationNode.addError(framework.getAnnotationAsString() + " does not allow to set a topic."); + annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic."); } - + JCFieldAccess loggingType = selfType(typeNode); createField(framework, typeNode, loggingType, annotationNode.get(), logFieldName.getName(), useStatic, loggerTopic); break; @@ -109,8 +109,8 @@ public class HandleLog { JCMethodInvocation factoryMethodCall = maker.Apply(List.<JCExpression>nil(), factoryMethod, List.<JCExpression>from(factoryParameters)); JCVariableDecl fieldDecl = recursiveSetGeneratedBy(maker.VarDef( - maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (useStatic ? Flags.STATIC : 0)), - typeNode.toName(logFieldName), loggerType, factoryMethodCall), source, typeNode.getContext()); + maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (useStatic ? Flags.STATIC : 0)), + typeNode.toName(logFieldName), loggerType, factoryMethodCall), source, typeNode.getContext()); injectFieldAndMarkGenerated(typeNode, fieldDecl); return true; diff --git a/website/templates/features/log.html b/website/templates/features/log.html index 1de26836..2547af14 100644 --- a/website/templates/features/log.html +++ b/website/templates/features/log.html @@ -7,52 +7,67 @@ <em>NEW in lombok 0.10: </em>You can annotate any class with a log annotation to let lombok generate a logger field.<br/> The logger is named <code>log</code> and the field's type depends on which logger you have selected. </p><p> - <em>NEW in lombok v1.16.24: </em>Addition of google's FluentLogger (flogger). + <em>NEW in lombok v1.16.24: </em>Addition of google's FluentLogger (via <a href="#Flogger"><code>@Flogger</code></a>). + </p><p> + <em>NEW in lombok v1.18.10: </em>Addition of <a href="#CustomLog"><code>@CustomLog</code></a> which lets you add any logger by configuring how to create them with a config key. </p> </@f.history> <@f.overview> <p> - You put the variant of <code>@Log</code> on your class (whichever one applies to the logging system you use); you then have a static final <code>log</code> field, initialized to the name of your class, which you can then use to write log statements. + You put the variant of <code>@Log</code> on your class (whichever one applies to the logging system you use); you then have a static final <code>log</code> field, initialized as is the commonly proscribed way for the logging framework you use, which you can then use to write log statements. </p><p> There are several choices available:<br /> <dl> - <dt> + <dt id="CommonsLog"> <code>@CommonsLog</code> </dt><dd> Creates <code><span class="keyword">private static final </span><a href="https://commons.apache.org/logging/apidocs/org/apache/commons/logging/Log.html">org.apache.commons.logging.Log</a> <span class="staticfield">log</span> = <a href="https://commons.apache.org/logging/apidocs/org/apache/commons/logging/LogFactory.html#getLog(java.lang.Class)">org.apache.commons.logging.LogFactory.getLog</a>(LogExample.<span class="keyword">class</span>);</code> - </dd><dt> + </dd><dt id="Flogger"> <code>@Flogger</code> </dt><dd> Creates <code><span class="keyword">private static final </span><a href="https://google.github.io/flogger/">com.google.common.flogger.FluentLogger</a> <span class="staticfield">log</span> = com.google.common.flogger.FluentLogger.forEnclosingClass();</code> - </dd><dt> + </dd><dt id="JBossLog"> <code>@JBossLog</code> </dt><dd> Creates <code><span class="keyword">private static final </span><a href="https://docs.jboss.org/jbosslogging/latest/org/jboss/logging/Logger.html">org.jboss.logging.Logger</a> <span class="staticfield">log</span> = <a href="https://docs.jboss.org/jbosslogging/latest/org/jboss/logging/Logger.html#getLogger(java.lang.Class)">org.jboss.logging.Logger.getLogger</a>(LogExample.<span class="keyword">class</span>);</code> - </dd><dt> + </dd><dt id="javaLog"> <code>@Log</code> </dt><dd> Creates <code><span class="keyword">private static final </span><a href="https://docs.oracle.com/javase/6/docs/api/java/util/logging/Logger.html">java.util.logging.Logger</a> <span class="staticfield">log</span> = <a href="https://docs.oracle.com/javase/6/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)">java.util.logging.Logger.getLogger</a>(LogExample.<span class="keyword">class</span>.getName());</code> - </dd><dt> + </dd><dt id="Log4j"> <code>@Log4j</code> </dt><dd> Creates <code><span class="keyword">private static final </span><a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html">org.apache.log4j.Logger</a> <span class="staticfield">log</span> = <a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html#getLogger(java.lang.Class)">org.apache.log4j.Logger.getLogger</a>(LogExample.<span class="keyword">class</span>);</code> - </dd><dt> + </dd><dt id="Log4j2"> <code>@Log4j2</code> </dt><dd> Creates <code><span class="keyword">private static final </span><a href="https://logging.apache.org/log4j/2.0/log4j-api/apidocs/org/apache/logging/log4j/Logger.html">org.apache.logging.log4j.Logger</a> <span class="staticfield">log</span> = <a href="https://logging.apache.org/log4j/2.0/log4j-api/apidocs/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.Class)">org.apache.logging.log4j.LogManager.getLogger</a>(LogExample.<span class="keyword">class</span>);</code> - </dd><dt> + </dd><dt id="Slf4j"> <code>@Slf4j</code> </dt><dd> Creates <code><span class="keyword">private static final </span><a href="https://www.slf4j.org/api/org/slf4j/Logger.html">org.slf4j.Logger</a> <span class="staticfield">log</span> = <a href="https://www.slf4j.org/api/org/slf4j/LoggerFactory.html#getLogger(java.lang.Class)">org.slf4j.LoggerFactory.getLogger</a>(LogExample.<span class="keyword">class</span>);</code> - </dd><dt> + </dd><dt id="Xslf4j"> <code>@XSlf4j</code> </dt><dd> Creates <code><span class="keyword">private static final </span><a href="https://www.slf4j.org/api/org/slf4j/ext/XLogger.html">org.slf4j.ext.XLogger</a> <span class="staticfield">log</span> = <a href="https://www.slf4j.org/api/org/slf4j/ext/XLoggerFactory.html#getXLogger(java.lang.Class)">org.slf4j.ext.XLoggerFactory.getXLogger</a>(LogExample.<span class="keyword">class</span>);</code> + </dd><dt id="CustomLog"> + <code>@CustomLog</code> + </dt><dd> + Creates <code><span class="keyword">private static final </span><em>com.foo.your.Logger</em> <span class="staticfield">log</span> = <em>com.foo.your.LoggerFactory.createYourLogger</em>(LogExample.<span class="keyword">class</span>);</code> + <p> + This option <em>requires</em> that you add a configuration to your <a href="/features/configuration"><code>lombok.config</code></a> file to specify what <code>@CustomLog</code> should do. + </p><p> + For example:<code>lombok.log.custom.declaration = com.foo.your.Logger com.foo.your.LoggerFactory.createYourLog(TYPE)(TOPIC)</code> which would produce the above statement. First comes a type which is the type of your logger, then a space, then the type of your logger factory, then a dot, then the name of the logger factory method, and then 1 or 2 parameter definitions; at most one definition with <code>TOPIC</code> and at most one without <code>TOPIC</code>. Each parameter definition is specified as a parenthesised comma-separated list of parameter kinds. The options are: <code>TYPE</code> (passes this <code>@Log</code> decorated type, as a class), <code>NAME</code> (passes this <code>@Log</code> decorated type's fully qualified name), <code>TOPIC</code> (passes the explicitly chosen topic string set on the <code>@CustomLog</code> annotation), and <code>NULL</code> (passes <code>null</code>). + </p><p> + The logger type is optional; if it is omitted, the logger factory type is used. (So, if your logger class has a static method that creates loggers, you can shorten your logger definition). + </p><p> + Please contact us if there is a public, open source, somewhat commonly used logging framework that we don't yet have an explicit annotation for. The primary purpose of <code>@CustomLog</code> is to support your in-house, private logging frameworks. + </p> </dd> </dl> </p><p> - By default, the topic (or name) of the logger will be the class name of the class annotated with the <code>@Log</code> annotation. This can be customised by specifying the <code>topic</code> parameter. For example: <code>@XSlf4j(topic="reporting")</code>. + By default, the topic (or name) of the logger will be the (name of) the class annotated with the <code>@Log</code> annotation. This can be customised by specifying the <code>topic</code> parameter. For example: <code>@XSlf4j(topic="reporting")</code>. </p> </@f.overview> @@ -68,10 +83,18 @@ </dt><dd> Normally the generated logger is a <code>static</code> field. By setting this key to <code>false</code>, the generated field will be an instance field instead. </dd><dt> + <code>lombok.log.custom.declaration</code> = <em>LoggerType </em> LoggerFactoryType.loggerFactoryMethod(loggerFactoryMethodParams)<em>(loggerFactoryMethodParams)</em> + </dt><dd> + Configures what to generate when <code>@CustomLog</code> is used. (The italicized parts are optional). loggerFactoryMethodParams is a comma-separated list of zero to any number of parameter kinds to pass. Valid kinds: TYPE, NAME, TOPIC, and NULL. You can include a parameter definition for the case where no explicit topic is set (do not include the TOPIC in the parameter list), and for when an explicit topic is set (do include the TOPIC parameter in the list). + </dd><dt> <code>lombok.log.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set) </dt><dd> Lombok will flag any usage of any of the various log annotations as a warning or error if configured. </dd><dt> + <code>lombok.log.custom.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set) + </dt><dd> + Lombok will flag any usage of <code>@lombok.CustomLog</code> as a warning or error if configured. + </dd><dt> <code>lombok.log.apacheCommons.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set) </dt><dd> Lombok will flag any usage of <code>@lombok.extern.apachecommons.CommonsLog</code> as a warning or error if configured. |