Custom log declaration

This commit is contained in:
Adam Juraszek
2019-05-14 18:48:01 +02:00
parent 399c516bd3
commit bb66465751
24 changed files with 647 additions and 201 deletions
+31
View File
@@ -25,6 +25,7 @@ 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;
@@ -428,6 +429,36 @@ 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;String: logDeclaration&gt;.
*
* The log declaration must follow the pattern:
* <br>
* {@code [LoggerType ]LoggerFactoryType.loggerFactoryMethod(loggerFactoryMethodParams)[(loggerFactoryMethodParams)]}
* <br>
* It consists of:
* <ul>
* <li>Optional fully qualified logger type, e.g. {@code my.cool.Logger}, followed by space. If not specified, it defaults to the logger factory type.
* <li>Fully qualified logger factory type, e.g. {@code my.cool.LoggerFactory}, followed by dot.
* <li>Factory method, e.g. {@code createLogger}. The method must be defined on the logger factory type and must be static.
* <li>At least one definition of factory method parameters, e.g. {@code ()} or {@code (TOPIC,TYPE)}. The format is comma-separated list of parameters wrapped in parentheses.
* The allowed parameters are: {@code TYPE} | {@code NAME} | {@code TOPIC} | {@code NULL}.
* There can be at most one parameter definition with {@code TOPIC} and at most one without {@code TOPIC}.
* </ul>
*
* If 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 #####
/**
+70
View File
@@ -0,0 +1,70 @@
/*
* 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.
* <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 will lead to errors.
*
* 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 {
/** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
@@ -0,0 +1,179 @@
/*
* Copyright (C) 2013 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 are too many parameters with TOPIC: " + parametersWithTopic + " and " + parameters);
}
parametersWithTopic = parameters;
} else {
if (parametersWithoutTopic != null) {
throw new IllegalArgumentException("There are too many parameters without TOPIC: " + parametersWithoutTopic + " and " + parameters);
}
parametersWithoutTopic = parameters;
}
}
if (parametersWithoutTopic == null && parametersWithTopic == null) {
// shouldn't happen the pattern does not allow it
throw new IllegalArgumentException("No logger factory method parameters specified.");
}
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-declartation";
}
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;
}
}
@@ -0,0 +1,77 @@
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;
}
}
+88 -119
View File
@@ -21,25 +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.core.configuration.IdentifierName;
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;
@@ -48,6 +43,16 @@ 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;
import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
public class HandleLog {
private static final IdentifierName LOG = IdentifierName.valueOf("log");
@@ -82,8 +87,12 @@ public class HandleLog {
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 to set a topic.");
}
ClassLiteralAccess loggingType = selfType(owner, source);
FieldDeclaration fieldDeclaration = createField(framework, source, loggingType, logFieldName.getName(), useStatic, loggerTopic);
fieldDeclaration.traverse(new SetGeneratedByVisitor(source), typeDecl.staticInitializerScope);
// TODO temporary workaround for issue 217. http://code.google.com/p/projectlombok/issues/detail?id=217
@@ -120,24 +129,17 @@ public class HandleLog {
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();
factoryMethodCall.receiver = createNameReference(logDeclaration.getLoggerFactoryType().getName(), source);
factoryMethodCall.selector = logDeclaration.getLoggerFactoryMethod().getCharArray();
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.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;
@@ -151,22 +153,61 @@ public class HandleLog {
int pS = source.sourceStart, pE = source.sourceEnd;
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.
@@ -256,92 +297,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 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 framework = new LoggingFramework(lombok.CustomLog.class, logDeclaration);
processAnnotation(framework, annotation, source, annotationNode, annotation.getInstance().topic());
}
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;
}
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;
};
}
}
+1
View File
@@ -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)
+1
View File
@@ -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)
+1
View File
@@ -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)
+2 -1
View File
@@ -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 {
+1
View File
@@ -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)
+1
View File
@@ -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)
+1
View File
@@ -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)
+1
View File
@@ -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)
+58 -79
View File
@@ -22,16 +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;
@@ -65,13 +68,18 @@ public class HandleLog {
boolean useStatic = !Boolean.FALSE.equals(annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_IS_STATIC));
if ((((JCClassDecl)typeNode.get()).mods.flags & Flags.INTERFACE) != 0) {
annotationNode.addError("@Log is legal only on classes and enums.");
annotationNode.addError(framework.getAnnotationAsString() + " is legal only on classes and enums.");
return;
}
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 to set a topic.");
}
JCFieldAccess loggingType = selfType(typeNode);
createField(framework, typeNode, loggingType, annotationNode.get(), logFieldName.getName(), useStatic, loggerTopic);
@@ -91,20 +99,14 @@ 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)),
@@ -114,6 +116,34 @@ public class HandleLog {
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.
*/
@@ -202,71 +232,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());
}
}
}
@@ -0,0 +1,13 @@
class LoggerCustomLog {
@java.lang.SuppressWarnings("all")
private static final MyLogger log = MyLoggerFactory.create(LoggerCustomLog.class);
}
class MyLoggerFactory {
static MyLogger create(Class<?> clazz) {
return null;
}
}
class MyLogger {
}
@@ -0,0 +1,14 @@
package before;
class LoggerCustomLog {
@java.lang.SuppressWarnings("all")
private static final before.MyLogger log = before.MyLoggerFactory.create(LoggerCustomLog.class);
}
class MyLoggerFactory {
static MyLogger create(Class<?> clazz) {
return null;
}
}
class MyLogger {
}
@@ -0,0 +1,10 @@
class LoggerCustomLog {
@java.lang.SuppressWarnings("all")
private static final MyLoggerFactory log = MyLoggerFactory.create(LoggerCustomLog.class.getName(), "t", null, LoggerCustomLog.class, "t");
}
class MyLoggerFactory {
static MyLoggerFactory create(String name, String t1, Object o, Class<?> clazz, String t2) {
return null;
}
}
@@ -0,0 +1,21 @@
@lombok.CustomLog class LoggerCustomLog {
private static final MyLogger log = MyLoggerFactory.create(LoggerCustomLog.class);
<clinit>() {
}
LoggerCustomLog() {
super();
}
}
class MyLoggerFactory {
MyLoggerFactory() {
super();
}
static MyLogger create(Class<?> clazz) {
return null;
}
}
class MyLogger {
MyLogger() {
super();
}
}
@@ -0,0 +1,22 @@
package before;
@lombok.CustomLog class LoggerCustomLog {
private static final before.MyLogger log = before.MyLoggerFactory.create(LoggerCustomLog.class);
<clinit>() {
}
LoggerCustomLog() {
super();
}
}
class MyLoggerFactory {
MyLoggerFactory() {
super();
}
static MyLogger create(Class<?> clazz) {
return null;
}
}
class MyLogger {
MyLogger() {
super();
}
}
@@ -0,0 +1,16 @@
@lombok.CustomLog(topic = "t") class LoggerCustomLog {
private static final MyLoggerFactory log = MyLoggerFactory.create(LoggerCustomLog.class.getName(), "t", null, LoggerCustomLog.class, "t");
<clinit>() {
}
LoggerCustomLog() {
super();
}
}
class MyLoggerFactory {
MyLoggerFactory() {
super();
}
static MyLoggerFactory create(String name, String t1, Object o, Class<?> clazz, String t2) {
return null;
}
}
@@ -0,0 +1,13 @@
//CONF: lombok.log.custom.declaration = MyLogger MyLoggerFactory.create(TYPE)
@lombok.CustomLog
class LoggerCustomLog {
}
class MyLoggerFactory {
static MyLogger create(Class<?> clazz) {
return null;
}
}
class MyLogger {
}
@@ -0,0 +1,14 @@
//CONF: lombok.log.custom.declaration = before.MyLogger before.MyLoggerFactory.create(TYPE)
package before;
@lombok.CustomLog
class LoggerCustomLog {
}
class MyLoggerFactory {
static MyLogger create(Class<?> clazz) {
return null;
}
}
class MyLogger {
}
@@ -0,0 +1,10 @@
//CONF: lombok.log.custom.declaration = MyLoggerFactory.create(NAME,TOPIC,NULL,TYPE,TOPIC)
@lombok.CustomLog(topic="t")
class LoggerCustomLog {
}
class MyLoggerFactory {
static MyLoggerFactory create(String name, String t1, Object o, Class<?> clazz, String t2) {
return null;
}
}
@@ -1,2 +1,2 @@
1 @Log is legal only on classes and enums.
4 @Log is legal only on classes and enums.
1 @Slf4j is legal only on classes and enums.
4 @Slf4j is legal only on classes and enums.