Sonar can't see compiled lombok code

Must-share information (formatted with Markdown):

  • which versions are you using (SonarQube, Scanner, Plugin, and any relevant extension)

id 'org.sonarqube' version '4.4.1.3373'
SonarLint 10.2.1.77304

  • how is SonarQube deployed: zip, Docker, Helm

Docker on my local using this docker-compose.yml

version: '3'

services:
  sonarqube:
    image: sonarqube
    ports:
      - "9000:9000"
    environment:
      - SONARQUBE_JDBC_URL=jdbc:h2:tcp://sonarqube-db:9092/sonar
    networks:
      - sonarnet
    container_name: sonarqube
    restart: unless-stopped

networks:
  sonarnet:
    driver: bridge
  • what are you trying to achieve

I’m trying to make Sonar see private access modifiers, which I add using @FieldDefaults(level = PRIVATE) lombok annotation on my java class. When I run ./gradlew build clean sonar it anyway highlights it as maintainability problem in results -
Fields in a “Serializable” class should either be transient or serializable[java:S1948]
To fix this it recommends to ‘Make “myFieldName” private or transient.’, however in compiled .class file for this java class I see that this field is private.

  • what have you tried so far to achieve this

After searching a lot I’ve managed to specify sonar property “sonar.java.libraries” in my build.gradle file to point to the location of my lombok.jar file in .gradle/caches dir.
Final property looks like this:
property "sonar.java.libraries", System.getenv().get("GRADLE_USER_HOME") + "/caches/**/**/**/lombok/**/**/*.jar"
After this it stopped highlighting some problems. But still for some classes which implement Serializable interface and have List of another Serializable object as a field, it highlights same maintainability problem.
I’ve also tried specifying property "sonar.java.binaries" property to point to by build/classes folder (which I suppose the value for sonar in gradle by default) and I debugged it with different pathes, even with absolute path, but that didn’t help. However, and interesting fact, is that when I configured my SonarLint IDEA plugin and specified sonar.java.binaries & sonar.java.libraries properties in a plugin config it became behaving correctly, it stopped highlighting this maintainability problem. Just in case, after this configuration of plugin it still shows other real problems in code, so that didn’t get broken with new properties.
I spent much time to achieve same result which I achieved for SonarLint plugin but for SonarQube server which I use with ./gradlew but no luck now.

Providing classes samples for wider picture:

@Data
@Builder
@FieldDefaults(level = PRIVATE)
public class Window implements Serializable {
    String name;
    List<RadioButtonEntry> buttons;
}

and RadioButtonEntry class code:

@Data
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = PRIVATE)
public class RadioButtonEntry implements Serializable {
    String label;
}

and the screenshot of results for this code from Sonar:


Hi,

Welcome to the community!

I see that you’re using the latest version of SonarLint for IntelliJ, but it’s not clear what version of SonarQube you’re using. Can you check the page footer, please?

It seems that with full/proper configuration, the False Positive you’re reporting went away in SonarLint. So it’s not clear to me what remains to handle. Is this now a question of getting your SonarQube analysis to properly recognize the Lombok annotations?

 
Thx,
Ann

Hi Ann! thanks for your reply
SonarQube version which I use - Community Edition Version 10.2.1 (build 78527)

So yeah, the question is how to get SonarQube analysis to properly recognize the Lombok annotations. In our project we use SonarLint for real-time development only, but on CI we use SonarQube which now fails for a correct code because of this problem.

Hi,

What’s your build technology? You should be able to use the corresponding SonarScanner to automatically pick up the binaries and libraries from the build environment.

 
Ann

Our porject is a Java + Spring Boot + Gradle project. And yes we use SonarScanner, but still for some reason it has this problem.

Our sonar-related configs from build.gradle:

plugins {
    id 'org.sonarqube' version '4.4.1.3373'
}

sonar {
    properties {
        property "sonar.projectVersion", "1.0"
        property "sonar.projectKey", "PROJECT-KEY"
        property "sonar.projectName", "Project Name"
        property "sonar.login", 'admin'
        property "sonar.password", 'admin'
    }
}

subprojects {
    sonar {
        properties {
            property "sonar.coverage.exclusions", "**/cucumber/**,**/model/**,**/config/**,**/*Application.java,**/*Configuration.java,**/*Response.java,**/*Request.java,**/*Model.java,**/*Config.java"
            property "sonar.sources", "src/main/java"
            property "sonar.exclusions", "src/test/java/**/*,**/cucumber/**"
            property "sonar.cpd.exclusions", "**/model/**,**/config/**"
            property "sonar.java.libraries", System.getenv().get("GRADLE_USER_HOME") + "/caches/**/**/org.projectlombok/lombok/**/**/lombok-*.jar"
            property "sonar.java.binaries", "${buildDir}/classes/java/main"
            property "sonar.coverage.jacoco.xmlReportPaths", "${buildDir}/reports/jacoco/test/jacocoTestReport.xml"
            property "sonar.sourceEncoding", "iso-8859-1"
            property "sonar.gradle.skipCompile", "false"
        }
    }
}

And so I assume this config is a proper complete config which should be sufficient for SonarScanner to work, but still it has that described problem
Hope this helps!

Hi,

You shouldn’t need to specify these properties:

They should be picked up automatically from Gradle. Can you try it without them?

 
Ann

Just tried without these properties, still same issue.
For reference, "sonar.java.libraries" property got added to point to the lombok jar file by a recommendation I found somewhere in the internet to solve this problem, but yeah, that didn’t help also.

Hi,

How is Lombok being used/included when you compile?

 
Ann

We mainly just use annotations provided by lombok, for setters/constructors/builders etc. And so we also used @FieldDefaults(level = PRIVATE)
if that’s what you’re asking about

Hi,

In order to use Lombok annotations, the Lombok jar/dependency has to be available when you compile, right?

 
Ann

Got your question, thanks for clarification. We get lombok dependency added in one of dependencies which we add to our project. Basically we have:

    compileOnly("org.projectlombok:lombok:${lombokVersion}")
    testCompileOnly("org.projectlombok:lombok:${lombokVersion}")
    annotationProcessor("org.projectlombok:lombok:${lombokVersion}")
    testAnnotationProcessor("org.projectlombok:lombok:${lombokVersion}")

and lombokVersion=1.18.26

Hi,

Thanks for that detail. I’ve flagged this for more expert eyes.

 
Ann

1 Like

Hi Vladyslav, unfortunately the @FieldDefaults(level = PRIVATE) annotation is not supported by the rule S1948. So I updated this SONARJAVA-4536 existing ticket about @Value to also fix the problem with @FieldDefaults. Thanks for your contribution and have a nice day.

2 Likes

Thank you for your response! In such case we’ll wait for the SONARJAVA-4536 to be completed but for now we’ll just put private explicitly on all fields
Have a nice day!