aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok
diff options
context:
space:
mode:
authorReinier Zwitserloot <r.zwitserloot@projectlombok.org>2019-07-09 00:46:03 +0200
committerReinier Zwitserloot <r.zwitserloot@projectlombok.org>2019-07-09 00:46:03 +0200
commitb7e67345b998e2a40ff63fabc893393cc9327596 (patch)
tree3e468ae52735d856b44821602001aeefd0c640b2 /src/core/lombok
parent0984d14826c62c5b99a2887aa198766ef08fea16 (diff)
parent5ad6796b182c8071fe747493ed2f9ad2443dc212 (diff)
downloadlombok-b7e67345b998e2a40ff63fabc893393cc9327596.tar.gz
lombok-b7e67345b998e2a40ff63fabc893393cc9327596.tar.bz2
lombok-b7e67345b998e2a40ff63fabc893393cc9327596.zip
Merge branch 'customlog'
Diffstat (limited to 'src/core/lombok')
-rw-r--r--src/core/lombok/ConfigurationKeys.java47
-rw-r--r--src/core/lombok/CustomLog.java75
-rw-r--r--src/core/lombok/core/configuration/ConfigurationDataType.java71
-rw-r--r--src/core/lombok/core/configuration/ConfigurationValueType.java37
-rw-r--r--src/core/lombok/core/configuration/IdentifierName.java69
-rw-r--r--src/core/lombok/core/configuration/LogDeclaration.java171
-rw-r--r--src/core/lombok/core/configuration/TypeName.java30
-rw-r--r--src/core/lombok/core/handlers/LoggingFramework.java98
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java2
-rw-r--r--src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java23
-rw-r--r--src/core/lombok/eclipse/handlers/HandleLog.java237
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSynchronized.java2
-rw-r--r--src/core/lombok/extern/apachecommons/CommonsLog.java1
-rw-r--r--src/core/lombok/extern/flogger/Flogger.java1
-rw-r--r--src/core/lombok/extern/java/Log.java1
-rw-r--r--src/core/lombok/extern/jbosslog/JBossLog.java3
-rw-r--r--src/core/lombok/extern/log4j/Log4j.java1
-rw-r--r--src/core/lombok/extern/log4j/Log4j2.java1
-rw-r--r--src/core/lombok/extern/slf4j/Slf4j.java1
-rw-r--r--src/core/lombok/extern/slf4j/XSlf4j.java1
-rw-r--r--src/core/lombok/javac/handlers/HandleFieldNameConstants.java23
-rw-r--r--src/core/lombok/javac/handlers/HandleLog.java167
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java4
23 files changed, 801 insertions, 265 deletions
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java
index 975cb72e..dda0b54b 100644
--- a/src/core/lombok/ConfigurationKeys.java
+++ b/src/core/lombok/ConfigurationKeys.java
@@ -25,7 +25,9 @@ import java.util.List;
import lombok.core.configuration.CallSuperType;
import lombok.core.configuration.ConfigurationKey;
+import lombok.core.configuration.LogDeclaration;
import lombok.core.configuration.FlagUsageType;
+import lombok.core.configuration.IdentifierName;
import lombok.core.configuration.NullCheckExceptionType;
import lombok.core.configuration.TypeName;
@@ -309,17 +311,16 @@ public class 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.") {};
@@ -423,7 +424,7 @@ public class ConfigurationKeys {
*
* If set the various log annotations (which make a log field) will use the stated identifier instead of {@code log} as a name.
*/
- public static final ConfigurationKey<String> LOG_ANY_FIELD_NAME = new ConfigurationKey<String>("lombok.log.fieldName", "Use this name for the generated logger fields (default: 'log').") {};
+ public static final ConfigurationKey<IdentifierName> LOG_ANY_FIELD_NAME = new ConfigurationKey<IdentifierName>("lombok.log.fieldName", "Use this name for the generated logger fields (default: 'log').") {};
/**
* lombok configuration: {@code lombok.log.fieldIsStatic} = {@code true} | {@code false}.
@@ -434,6 +435,40 @@ public class ConfigurationKeys {
*/
public static final ConfigurationKey<Boolean> LOG_ANY_FIELD_IS_STATIC = new ConfigurationKey<Boolean>("lombok.log.fieldIsStatic", "Make the generated logger fields static (default: true).") {};
+ // ----- Custom Logging -----
+
+ /**
+ * lombok configuration: {@code lombok.log.custom.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @CustomLog} results in a warning / error.
+ */
+ 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;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 <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}. 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>
+ *
+ * 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.") {};
+
// ##### Experimental #####
/**
@@ -548,7 +583,7 @@ public class ConfigurationKeys {
*
* The names of the constants generated by {@code @FieldNameConstants} will be prefixed with this value.
*/
- public static final ConfigurationKey<String> FIELD_NAME_CONSTANTS_INNER_TYPE_NAME = new ConfigurationKey<String>("lombok.fieldNameConstants.innerTypeName", "The default name of the inner type generated by @FieldNameConstants. (default: 'Fields').") {};
+ public static final ConfigurationKey<IdentifierName> FIELD_NAME_CONSTANTS_INNER_TYPE_NAME = new ConfigurationKey<IdentifierName>("lombok.fieldNameConstants.innerTypeName", "The default name of the inner type generated by @FieldNameConstants. (default: 'Fields').") {};
/**
* lombok configuration: {@code lombok.fieldNameConstants.uppercase} = {@code true} | {@code false}.
diff --git a/src/core/lombok/CustomLog.java b/src/core/lombok/CustomLog.java
new file mode 100644
index 00000000..d1f45f7c
--- /dev/null
+++ b/src/core/lombok/CustomLog.java
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 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>
+ * Example:
+ * <pre>
+ * &#64;CustomLog
+ * public class LogExample {
+ * }
+ * </pre>
+ * With configuration:
+ * <pre>
+ * lombok.log.custom.declaration=my.cool.Logger my.cool.LoggerFactory.getLogger(NAME)
+ * </pre>
+ *
+ * will generate:
+ *
+ * <pre>
+ * public class LogExample {
+ * private static final my.cool.Logger log = my.cool.LoggerFactory.getLogger(LogExample.class.getName());
+ * }
+ * </pre>
+ * <p>
+ * 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
+ * @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
+ * @see lombok.extern.log4j.Log4j &#64;Log4j
+ * @see lombok.extern.log4j.Log4j2 &#64;Log4j2
+ * @see lombok.extern.slf4j.Slf4j &#64;Slf4j
+ * @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
+ * @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
+ * @see lombok.extern.flogger.Flogger &#64;Flogger
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface CustomLog {
+ /**
+ *
+ * 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 7512d2e6..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
@@ -21,6 +21,8 @@
*/
package lombok.core.configuration;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
@@ -97,23 +99,10 @@ public final class ConfigurationDataType {
return "[false | true]";
}
});
- map.put(TypeName.class, new ConfigurationValueParser() {
- @Override public Object parse(String value) {
- return TypeName.valueOf(value);
- }
-
- @Override public String description() {
- return "type-name";
- }
-
- @Override public String exampleValue() {
- return "<fully.qualified.Type>";
- }
- });
SIMPLE_TYPES = map;
}
- private static ConfigurationValueParser enumParser(Object enumType) {
+ private static ConfigurationValueParser enumParser(Type enumType) {
final Class<?> type = (Class<?>) enumType;
@SuppressWarnings("rawtypes") final Class rawType = type;
@@ -145,6 +134,38 @@ public final class ConfigurationDataType {
};
}
+ private static ConfigurationValueParser valueTypeParser(Type argumentType) {
+ final Class<?> type = (Class<?>) argumentType;
+ final Method valueOfMethod = getMethod(type, "valueOf", String.class);
+ final Method descriptionMethod = getMethod(type, "description");
+ final Method exampleValueMethod = getMethod(type, "exampleValue");
+ return new ConfigurationValueParser() {
+ @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")
+ private <R> R invokeStaticMethod(Method method, Object... arguments) {
+ try {
+ return (R) method.invoke(null, arguments);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException("The method " + method.getName() + " ", e);
+ } catch (InvocationTargetException e) {
+ // There shouldn't be any checked Exception, only IllegalArgumentException is expected
+ throw (RuntimeException) e.getTargetException();
+ }
+ }
+ };
+ }
+
private final boolean isList;
private final ConfigurationValueParser parser;
@@ -155,7 +176,7 @@ public final class ConfigurationDataType {
Type type = keyClass.getGenericSuperclass();
if (!(type instanceof ParameterizedType)) {
- throw new IllegalArgumentException("Missing type parameter in "+ type);
+ throw new IllegalArgumentException("Missing type parameter in " + type);
}
ParameterizedType parameterized = (ParameterizedType) type;
@@ -178,6 +199,10 @@ public final class ConfigurationDataType {
return new ConfigurationDataType(isList, enumParser(argumentType));
}
+ if (isConfigurationValueType(argumentType)) {
+ return new ConfigurationDataType(isList, valueTypeParser(argumentType));
+ }
+
throw new IllegalArgumentException("Unsupported type parameter in " + type);
}
@@ -203,4 +228,18 @@ public final class ConfigurationDataType {
private static boolean isEnum(Type argumentType) {
return argumentType instanceof Class && ((Class<?>) argumentType).isEnum();
}
+
+ private static boolean isConfigurationValueType(Type argumentType) {
+ return argumentType instanceof Class && ConfigurationValueType.class.isAssignableFrom((Class<?>) argumentType);
+ }
+
+ private static Method getMethod(Class<?> argumentType, String name, Class<?>... parameterTypes) {
+ try {
+ return argumentType.getMethod(name, parameterTypes);
+ } catch (NoSuchMethodException 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);
+ }
+ }
} \ No newline at end of file
diff --git a/src/core/lombok/core/configuration/ConfigurationValueType.java b/src/core/lombok/core/configuration/ConfigurationValueType.java
new file mode 100644
index 00000000..a44a5a83
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationValueType.java
@@ -0,0 +1,37 @@
+/*
+ * 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.configuration;
+
+/**
+ * If a type used in {@link ConfigurationKey} type argument implements this interface,
+ * it is expected to provide the following three static methods:
+ * <ul>
+ * <li><code>public static SELF valueOf(String value)</code>
+ * <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.
+ */
+public interface ConfigurationValueType {
+}
diff --git a/src/core/lombok/core/configuration/IdentifierName.java b/src/core/lombok/core/configuration/IdentifierName.java
new file mode 100644
index 00000000..db83c2cc
--- /dev/null
+++ b/src/core/lombok/core/configuration/IdentifierName.java
@@ -0,0 +1,69 @@
+/*
+ * 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.configuration;
+
+import lombok.core.JavaIdentifiers;
+
+public final class IdentifierName implements ConfigurationValueType {
+ private final String name;
+
+ private IdentifierName(String name) {
+ this.name = name;
+ }
+
+ public static IdentifierName valueOf(String name) {
+ if (name == null || name.trim().isEmpty()) return null;
+
+ String trimmedName = name.trim();
+ if (!JavaIdentifiers.isValidJavaIdentifier(trimmedName)) throw new IllegalArgumentException("Invalid identifier " + trimmedName);
+ return new IdentifierName(trimmedName);
+ }
+
+ public static String description() {
+ return "identifier-name";
+ }
+
+ public static String exampleValue() {
+ return "<javaIdentifier>";
+ }
+
+ @Override public boolean equals(Object obj) {
+ if (!(obj instanceof IdentifierName)) return false;
+ return name.equals(((IdentifierName) obj).name);
+ }
+
+ @Override public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override public String toString() {
+ return name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public char[] getCharArray() {
+ return name.toCharArray();
+ }
+}
diff --git a/src/core/lombok/core/configuration/LogDeclaration.java b/src/core/lombok/core/configuration/LogDeclaration.java
new file mode 100644
index 00000000..ad4102d4
--- /dev/null
+++ b/src/core/lombok/core/configuration/LogDeclaration.java
@@ -0,0 +1,171 @@
+/*
+ * 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.configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class LogDeclaration implements ConfigurationValueType {
+ private static final Pattern PARAMETERS_PATTERN = Pattern.compile("(?:\\(([A-Z,]*)\\))");
+ private static final Pattern DECLARATION_PATTERN = Pattern.compile("^(?:([^ ]+) )?([^(]+)\\.([^(]+)(" + PARAMETERS_PATTERN.pattern() + "+)$");
+
+ public enum LogFactoryParameter {
+ TYPE, NAME, TOPIC, NULL;
+ }
+
+ private final TypeName loggerType;
+ private final TypeName loggerFactoryType;
+ private final IdentifierName loggerFactoryMethod;
+ private final List<LogFactoryParameter> parametersWithoutTopic;
+ private final List<LogFactoryParameter> parametersWithTopic;
+
+ private LogDeclaration(TypeName loggerType, TypeName loggerFactoryType, IdentifierName loggerFactoryMethod, List<LogFactoryParameter> parametersWithoutTopic, List<LogFactoryParameter> parametersWithTopic) {
+ this.loggerType = loggerType;
+ this.loggerFactoryType = loggerFactoryType;
+ this.loggerFactoryMethod = loggerFactoryMethod;
+ this.parametersWithoutTopic = parametersWithoutTopic;
+ this.parametersWithTopic = parametersWithTopic;
+ }
+
+ public static LogDeclaration valueOf(String declaration) {
+ 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)]");
+
+ TypeName loggerFactoryType = TypeName.valueOf(matcher.group(2));
+ TypeName loggerType = TypeName.valueOf(matcher.group(1));
+ if (loggerType == null) loggerType = loggerFactoryType;
+ IdentifierName loggerFactoryMethod = IdentifierName.valueOf(matcher.group(3));
+ List<List<LogFactoryParameter>> allParameters = parseParameters(matcher.group(4));
+
+ List<LogFactoryParameter> parametersWithoutTopic = null;
+ List<LogFactoryParameter> parametersWithTopic = null;
+ for (List<LogFactoryParameter> parameters: allParameters) {
+ if (parameters.contains(LogFactoryParameter.TOPIC)) {
+ 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 is more than one parmaeter definition that does not include TOPIC: " + parametersWithoutTopic + " and " + parameters);
+ parametersWithoutTopic = parameters;
+ }
+ }
+
+ // 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);
+ }
+
+ private static List<List<LogFactoryParameter>> parseParameters(String parametersDefinitions) {
+ List<List<LogFactoryParameter>> allParameters = new ArrayList<List<LogFactoryParameter>>();
+ Matcher matcher = PARAMETERS_PATTERN.matcher(parametersDefinitions);
+ while (matcher.find()) {
+ String parametersDefinition = matcher.group(1);
+ List<LogFactoryParameter> parameters = new ArrayList<LogFactoryParameter>();
+ if (!parametersDefinition.isEmpty()) {
+ for (String parameter : parametersDefinition.split(",")) {
+ parameters.add(LogFactoryParameter.valueOf(parameter));
+ }
+ }
+ allParameters.add(parameters);
+ }
+ return allParameters;
+ }
+
+ public static String description() {
+ return "custom-log-declaration";
+ }
+
+ public static String exampleValue() {
+ return "my.cool.Logger my.cool.LoggerFactory.createLogger()(TOPIC,TYPE)";
+ }
+
+ @Override public boolean equals(Object obj) {
+ if (!(obj instanceof LogDeclaration)) return false;
+ return loggerType.equals(((LogDeclaration) obj).loggerType)
+ && loggerFactoryType.equals(((LogDeclaration) obj).loggerFactoryType)
+ && loggerFactoryMethod.equals(((LogDeclaration) obj).loggerFactoryMethod)
+ && parametersWithoutTopic == ((LogDeclaration) obj).parametersWithoutTopic || parametersWithoutTopic.equals(((LogDeclaration) obj).parametersWithoutTopic)
+ && parametersWithTopic == ((LogDeclaration) obj).parametersWithTopic || parametersWithTopic.equals(((LogDeclaration) obj).parametersWithTopic);
+ }
+
+ @Override public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + loggerType.hashCode();
+ result = prime * result + loggerFactoryType.hashCode();
+ result = prime * result + loggerFactoryMethod.hashCode();
+ result = prime * result + ((parametersWithTopic == null) ? 0 : parametersWithTopic.hashCode());
+ result = prime * result + ((parametersWithoutTopic == null) ? 0 : parametersWithoutTopic.hashCode());
+ return result;
+ }
+
+ @Override public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(loggerType);
+ sb.append(" ");
+ sb.append(loggerFactoryType);
+ sb.append(".");
+ sb.append(loggerFactoryMethod);
+ appendParams(sb, parametersWithoutTopic);
+ appendParams(sb, parametersWithTopic);
+ return sb.toString();
+ }
+
+ private static void appendParams(StringBuilder sb, List<LogFactoryParameter> params) {
+ if (params != null) {
+ sb.append("(");
+ boolean first = true;
+ for (LogFactoryParameter param : params) {
+ if (!first) {
+ sb.append(",");
+ }
+ first = false;
+ sb.append(param);
+ }
+ sb.append(")");
+ }
+ }
+
+ public TypeName getLoggerType() {
+ return loggerType;
+ }
+
+ public TypeName getLoggerFactoryType() {
+ return loggerFactoryType;
+ }
+
+ public IdentifierName getLoggerFactoryMethod() {
+ return loggerFactoryMethod;
+ }
+
+ public List<LogFactoryParameter> getParametersWithoutTopic() {
+ return parametersWithoutTopic;
+ }
+
+ public List<LogFactoryParameter> getParametersWithTopic() {
+ return parametersWithTopic;
+ }
+}
diff --git a/src/core/lombok/core/configuration/TypeName.java b/src/core/lombok/core/configuration/TypeName.java
index 989e1b97..a1eac7bd 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
@@ -21,7 +21,9 @@
*/
package lombok.core.configuration;
-public final class TypeName {
+import lombok.core.JavaIdentifiers;
+
+public final class TypeName implements ConfigurationValueType {
private final String name;
private TypeName(String name) {
@@ -29,7 +31,21 @@ public final class TypeName {
}
public static TypeName valueOf(String name) {
- return new TypeName(name);
+ 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 + ")");
+ }
+ return new TypeName(trimmedName);
+ }
+
+ public static String description() {
+ return "type-name";
+ }
+
+ public static String exampleValue() {
+ return "<fully.qualified.Type>";
}
@Override public boolean equals(Object obj) {
@@ -44,4 +60,12 @@ public final class TypeName {
@Override public String toString() {
return name;
}
+
+ public String getName() {
+ return name;
+ }
+
+ public char[] getCharArray() {
+ return name.toCharArray();
+ }
}
diff --git a/src/core/lombok/core/handlers/LoggingFramework.java b/src/core/lombok/core/handlers/LoggingFramework.java
new file mode 100644
index 00000000..88c0317b
--- /dev/null
+++ b/src/core/lombok/core/handlers/LoggingFramework.java
@@ -0,0 +1,98 @@
+/*
+ * 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;
+
+import lombok.core.configuration.LogDeclaration;
+
+public class LoggingFramework {
+ // private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(TargetType.class);
+ public static final LoggingFramework COMMONS = new LoggingFramework(
+ lombok.extern.apachecommons.CommonsLog.class,
+ LogDeclaration.valueOf("org.apache.commons.logging.Log org.apache.commons.logging.LogFactory.getLog(TYPE)(TOPIC)")
+ );
+
+ // private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(TargetType.class.getName());
+ public static final LoggingFramework JUL = new LoggingFramework(
+ lombok.extern.java.Log.class,
+ LogDeclaration.valueOf("java.util.logging.Logger java.util.logging.Logger.getLogger(NAME)(TOPIC)")
+ );
+
+ // private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TargetType.class);
+ public static final LoggingFramework LOG4J = new LoggingFramework(
+ lombok.extern.log4j.Log4j.class,
+ LogDeclaration.valueOf("org.apache.log4j.Logger org.apache.log4j.Logger.getLogger(TYPE)(TOPIC)")
+ );
+
+ // private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(TargetType.class);
+ public static final LoggingFramework LOG4J2 = new LoggingFramework(
+ lombok.extern.log4j.Log4j2.class,
+ LogDeclaration.valueOf("org.apache.logging.log4j.Logger org.apache.logging.log4j.LogManager.getLogger(TYPE)(TOPIC)")
+ );
+
+ // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TargetType.class);
+ public static final LoggingFramework SLF4J = new LoggingFramework(
+ lombok.extern.slf4j.Slf4j.class,
+ LogDeclaration.valueOf("org.slf4j.Logger org.slf4j.LoggerFactory.getLogger(TYPE)(TOPIC)")
+ );
+
+ // private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(TargetType.class);
+ public static final LoggingFramework XSLF4J = new LoggingFramework(
+ lombok.extern.slf4j.XSlf4j.class,
+ LogDeclaration.valueOf("org.slf4j.ext.XLogger org.slf4j.ext.XLoggerFactory.getXLogger(TYPE)(TOPIC)")
+ );
+
+ // private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(TargetType.class);
+ public static final LoggingFramework JBOSSLOG = new LoggingFramework(
+ lombok.extern.jbosslog.JBossLog.class,
+ LogDeclaration.valueOf("org.jboss.logging.Logger org.jboss.logging.Logger.getLogger(TYPE)(TOPIC)")
+ );
+
+ // private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();
+ public static final LoggingFramework FLOGGER = new LoggingFramework(
+ lombok.extern.flogger.Flogger.class,
+ LogDeclaration.valueOf("com.google.common.flogger.FluentLogger com.google.common.flogger.FluentLogger.forEnclosingClass()")
+ );
+
+ 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();
+ this.declaration = declaration;
+ }
+
+ public Class<? extends Annotation> getAnnotationClass() {
+ return annotationClass;
+ }
+
+ public String getAnnotationAsString() {
+ return annotationAsString;
+ }
+
+ public LogDeclaration getDeclaration() {
+ return declaration;
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index 463990d1..1a0633bf 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -761,7 +761,7 @@ public class EclipseHandlerUtil {
TypeReference typeRef = annotation.type;
boolean match = false;
if (typeRef != null && typeRef.getTypeName() != null) {
- for (TypeName cn : configuredCopyable) if (typeMatches(cn.toString(), node, typeRef)) {
+ for (TypeName cn : configuredCopyable) if (cn != null && typeMatches(cn.toString(), node, typeRef)) {
result.add(annotation);
match = true;
break;
diff --git a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
index 574c1f41..2db7591c 100644
--- a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
+++ b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
@@ -47,6 +47,7 @@ import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.configuration.IdentifierName;
import lombok.core.handlers.HandlerUtil;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
@@ -56,7 +57,9 @@ import lombok.experimental.FieldNameConstants;
@ProviderFor(EclipseAnnotationHandler.class)
public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldNameConstants> {
- public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit, boolean uppercase) {
+ private static final IdentifierName FIELDS = IdentifierName.valueOf("Fields");
+
+ public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, boolean asEnum, IdentifierName innerTypeName, boolean onlyExplicit, boolean uppercase) {
TypeDeclaration typeDecl = null;
if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
@@ -110,23 +113,29 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldName
return;
}
- String innerTypeName = annotationInstance.innerTypeName();
- if (innerTypeName.isEmpty()) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME);
- if (innerTypeName == null || innerTypeName.isEmpty()) innerTypeName = "Fields";
+ IdentifierName innerTypeName;
+ try {
+ innerTypeName = IdentifierName.valueOf(annotationInstance.innerTypeName());
+ } catch(IllegalArgumentException e) {
+ annotationNode.addError("InnerTypeName " + annotationInstance.innerTypeName() + " is not a valid Java identifier.");
+ return;
+ }
+ if (innerTypeName == null) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME);
+ if (innerTypeName == null) innerTypeName = FIELDS;
Boolean uppercase = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_UPPERCASE);
if (uppercase == null) uppercase = false;
generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded(), uppercase);
}
- private void createInnerTypeFieldNameConstants(EclipseNode typeNode, EclipseNode errorNode, ASTNode source, AccessLevel level, List<EclipseNode> fields, boolean asEnum, String innerTypeName, boolean uppercase) {
+ private void createInnerTypeFieldNameConstants(EclipseNode typeNode, EclipseNode errorNode, ASTNode source, AccessLevel level, List<EclipseNode> fields, boolean asEnum, IdentifierName innerTypeName, boolean uppercase) {
if (fields.isEmpty()) return;
ASTVisitor generatedByVisitor = new SetGeneratedByVisitor(source);
TypeDeclaration parent = (TypeDeclaration) typeNode.get();
- EclipseNode fieldsType = findInnerClass(typeNode, innerTypeName);
+ EclipseNode fieldsType = findInnerClass(typeNode, innerTypeName.getName());
boolean genConstr = false, genClinit = false;
- char[] name = innerTypeName.toCharArray();
+ char[] name = innerTypeName.getCharArray();
TypeDeclaration generatedInnerType = null;
if (fieldsType == null) {
generatedInnerType = new TypeDeclaration(parent.compilationResult);
diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java
index 8c7f7971..7a140193 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
@@ -21,24 +21,20 @@
*/
package lombok.eclipse.handlers;
-import static lombok.core.handlers.HandlerUtil.*;
+import static lombok.core.handlers.HandlerUtil.handleFlagUsage;
import static lombok.eclipse.Eclipse.fromQualifiedName;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.lang.reflect.Modifier;
import java.util.Arrays;
-
-import lombok.ConfigurationKeys;
-import lombok.core.AnnotationValues;
-import lombok.eclipse.EclipseAnnotationHandler;
-import lombok.eclipse.EclipseNode;
-import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
+import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
@@ -47,7 +43,18 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.mangosdk.spi.ProviderFor;
+import lombok.ConfigurationKeys;
+import lombok.core.AnnotationValues;
+import lombok.core.configuration.IdentifierName;
+import lombok.core.configuration.LogDeclaration;
+import lombok.core.configuration.LogDeclaration.LogFactoryParameter;
+import lombok.core.handlers.LoggingFramework;
+import lombok.eclipse.EclipseAnnotationHandler;
+import lombok.eclipse.EclipseNode;
+
public class HandleLog {
+ private static final IdentifierName LOG = IdentifierName.valueOf("log");
+
private HandleLog() {
throw new UnsupportedOperationException();
}
@@ -57,8 +64,8 @@ public class HandleLog {
switch (owner.getKind()) {
case TYPE:
- String logFieldName = annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_NAME);
- if (logFieldName == null) logFieldName = "log";
+ IdentifierName logFieldName = annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_NAME);
+ if (logFieldName == null) logFieldName = LOG;
boolean useStatic = !Boolean.FALSE.equals(annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_IS_STATIC));
@@ -66,24 +73,32 @@ 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.");
return;
}
- if (fieldExists(logFieldName, owner) != MemberExistsResult.NOT_EXISTS) {
+ if (fieldExists(logFieldName.getName(), owner) != MemberExistsResult.NOT_EXISTS) {
annotationNode.addWarning("Field '" + logFieldName + "' already exists.");
return;
}
- ClassLiteralAccess loggingType = selfType(owner, source);
+ if (loggerTopic != null && loggerTopic.trim().isEmpty()) loggerTopic = null;
+ if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) {
+ annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic.");
+ loggerTopic = null;
+ }
+ if (framework.getDeclaration().getParametersWithoutTopic() == null && loggerTopic == null) {
+ annotationNode.addError(framework.getAnnotationAsString() + " requires a topic.");
+ loggerTopic = "";
+ }
- FieldDeclaration fieldDeclaration = createField(framework, source, loggingType, logFieldName, useStatic, loggerTopic);
+ 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();
@@ -95,12 +110,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);
@@ -111,30 +126,23 @@ 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;
fieldDecl.modifiers = Modifier.PRIVATE | (useStatic ? Modifier.STATIC : 0) | Modifier.FINAL;
- fieldDecl.type = createTypeReference(framework.getLoggerTypeName(), source);
+ LogDeclaration logDeclaration = framework.getDeclaration();
+ fieldDecl.type = createTypeReference(logDeclaration.getLoggerType().getName(), source);
MessageSend factoryMethodCall = new MessageSend();
setGeneratedBy(factoryMethodCall, source);
-
- factoryMethodCall.receiver = createNameReference(framework.getLoggerFactoryTypeName(), source);
- factoryMethodCall.selector = framework.getLoggerFactoryMethodName().toCharArray();
- Expression parameter;
- if (!framework.passTypeName) {
- parameter = null;
- } else if (loggerTopic == null || loggerTopic.trim().length() == 0) {
- parameter = framework.createFactoryParameter(loggingType, source);
- } else {
- parameter = new StringLiteral(loggerTopic.toCharArray(), pS, pE, 0);
- }
+ factoryMethodCall.receiver = createNameReference(logDeclaration.getLoggerFactoryType().getName(), source);
+ factoryMethodCall.selector = logDeclaration.getLoggerFactoryMethod().getCharArray();
- factoryMethodCall.arguments = parameter != null ? new Expression[] { parameter } : null;
+ List<LogFactoryParameter> parameters = loggerTopic != null ? logDeclaration.getParametersWithTopic() : logDeclaration.getParametersWithoutTopic();
+ factoryMethodCall.arguments = createFactoryParameters(loggingType, source, parameters, loggerTopic);
factoryMethodCall.nameSourcePosition = p;
factoryMethodCall.sourceStart = pS;
factoryMethodCall.sourceEnd = factoryMethodCall.statementEnd = pE;
@@ -146,25 +154,64 @@ 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;
- TypeReference typeReference;
- if (typeName.contains(".")) {
-
- char[][] typeNameTokens = fromQualifiedName(typeName);
- long[] pos = new long[typeNameTokens.length];
- Arrays.fill(pos, p);
-
- typeReference = new QualifiedTypeReference(typeNameTokens, pos);
- }
- else {
- typeReference = null;
- }
+ char[][] typeNameTokens = fromQualifiedName(typeName);
+ long[] pos = new long[typeNameTokens.length];
+ Arrays.fill(pos, p);
+ TypeReference typeReference = new QualifiedTypeReference(typeNameTokens, pos);
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;
+
+ for (int i = 0; i < parameters.size(); i++) {
+ LogFactoryParameter parameter = parameters.get(i);
+
+ switch(parameter) {
+ case TYPE:
+ expressions[i] = createFactoryTypeParameter(loggingType, source);
+ break;
+ case NAME:
+ long p = (long) pS << 32 | pE;
+
+ MessageSend factoryParameterCall = new MessageSend();
+ setGeneratedBy(factoryParameterCall, source);
+
+ factoryParameterCall.receiver = createFactoryTypeParameter(loggingType, source);
+ factoryParameterCall.selector = "getName".toCharArray();
+
+ factoryParameterCall.nameSourcePosition = p;
+ factoryParameterCall.sourceStart = pS;
+ factoryParameterCall.sourceEnd = factoryParameterCall.statementEnd = pE;
+
+ expressions[i] = factoryParameterCall;
+ break;
+ case TOPIC:
+ expressions[i] = new StringLiteral(loggerTopic.toCharArray(), pS, pE, 0);
+ break;
+ case NULL:
+ expressions[i] = new NullLiteral(pS, pE);
+ break;
+ default:
+ throw new IllegalStateException("Unknown logger factory parameter type: " + parameter);
+ }
+ }
+
+ return expressions;
+ }
+
+ private static final Expression createFactoryTypeParameter(ClassLiteralAccess loggingType, Annotation source) {
+ TypeReference copy = copyType(loggingType.type, source);
+ ClassLiteralAccess result = new ClassLiteralAccess(source.sourceEnd, copy);
+ setGeneratedBy(result, source);
+ return result;
+ }
+
/**
* Handles the {@link lombok.extern.apachecommons.CommonsLog} annotation for Eclipse.
*/
@@ -253,92 +300,20 @@ public class HandleLog {
}
}
- enum LoggingFramework {
- // private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(TargetType.class);
- COMMONS("org.apache.commons.logging.Log", "org.apache.commons.logging.LogFactory", "getLog", "@CommonsLog"),
-
- // private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(TargetType.class.getName());
- JUL("java.util.logging.Logger", "java.util.logging.Logger", "getLogger", "@Log") {
- @Override public Expression createFactoryParameter(ClassLiteralAccess type, Annotation source) {
- int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long)pS << 32 | pE;
-
- MessageSend factoryParameterCall = new MessageSend();
- setGeneratedBy(factoryParameterCall, source);
-
- factoryParameterCall.receiver = super.createFactoryParameter(type, source);
- factoryParameterCall.selector = "getName".toCharArray();
-
- factoryParameterCall.nameSourcePosition = p;
- factoryParameterCall.sourceStart = pS;
- factoryParameterCall.sourceEnd = factoryParameterCall.statementEnd = pE;
-
- return factoryParameterCall;
+ /**
+ * Handles the {@link lombok.CustomLog} annotation for Eclipse.
+ */
+ @ProviderFor(EclipseAnnotationHandler.class)
+ public static class HandleCustomLog extends EclipseAnnotationHandler<lombok.CustomLog> {
+ @Override public void handle(AnnotationValues<lombok.CustomLog> annotation, Annotation source, EclipseNode annotationNode) {
+ 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 annotation is not configured; please set log.custom.declaration in lombok.config.");
+ return;
}
- },
-
- // private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TargetType.class);
- LOG4J("org.apache.log4j.Logger", "org.apache.log4j.Logger", "getLogger", "@Log4j"),
-
- // private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(TargetType.class);
- LOG4J2("org.apache.logging.log4j.Logger", "org.apache.logging.log4j.LogManager", "getLogger", "@Log4j2"),
-
- // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TargetType.class);
- SLF4J("org.slf4j.Logger", "org.slf4j.LoggerFactory", "getLogger", "@Slf4j"),
-
- // private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(TargetType.class);
- XSLF4J("org.slf4j.ext.XLogger", "org.slf4j.ext.XLoggerFactory", "getXLogger", "@XSlf4j"),
-
- // private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(TargetType.class);
- JBOSSLOG("org.jboss.logging.Logger", "org.jboss.logging.Logger", "getLogger", "@JBossLog"),
-
- // private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();
- FLOGGER("com.google.common.flogger.FluentLogger", "com.google.common.flogger.FluentLogger", "forEnclosingClass", "@Flogger", false),
- ;
-
- private final String loggerTypeName;
- private final String loggerFactoryTypeName;
- private final String loggerFactoryMethodName;
- private final String annotationAsString;
- private final boolean passTypeName;
-
- LoggingFramework(String loggerTypeName, String loggerFactoryTypeName, String loggerFactoryMethodName, String annotationAsString, boolean passTypeName) {
- this.loggerTypeName = loggerTypeName;
- this.loggerFactoryTypeName = loggerFactoryTypeName;
- this.loggerFactoryMethodName = loggerFactoryMethodName;
- this.annotationAsString = annotationAsString;
- this.passTypeName = passTypeName;
- }
-
- LoggingFramework(String loggerTypeName, String loggerFactoryTypeName, String loggerFactoryMethodName, String annotationAsString) {
- this.loggerTypeName = loggerTypeName;
- this.loggerFactoryTypeName = loggerFactoryTypeName;
- this.loggerFactoryMethodName = loggerFactoryMethodName;
- this.annotationAsString = annotationAsString;
- this.passTypeName = true;
- }
-
- final String getAnnotationAsString() {
- return annotationAsString;
- }
-
- final String getLoggerTypeName() {
- return loggerTypeName;
+ LoggingFramework framework = new LoggingFramework(lombok.CustomLog.class, logDeclaration);
+ processAnnotation(framework, annotation, source, annotationNode, annotation.getInstance().topic());
}
-
- final String getLoggerFactoryTypeName() {
- return loggerFactoryTypeName;
- }
-
- final String getLoggerFactoryMethodName() {
- return loggerFactoryMethodName;
- }
-
- Expression createFactoryParameter(ClassLiteralAccess loggingType, Annotation source) {
- TypeReference copy = copyType(loggingType.type, source);
- ClassLiteralAccess result = new ClassLiteralAccess(source.sourceEnd, copy);
- setGeneratedBy(result, source);
- return result;
- };
}
}
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/extern/apachecommons/CommonsLog.java b/src/core/lombok/extern/apachecommons/CommonsLog.java
index fa3d6f09..ca808329 100644
--- a/src/core/lombok/extern/apachecommons/CommonsLog.java
+++ b/src/core/lombok/extern/apachecommons/CommonsLog.java
@@ -57,6 +57,7 @@ import java.lang.annotation.Target;
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
* @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
* @see lombok.extern.flogger.Flogger &#64;Flogger
+ * @see lombok.CustomLog &#64;CustomLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
diff --git a/src/core/lombok/extern/flogger/Flogger.java b/src/core/lombok/extern/flogger/Flogger.java
index ecbfd28c..3446e949 100644
--- a/src/core/lombok/extern/flogger/Flogger.java
+++ b/src/core/lombok/extern/flogger/Flogger.java
@@ -55,6 +55,7 @@ import java.lang.annotation.Target;
* @see lombok.extern.slf4j.Slf4j &#64;Slf4j
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
* @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
+ * @see lombok.CustomLog &#64;CustomLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
diff --git a/src/core/lombok/extern/java/Log.java b/src/core/lombok/extern/java/Log.java
index 9a1ee412..f2b5024f 100644
--- a/src/core/lombok/extern/java/Log.java
+++ b/src/core/lombok/extern/java/Log.java
@@ -56,6 +56,7 @@ import java.lang.annotation.Target;
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
* @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
* @see lombok.extern.flogger.Flogger &#64;Flogger
+ * @see lombok.CustomLog &#64;CustomLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
diff --git a/src/core/lombok/extern/jbosslog/JBossLog.java b/src/core/lombok/extern/jbosslog/JBossLog.java
index 684585e0..960a111b 100644
--- a/src/core/lombok/extern/jbosslog/JBossLog.java
+++ b/src/core/lombok/extern/jbosslog/JBossLog.java
@@ -56,7 +56,8 @@ import java.lang.annotation.Target;
* @see lombok.extern.slf4j.Slf4j &#64;Slf4j
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
* @see lombok.extern.flogger.Flogger &#64;Flogger
- * */
+ * @see lombok.CustomLog &#64;CustomLog
+ */
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface JBossLog {
diff --git a/src/core/lombok/extern/log4j/Log4j.java b/src/core/lombok/extern/log4j/Log4j.java
index 249ef71a..1b4a973b 100644
--- a/src/core/lombok/extern/log4j/Log4j.java
+++ b/src/core/lombok/extern/log4j/Log4j.java
@@ -57,6 +57,7 @@ import java.lang.annotation.Target;
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
* @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
* @see lombok.extern.flogger.Flogger &#64;Flogger
+ * @see lombok.CustomLog &#64;CustomLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
diff --git a/src/core/lombok/extern/log4j/Log4j2.java b/src/core/lombok/extern/log4j/Log4j2.java
index a6aa90c0..571b0563 100644
--- a/src/core/lombok/extern/log4j/Log4j2.java
+++ b/src/core/lombok/extern/log4j/Log4j2.java
@@ -57,6 +57,7 @@ import java.lang.annotation.Target;
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
* @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
* @see lombok.extern.flogger.Flogger &#64;Flogger
+ * @see lombok.CustomLog &#64;CustomLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
diff --git a/src/core/lombok/extern/slf4j/Slf4j.java b/src/core/lombok/extern/slf4j/Slf4j.java
index 347d81d2..c4aded24 100644
--- a/src/core/lombok/extern/slf4j/Slf4j.java
+++ b/src/core/lombok/extern/slf4j/Slf4j.java
@@ -56,6 +56,7 @@ import java.lang.annotation.Target;
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
* @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
* @see lombok.extern.flogger.Flogger &#64;Flogger
+ * @see lombok.CustomLog &#64;CustomLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
diff --git a/src/core/lombok/extern/slf4j/XSlf4j.java b/src/core/lombok/extern/slf4j/XSlf4j.java
index 4d53a1eb..b99554a5 100644
--- a/src/core/lombok/extern/slf4j/XSlf4j.java
+++ b/src/core/lombok/extern/slf4j/XSlf4j.java
@@ -56,6 +56,7 @@ import java.lang.annotation.Target;
* @see lombok.extern.slf4j.Slf4j &#64;Slf4j
* @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
* @see lombok.extern.flogger.Flogger &#64;Flogger
+ * @see lombok.CustomLog &#64;CustomLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
diff --git a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java
index 628e83dc..ec4015c7 100644
--- a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java
+++ b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java
@@ -30,6 +30,7 @@ import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.configuration.IdentifierName;
import lombok.core.handlers.HandlerUtil;
import lombok.experimental.FieldNameConstants;
import lombok.javac.JavacAnnotationHandler;
@@ -54,7 +55,9 @@ import com.sun.tools.javac.util.Name;
@ProviderFor(JavacAnnotationHandler.class)
public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameConstants> {
- public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit, boolean uppercase) {
+ private static final IdentifierName FIELDS = IdentifierName.valueOf("Fields");
+
+ public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean asEnum, IdentifierName innerTypeName, boolean onlyExplicit, boolean uppercase) {
JCClassDecl typeDecl = null;
if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
@@ -115,24 +118,30 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo
return;
}
- String innerTypeName = annotationInstance.innerTypeName();
- if (innerTypeName.isEmpty()) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME);
- if (innerTypeName == null || innerTypeName.isEmpty()) innerTypeName = "Fields";
+ IdentifierName innerTypeName;
+ try {
+ innerTypeName = IdentifierName.valueOf(annotationInstance.innerTypeName());
+ } catch(IllegalArgumentException e) {
+ annotationNode.addError("InnerTypeName " + annotationInstance.innerTypeName() + " is not a valid Java identifier.");
+ return;
+ }
+ if (innerTypeName == null) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME);
+ if (innerTypeName == null) innerTypeName = FIELDS;
Boolean uppercase = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_UPPERCASE);
if (uppercase == null) uppercase = false;
generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded(), uppercase);
}
- private void createInnerTypeFieldNameConstants(JavacNode typeNode, JavacNode errorNode, JCTree pos, AccessLevel level, java.util.List<JavacNode> fields, boolean asEnum, String innerTypeName, boolean uppercase) {
+ private void createInnerTypeFieldNameConstants(JavacNode typeNode, JavacNode errorNode, JCTree pos, AccessLevel level, java.util.List<JavacNode> fields, boolean asEnum, IdentifierName innerTypeName, boolean uppercase) {
if (fields.isEmpty()) return;
JavacTreeMaker maker = typeNode.getTreeMaker();
JCModifiers mods = maker.Modifiers(toJavacModifier(level) | (asEnum ? Flags.ENUM : Flags.STATIC | Flags.FINAL));
- Name fieldsName = typeNode.toName(innerTypeName);
+ Name fieldsName = typeNode.toName(innerTypeName.getName());
- JavacNode fieldsType = findInnerClass(typeNode, innerTypeName);
+ JavacNode fieldsType = findInnerClass(typeNode, innerTypeName.getName());
boolean genConstr = false;
if (fieldsType == null) {
JCClassDecl innerType = maker.ClassDef(mods, fieldsName, List.<JCTypeParameter>nil(), null, List.<JCExpression>nil(), List.<JCTree>nil());
diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java
index 6d742e76..522f8576 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
@@ -22,15 +22,19 @@
package lombok.javac.handlers;
import static lombok.core.handlers.HandlerUtil.*;
+import static lombok.javac.Javac.CTC_BOT;
import static lombok.javac.handlers.JavacHandlerUtil.*;
-import java.lang.annotation.Annotation;
-
import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
+import lombok.core.configuration.IdentifierName;
+import lombok.core.configuration.LogDeclaration;
+import lombok.core.configuration.LogDeclaration.LogFactoryParameter;
+import lombok.core.handlers.LoggingFramework;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
import org.mangosdk.spi.ProviderFor;
@@ -46,32 +50,44 @@ import com.sun.tools.javac.util.List;
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:
- String logFieldName = annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_NAME);
- if (logFieldName == null) logFieldName = "log";
+ IdentifierName logFieldName = annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_NAME);
+ if (logFieldName == null) logFieldName = LOG;
boolean useStatic = !Boolean.FALSE.equals(annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_IS_STATIC));
- if ((((JCClassDecl)typeNode.get()).mods.flags & Flags.INTERFACE) != 0) {
- annotationNode.addError("@Log is legal only on classes and enums.");
+ if ((((JCClassDecl) typeNode.get()).mods.flags & Flags.INTERFACE) != 0) {
+ annotationNode.addError(framework.getAnnotationAsString() + " is legal only on classes and enums.");
return;
}
- if (fieldExists(logFieldName, typeNode) != MemberExistsResult.NOT_EXISTS) {
+ if (fieldExists(logFieldName.getName(), typeNode) != MemberExistsResult.NOT_EXISTS) {
annotationNode.addWarning("Field '" + logFieldName + "' already exists.");
return;
}
-
+
+ if (loggerTopic != null && loggerTopic.trim().isEmpty()) loggerTopic = null;
+ if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) {
+ annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic.");
+ loggerTopic = null;
+ }
+ if (framework.getDeclaration().getParametersWithoutTopic() == null && loggerTopic == null) {
+ annotationNode.addError(framework.getAnnotationAsString() + " requires a topic.");
+ loggerTopic = "";
+ }
+
JCFieldAccess loggingType = selfType(typeNode);
- createField(framework, typeNode, loggingType, annotationNode.get(), logFieldName, useStatic, loggerTopic);
+ createField(framework, typeNode, loggingType, annotationNode.get(), logFieldName.getName(), useStatic, loggerTopic);
break;
default:
annotationNode.addError("@Log is legal only on types.");
@@ -88,29 +104,51 @@ public class HandleLog {
private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source, String logFieldName, boolean useStatic, String loggerTopic) {
JavacTreeMaker maker = typeNode.getTreeMaker();
+ LogDeclaration logDeclaration = framework.getDeclaration();
// private static final <loggerType> log = <factoryMethod>(<parameter>);
- JCExpression loggerType = chainDotsString(typeNode, framework.getLoggerTypeName());
- JCExpression factoryMethod = chainDotsString(typeNode, framework.getLoggerFactoryMethodName());
+ JCExpression loggerType = chainDotsString(typeNode, logDeclaration.getLoggerType().getName());
+ JCExpression factoryMethod = chainDotsString(typeNode, logDeclaration.getLoggerFactoryType().getName() + "." + logDeclaration.getLoggerFactoryMethod().getName());
- JCExpression loggerName;
- if (!framework.passTypeName) {
- loggerName = null;
- } else if (loggerTopic == null || loggerTopic.trim().length() == 0) {
- loggerName = framework.createFactoryParameter(typeNode, loggingType);
- } else {
- loggerName = maker.Literal(loggerTopic);
- }
-
- JCMethodInvocation factoryMethodCall = maker.Apply(List.<JCExpression>nil(), factoryMethod, loggerName != null ? List.<JCExpression>of(loggerName) : List.<JCExpression>nil());
+ java.util.List<LogFactoryParameter> parameters = loggerTopic != null ? logDeclaration.getParametersWithTopic() : logDeclaration.getParametersWithoutTopic();
+ JCExpression[] factoryParameters = createFactoryParameters(typeNode, loggingType, parameters, loggerTopic);
+ 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;
}
+ private static JCExpression[] createFactoryParameters(JavacNode typeNode, JCFieldAccess loggingType, java.util.List<LogFactoryParameter> parameters, String loggerTopic) {
+ JCExpression[] expressions = new JCExpression[parameters.size()];
+ JavacTreeMaker maker = typeNode.getTreeMaker();
+
+ for (int i = 0; i < parameters.size(); i++) {
+ LogFactoryParameter parameter = parameters.get(i);
+ switch (parameter) {
+ case TYPE:
+ expressions[i] = loggingType;
+ break;
+ case NAME:
+ JCExpression method = maker.Select(loggingType, typeNode.toName("getName"));
+ expressions[i] = maker.Apply(List.<JCExpression>nil(), method, List.<JCExpression>nil());
+ break;
+ case TOPIC:
+ expressions[i] = maker.Literal(loggerTopic);
+ break;
+ case NULL:
+ expressions[i] = maker.Literal(CTC_BOT, null);
+ break;
+ default:
+ throw new IllegalStateException("Unknown logger factory parameter type: " + parameter);
+ }
+ }
+
+ return expressions;
+ }
+
/**
* Handles the {@link lombok.extern.apachecommons.CommonsLog} annotation for javac.
*/
@@ -199,71 +237,20 @@ public class HandleLog {
}
}
- enum LoggingFramework {
- // private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(TargetType.class);
- COMMONS(lombok.extern.apachecommons.CommonsLog.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.extern.java.Log.class, "java.util.logging.Logger", "java.util.logging.Logger.getLogger") {
- @Override public JCExpression createFactoryParameter(JavacNode typeNode, JCFieldAccess loggingType) {
- JavacTreeMaker maker = typeNode.getTreeMaker();
- JCExpression method = maker.Select(loggingType, typeNode.toName("getName"));
- return maker.Apply(List.<JCExpression>nil(), method, List.<JCExpression>nil());
+ /**
+ * Handles the {@link lombok.CustomLog} annotation for javac.
+ */
+ @ProviderFor(JavacAnnotationHandler.class)
+ public static class HandleCustomLog extends JavacAnnotationHandler<lombok.CustomLog> {
+ @Override public void handle(AnnotationValues<lombok.CustomLog> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ 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.");
+ return;
}
- },
-
- // private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TargetType.class);
- LOG4J(lombok.extern.log4j.Log4j.class, "org.apache.log4j.Logger", "org.apache.log4j.Logger.getLogger"),
-
- // private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(TargetType.class);
- LOG4J2(lombok.extern.log4j.Log4j2.class, "org.apache.logging.log4j.Logger", "org.apache.logging.log4j.LogManager.getLogger"),
-
- // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TargetType.class);
- SLF4J(lombok.extern.slf4j.Slf4j.class, "org.slf4j.Logger", "org.slf4j.LoggerFactory.getLogger"),
-
- // private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(TargetType.class);
- XSLF4J(lombok.extern.slf4j.XSlf4j.class, "org.slf4j.ext.XLogger", "org.slf4j.ext.XLoggerFactory.getXLogger"),
-
- // private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(TargetType.class);
- JBOSSLOG(lombok.extern.jbosslog.JBossLog.class, "org.jboss.logging.Logger", "org.jboss.logging.Logger.getLogger"),
-
- // private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();
- FLOGGER(lombok.extern.flogger.Flogger.class, "com.google.common.flogger.FluentLogger", "com.google.common.flogger.FluentLogger.forEnclosingClass", false),
- ;
-
- private final Class<? extends Annotation> annotationClass;
- private final String loggerTypeName;
- private final String loggerFactoryName;
- private final boolean passTypeName;
-
- LoggingFramework(Class<? extends Annotation> annotationClass, String loggerTypeName, String loggerFactoryName, boolean passTypeName) {
- this.annotationClass = annotationClass;
- this.loggerTypeName = loggerTypeName;
- this.loggerFactoryName = loggerFactoryName;
- this.passTypeName = passTypeName;
- }
-
- LoggingFramework(Class<? extends Annotation> annotationClass, String loggerTypeName, String loggerFactoryName) {
- this.annotationClass = annotationClass;
- this.loggerTypeName = loggerTypeName;
- this.loggerFactoryName = loggerFactoryName;
- this.passTypeName = true;
- }
-
- final Class<? extends Annotation> getAnnotationClass() {
- return annotationClass;
- }
-
- final String getLoggerTypeName() {
- return loggerTypeName;
- }
-
- final String getLoggerFactoryMethodName() {
- return loggerFactoryName;
- }
-
- JCExpression createFactoryParameter(JavacNode typeNode, JCFieldAccess loggingType) {
- return loggingType;
+ LoggingFramework framework = new LoggingFramework(lombok.CustomLog.class, logDeclaration);
+ processAnnotation(framework, annotation, annotationNode, annotation.getInstance().topic());
}
}
}
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index ee012d2b..6fa70ff3 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -1450,7 +1450,7 @@ public class JavacHandlerUtil {
java.util.List<TypeName> configuredCopyable = node.getAst().readConfiguration(ConfigurationKeys.COPYABLE_ANNOTATIONS);
if (!annoName.isEmpty()) {
- for (TypeName cn : configuredCopyable) if (typeMatches(cn.toString(), node, anno.annotationType)) return List.of(anno);
+ for (TypeName cn : configuredCopyable) if (cn != null && typeMatches(cn.toString(), node, anno.annotationType)) return List.of(anno);
for (String bn : BASE_COPYABLE_ANNOTATIONS) if (typeMatches(bn, node, anno.annotationType)) return List.of(anno);
}
@@ -1459,7 +1459,7 @@ public class JavacHandlerUtil {
if (child.getKind() == Kind.ANNOTATION) {
JCAnnotation annotation = (JCAnnotation) child.get();
boolean match = false;
- for (TypeName cn : configuredCopyable) if (typeMatches(cn.toString(), node, annotation.annotationType)) {
+ for (TypeName cn : configuredCopyable) if (cn != null && typeMatches(cn.toString(), node, annotation.annotationType)) {
result.append(annotation);
match = true;
break;