diff options
Diffstat (limited to 'src')
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} = <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} = <logDeclaration string>. + * + * 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> + * @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 @Log + * @see lombok.extern.apachecommons.CommonsLog @CommonsLog + * @see lombok.extern.log4j.Log4j @Log4j + * @see lombok.extern.log4j.Log4j2 @Log4j2 + * @see lombok.extern.slf4j.Slf4j @Slf4j + * @see lombok.extern.slf4j.XSlf4j @XSlf4j + * @see lombok.extern.jbosslog.JBossLog @JBossLog + * @see lombok.extern.flogger.Flogger @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.Flu |
