SonarQube и lombok

Hello everyone. Can you please advise if SonarQube works correctly with Lombok?
When using it with the @Slf4j annotation, there are no issues detected, but when we stopped using Lombok, it started highlighting logging problems that were not highlighted before. Perhaps additional configuration is needed, or SonarQube does not support Lombok/some of its annotations?
Version of SQ: 9.9.1.69595, Enterprise Edition

Hi,

Unfortunately, I don’t think there’s a boolean answer to this question. I believe Lombok compatibility is added at the rule level, and probably also annotation by annotation.

Can you be specific about the rules and annotations you’re wondering about?

 
Thx,
Ann

Did you solve this question ? I’m having the same problem as you. I tried install Lombok plugins for sonar but not worked.

Hi Ann, I’m having the same problem as Vyacheslav, my customer rule which pasted can’t recognize Log Object created Slf4j annotation. Does sonar support for Lombok annotation ? and Did my rule have some problem for scanning Log object created by Lombok annotation?
A reply would be appreciated.

package org.sonar.samples.java.checks;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.check.Rule;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.semantic.SymbolMetadata;
import org.sonar.plugins.java.api.tree.*;

import java.util.Arrays;
import java.util.List;

/**
 * @Auther ZellousCheung
 * @Date 2024/9/3
 */
@Rule(key = "NoLoggingInLoops2")
public class NoLoggingInLoopsRule2 extends IssuableSubscriptionVisitor {

   
    private static final Logger log = LoggerFactory.getLogger(NoLoggingInLoopsRule2.class);

   
    List<String> logMethod = Arrays.asList("log", "debug", "info", "warn","warning", "error", "trace");

   
    @Override
    public List<Tree.Kind> nodesToVisit() {
        return Arrays.asList(Tree.Kind.FOR_STATEMENT, Tree.Kind.WHILE_STATEMENT, Tree.Kind.DO_STATEMENT, Tree.Kind.CLASS);
    }

    @Override
    public void visitNode(Tree tree) {
        // Determine whether it is a class declaration
        if (tree.is(Tree.Kind.CLASS)) {
            ClassTree classTree = (ClassTree) tree;
            SymbolMetadata metadata = classTree.symbol().metadata();

            //
            if (metadata.isAnnotatedWith("lombok.extern.slf4j.Slf4j")) {
                log.info("scan @Slf4j annotation");
            }
        }

        // 判断是否为 For、While 或 Do-While 循环
        if (tree.is(Tree.Kind.FOR_STATEMENT)) {
            log.info("scan for loop");
            checkForLogging(((ForStatementTree) tree).statement());
        } else if (tree.is(Tree.Kind.WHILE_STATEMENT)) {
            log.info("scan while loop");
            checkForLogging(((WhileStatementTree) tree).statement());
        } else if (tree.is(Tree.Kind.DO_STATEMENT)) {
            log.info("scan do-while loop");
            checkForLogging(((DoWhileStatementTree) tree).statement());
        }
    }

    // Check if there is a log print inside the circulation body
    private void checkForLogging(Tree loopBody) {
        if (loopBody != null) {
            loopBody.accept(new BaseTreeVisitor() {
                @Override
                public void visitMethodInvocation(MethodInvocationTree methodInvocationTree) {
                    // 检查日志打印方法
                    if (isLoggingMethod(methodInvocationTree)) {
                        reportIssue(methodInvocationTree, "Logging inside loops is not allowed");
                    }
                    super.visitMethodInvocation(methodInvocationTree);
                }
            });
        }
    }

    //
    private boolean isLoggingMethod(MethodInvocationTree methodInvocationTree) {
        Symbol symbol = methodInvocationTree.symbol();
        if (symbol == null || symbol.owner() == null || symbol.owner().type() == null) {
            return false;
        }

        String methodName = symbol.name();
        String fullyQualifiedClassName = symbol.owner().type().fullyQualifiedName();

        log.info("class name:" + fullyQualifiedClassName);
        log.info("method name:" + methodName);

        // 如果类使用了 @Slf4j 注解,Lombok 会生成一个 log 对象,使用该对象进行日志打印
        if (fullyQualifiedClassName.equals("NoLoggingInLoops") && logMethod.contains(methodName)) {
            return true;
        }

        // Check whether the log printing method is common
        return logMethod.contains(methodName) &&
                (fullyQualifiedClassName.startsWith("org.slf4j.Logger") ||
                        fullyQualifiedClassName.startsWith("lombok.extern.slf4j.Slf4j") ||
                        fullyQualifiedClassName.startsWith("org.apache.logging") ||
                        fullyQualifiedClassName.startsWith("java.util.logging"));
    }
}

Hi @SugarZeal328,

You’ve resurrected a 4-month-old post to add a mostly unrelated question related to writing custom rules. Per the FAQ, please don’t do that. Please create a new thread with all your details.

 
Ann