Skip to content

Commit

Permalink
Code review for @CustomLog, and added documentation and a changelog…
Browse files Browse the repository at this point in the history
… entry.
  • Loading branch information
rzwitserloot committed May 21, 2019
1 parent bb66465 commit 7fe4896
Show file tree
Hide file tree
Showing 13 changed files with 127 additions and 90 deletions.
2 changes: 1 addition & 1 deletion doc/changelog.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
25 changes: 14 additions & 11 deletions src/core/lombok/ConfigurationKeys.java
Original file line number Diff line number Diff line change
Expand Up @@ -304,17 +304,16 @@ private ConfigurationKeys() {}
// ----- NonNull -----

/**
* lombok configuration: {@code lombok.nonNull.exceptionType} = &lt;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.") {};
Expand Down Expand Up @@ -439,23 +438,27 @@ private 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} = &lt;String: logDeclaration&gt;.
* lombok configuration: {@code lombok.log.custom.declaration} = &lt;logDeclaration string&gt;.
*
* The log declaration must follow the pattern:
* <br>
* {@code [LoggerType ]LoggerFactoryType.loggerFactoryMethod(loggerFactoryMethodParams)[(loggerFactoryMethodParams)]}
* <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.") {};

Expand Down
11 changes: 8 additions & 3 deletions src/core/lombok/CustomLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
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>
Expand All @@ -50,7 +50,7 @@
* }
* </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 &#64;Log
Expand All @@ -65,6 +65,11 @@
@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 "";
}
10 changes: 5 additions & 5 deletions src/core/lombok/core/configuration/ConfigurationDataType.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -143,16 +143,16 @@ private static ConfigurationValueParser valueTypeParser(Type argumentType) {
@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);
Expand Down Expand Up @@ -237,7 +237,7 @@ private static Method getMethod(Class<?> argumentType, String name, Class<?>...
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);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -29,6 +29,7 @@
* <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.
*/
Expand Down
11 changes: 4 additions & 7 deletions src/core/lombok/core/configuration/IdentifierName.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -31,13 +31,10 @@ private IdentifierName(String name) {
}

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);
}

Expand Down
28 changes: 10 additions & 18 deletions src/core/lombok/core/configuration/LogDeclaration.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -49,14 +49,11 @@ private LogDeclaration(TypeName loggerType, TypeName loggerFactoryType, Identifi
}

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;
Expand All @@ -67,21 +64,16 @@ public static LogDeclaration valueOf(String declaration) {
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);
}
Expand All @@ -103,7 +95,7 @@ private static List<List<LogFactoryParameter>> parseParameters(String parameters
}

public static String description() {
return "custom-log-declartation";
return "custom-log-declaration";
}

public static String exampleValue() {
Expand Down
11 changes: 4 additions & 7 deletions src/core/lombok/core/configuration/TypeName.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -31,14 +31,11 @@ private TypeName(String name) {
}

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);
}
Expand Down
23 changes: 22 additions & 1 deletion src/core/lombok/core/handlers/LoggingFramework.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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();
Expand Down
Loading

0 comments on commit 7fe4896

Please sign in to comment.