Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Checkstyle linter #2688

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open

Conversation

rmoreliovlabs
Copy link
Contributor

@rmoreliovlabs rmoreliovlabs commented Aug 19, 2024

Add Checkstyle with Google Code Conventions and Spotless for Google Java Code Formatting

depends on powpeg pr: https://github.com/rsksmart/powpeg-node/pull/324/files

Description

This PR introduces Checkstyle 8.45, configured with Google Code Conventions, and adds Spotless to our project for code formatting using the official Google Java Format. Checkstyle will analyze the codebase to enforce coding standards, while Spotless ensures consistent code formatting. This addition aims to improve code quality and maintain consistency for new contributions.

Due to security concerns with the previous unofficial Google Java Formatter plugin by sherter, which was from a less-established source, Spotless was chosen as a more widely used and trusted alternative. Spotless not only integrates Google's official format but also offers better reliability and security for formatting our code.

Highlights:

  • Added Checkstyle 8.45 configured with Google Code Conventions for code quality enforcement
  • Integrated Spotless to use the official Google Java Format for consistent code styling
  • Configured Checkstyle to analyze only newly added code, avoiding disruption of existing code
  • Spotless offers enhanced reliability and security for code formatting compared to previous tools

Motivation and Context

This update is designed to help our project follow the latest best practices and industry standards for Java-based open-source projects. By adding Checkstyle with Google Code Conventions and the Google Java Formatter, we’re making sure that all new code meets high-quality standards and maintains consistent formatting.

Basic Implementation:

  • Checkstyle Version: Added Checkstyle 8.45 to ensure compatibility with Java 8.
  • Configuration: Integrated Google Code Conventions to align with industry standards.
  • Suppressions File: Included a suppressions.xml file to manage specific rule exceptions. This file allows us to suppress certain Checkstyle rules where they might not apply or are too restrictive.

Why Use Spotless with Official Google Java Formatter

I have chosen Spotless with the official Google Java Format over the unofficial sherter plugin due to several reasons:

  • Security: Spotless is a widely used, trusted tool with a well-established reputation, whereas the sherter plugin comes from a less-established source, raising potential security concerns.
  • Reliability: Spotless integrates directly with Google's official formatting standards, ensuring consistent and accurate code formatting.

File Checking Mechanism: The method for filtering files has been updated. Previously, Checkstyle and the Google Formatter relied on the lastModified() timestamp of files, which could lead to inconsistencies. For example, if you modify file A and then undo those changes, the lastModified() timestamp might still indicate that the file was recently changed, causing Checkstyle and the formatter to run on it even though the modifications were reverted.

To address this, we now use Git commands to identify modified, staged, and committed files based on a specific timestamp. This method ensures that Checkstyle and Spotless formatting checks are applied more accurately. For instance, with the new approach, if you revert changes to file A, Git will no longer include it in the list of modified files, so neither Checkstyle nor Spotless will check it unnecessarily. This ensures more precise and reliable code quality and formatting checks.

To run Checkstyle and verify the new code, use the following command:./gradlew clean rskj-core:checkstyleMain
To verify files to format without formatting them, use the following command:./gradlew clean rskj-core:spotlessCheck
To format code, use the following command:./gradlew clean rskj-core:spotlessApply

Example of Suppression:
In suppressions.xml, you can suppress a rule like this:

<suppressions>
    <suppress checks="CheckstyleRuleName" files=".*SomeFile.java"/>
</suppressions>

This example suppresses a specific Checkstyle rule for SomeFile.java. The suppressions file helps tailor the Checkstyle configuration to fit our project needs more precisely.

Example of the Formatting Mechanism:

The file filtering mechanism now uses Git commands to determine which files have been modified, staged, or committed since a specific timestamp. This ensures that only the relevant files are processed, based on actual changes tracked by Git.

Example:

Modified File (/rskj/rskj-core/src/main/java/co/rsk/config/GasLimitConfig.java):

- Before Formatting:

**/**
 * Wraps configuration for Mining, which is usually derived from configuration files.
 */**
public class GasLimitConfig {
    private final int minGasLimit;
    private final long targetGasLimit;
    private final boolean isTargetGasLimitForced;

    public GasLimitConfig(int minGasLimit, long targetGasLimit, boolean isTargetGasLimitForced) {
        this.minGasLimit = minGasLimit;
        this.targetGasLimit = targetGasLimit;
        this.isTargetGasLimitForced = isTargetGasLimitForced;
    }

    public int getMininimum() {
        return minGasLimit;
    }

    public long getTarget() {
        return targetGasLimit;
    }

    public boolean isTargetForced() {
        return isTargetGasLimitForced;
    }
}

- After Formatting:

package co.rsk.config;

**/** Wraps configuration for Mining, which is usually derived from configuration files. */**
public class GasLimitConfig {
    private final int minGasLimit;
    private final long targetGasLimit;
    private final boolean isTargetGasLimitForced;

    public GasLimitConfig(int minGasLimit, long targetGasLimit, boolean isTargetGasLimitForced) {
        this.minGasLimit = minGasLimit;
        this.targetGasLimit = targetGasLimit;
        this.isTargetGasLimitForced = isTargetGasLimitForced;
    }

    public int getMininimum() {
        return minGasLimit;
    }

    public long getTarget() {
        return targetGasLimit;
    }

    public boolean isTargetForced() {
        return isTargetGasLimitForced;
    }
}

And then, if we run Checkstyle, the console might look something like this:

> Task :rskj-core:checkstyleMain
[ant:checkstyle] [WARN] /Users/reynoldmorel/Documents/projects/rskj/rskj-core/src/main/java/co/rsk/config/GasLimitConfig.java:27:5: Missing a Javadoc comment. [MissingJavadocMethod]
Checkstyle rule violations were found. See the report at: file:///Users/reynoldmorel/Documents/projects/rskj/rskj-core/build/reports/checkstyle/main.html
Checkstyle files with violations: 1
Checkstyle violations by severity: [warning:1]

  • Other information:

fed:updating_dependencies_for_spotless

@rmoreliovlabs rmoreliovlabs marked this pull request as ready for review August 21, 2024 02:24
@rmoreliovlabs rmoreliovlabs force-pushed the add-linter-and-formatter branch 7 times, most recently from ea6e830 to 46c3fec Compare September 5, 2024 17:46
Copy link
Contributor

@fmacleal fmacleal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job, the spotless addition seems a very nice one. I think that these tasks will be very useful to make the code follow a pattern. 👏

I have a few comments regarding the date, once we clear that out, I will approve.

rskj-core/build.gradle Outdated Show resolved Hide resolved
rskj-core/build.gradle Outdated Show resolved Hide resolved
rskj-core/build.gradle Outdated Show resolved Hide resolved
rskj-core/build.gradle Show resolved Hide resolved
@apancorb
Copy link
Contributor

apancorb commented Sep 6, 2024

Hey guys, a couple of months ago I worked on something similar. Leaving PR here so you can check it out. This is a great integration!

import java.nio.file.Paths

// Define static timestamp
def staticTimestamp = '2024-09-03T02:17:00'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also the option to use ratchetFrom, which only formats from a given git tag

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the suggestion! I considered using ratchetFrom to format only changes from a specific git tag. However, the last tag in the repository is from July 10, which is quite a while ago. Using ratchetFrom would include all changes made since that tag, which would affect files modified after that date—something we want to avoid in this case

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks! Do you think it makes sense to switch to ratchetFrom once a new git tag is released?

@rmoreliovlabs rmoreliovlabs force-pushed the add-linter-and-formatter branch 3 times, most recently from 5f73a86 to 50e8d7e Compare September 6, 2024 20:14
@rmoreliovlabs rmoreliovlabs force-pushed the add-linter-and-formatter branch 15 times, most recently from f650cee to 90b67b5 Compare September 27, 2024 15:27
@rmoreliovlabs rmoreliovlabs force-pushed the add-linter-and-formatter branch 12 times, most recently from 63c0bc3 to 218c605 Compare October 15, 2024 14:11
Copy link

sonarcloud bot commented Oct 17, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants