lombok.eclipse.handlers.HandleLog Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2010-2021 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.eclipse.handlers;
import static lombok.core.handlers.HandlerUtil.handleFlagUsage;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.lang.reflect.Modifier;
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.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
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;
import lombok.spi.Provides;
public class HandleLog {
private static final IdentifierName LOG = IdentifierName.valueOf("log");
private HandleLog() {
throw new UnsupportedOperationException();
}
public static void processAnnotation(LoggingFramework framework, AnnotationValues extends java.lang.annotation.Annotation> annotation, Annotation source, EclipseNode annotationNode) {
EclipseNode owner = annotationNode.up();
switch (owner.getKind()) {
case TYPE:
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));
TypeDeclaration typeDecl = null;
if (owner.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) owner.get();
int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
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.getName(), owner) != MemberExistsResult.NOT_EXISTS) {
annotationNode.addWarning("Field '" + logFieldName + "' already exists.");
return;
}
if (isRecord(owner) && !useStatic) {
annotationNode.addError("Logger fields must be static in records.");
return;
}
if (useStatic && !isStaticAllowed(owner)) {
annotationNode.addError(framework.getAnnotationAsString() + " is not supported on non-static nested classes.");
return;
}
Object valueGuess = annotation.getValueGuess("topic");
Expression loggerTopic = (Expression) annotation.getActualExpression("topic");
if (valueGuess instanceof String && ((String) valueGuess).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 = new StringLiteral(new char[]{}, 0, 0, 0);
}
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 290. https://github.com/projectlombok/lombok/issues/290
// injectFieldSuppressWarnings(owner, fieldDeclaration);
injectField(owner, fieldDeclaration);
owner.rebuild();
break;
default:
break;
}
}
public static ClassLiteralAccess selfType(EclipseNode type, Annotation source) {
int pS = source.sourceStart, pE = source.sourceEnd;
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);
return result;
}
private static FieldDeclaration createField(LoggingFramework framework, Annotation source, ClassLiteralAccess loggingType, String logFieldName, boolean useStatic, Expression loggerTopic) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
// private static final log = ();
FieldDeclaration fieldDecl = new FieldDeclaration(logFieldName.toCharArray(), 0, -1);
setGeneratedBy(fieldDecl, source);
fieldDecl.declarationSourceEnd = -1;
fieldDecl.modifiers = Modifier.PRIVATE | (useStatic ? Modifier.STATIC : 0) | Modifier.FINAL;
LogDeclaration logDeclaration = framework.getDeclaration();
fieldDecl.type = createTypeReference(logDeclaration.getLoggerType().getName(), source);
MessageSend factoryMethodCall = new MessageSend();
setGeneratedBy(factoryMethodCall, source);
factoryMethodCall.receiver = createNameReference(logDeclaration.getLoggerFactoryType().getName(), source);
factoryMethodCall.selector = logDeclaration.getLoggerFactoryMethod().getCharArray();
List 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;
fieldDecl.initialization = factoryMethodCall;
return fieldDecl;
}
private static final Expression[] createFactoryParameters(ClassLiteralAccess loggingType, Annotation source, List parameters, Expression 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] = EclipseHandlerUtil.copyAnnotationMemberValue(loggerTopic);
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.
*/
@Provides
public static class HandleCommonsLog extends EclipseAnnotationHandler {
@Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_COMMONS_FLAG_USAGE, "@apachecommons.CommonsLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.COMMONS, annotation, source, annotationNode);
}
}
/**
* Handles the {@link lombok.extern.java.Log} annotation for Eclipse.
*/
@Provides
public static class HandleJulLog extends EclipseAnnotationHandler {
@Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JUL_FLAG_USAGE, "@java.Log", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.JUL, annotation, source, annotationNode);
}
}
/**
* Handles the {@link lombok.extern.log4j.Log4j} annotation for Eclipse.
*/
@Provides
public static class HandleLog4jLog extends EclipseAnnotationHandler {
@Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J_FLAG_USAGE, "@Log4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.LOG4J, annotation, source, annotationNode);
}
}
/**
* Handles the {@link lombok.extern.log4j.Log4j2} annotation for Eclipse.
*/
@Provides
public static class HandleLog4j2Log extends EclipseAnnotationHandler {
@Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J2_FLAG_USAGE, "@Log4j2", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.LOG4J2, annotation, source, annotationNode);
}
}
/**
* Handles the {@link lombok.extern.slf4j.Slf4j} annotation for Eclipse.
*/
@Provides
public static class HandleSlf4jLog extends EclipseAnnotationHandler {
@Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_SLF4J_FLAG_USAGE, "@Slf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.SLF4J, annotation, source, annotationNode);
}
}
/**
* Handles the {@link lombok.extern.slf4j.XSlf4j} annotation for Eclipse.
*/
@Provides
public static class HandleXSlf4jLog extends EclipseAnnotationHandler {
@Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_XSLF4J_FLAG_USAGE, "@XSlf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.XSLF4J, annotation, source, annotationNode);
}
}
/**
* Handles the {@link lombok.extern.jbosslog.JBossLog} annotation for Eclipse.
*/
@Provides
public static class HandleJBossLog extends EclipseAnnotationHandler {
@Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JBOSSLOG_FLAG_USAGE, "@JBossLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.JBOSSLOG, annotation, source, annotationNode);
}
}
/**
* Handles the {@link lombok.extern.flogger.Flogger} annotation for Eclipse.
*/
@Provides
public static class HandleFloggerLog extends EclipseAnnotationHandler {
@Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_FLOGGER_FLAG_USAGE, "@Flogger", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.FLOGGER, annotation, source, annotationNode);
}
}
/**
* Handles the {@link lombok.CustomLog} annotation for Eclipse.
*/
@Provides
public static class HandleCustomLog extends EclipseAnnotationHandler {
@Override public void handle(AnnotationValues 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 lombok.log.custom.declaration in lombok.config.");
return;
}
LoggingFramework framework = new LoggingFramework(lombok.CustomLog.class, logDeclaration);
processAnnotation(framework, annotation, source, annotationNode);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy