Automatically fix Checkstyle violations
Most programmers agree that having consistent formatting across a code base makes it easier to work with. Tools like Checkstyle provide automated enforcement of these policies. But it's never fun to have your workflow interrupted by complaints about formatting. This guide will show you how to configure OpenRewrite to automate the remediation of Checkstyle policy violations.
Example Configuration
How you configure Checkstyle integration depends on whether or not your build also applies a Checkstyle plugin. For Gradle builds this means the built-in plugin named Checkstyle Plugin. For Maven builds this means maven-checkstyle-plugin.
With Checkstyle Plugin
If your build uses either the Gradle or Maven checkstyle plugins, then good news, the OpenRewrite build plugins will detect that and automatically match their configuration. All that remains is to activate the Code cleanup recipe:
- Maven
- Gradle
<project>
<build>
<plugins>
<plugin>
<groupId>org.openrewrite.maven</groupId>
<artifactId>rewrite-maven-plugin</artifactId>
<version>5.47.0</version>
<configuration>
<activeRecipes>
<recipe>org.openrewrite.staticanalysis.CodeCleanup</recipe>
</activeRecipes>
</configuration>
<dependencies>
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-static-analysis</artifactId>
<version>1.22.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
</configuration>
</plugin>
</plugins>
</build>
</project>
plugins {
id("java")
id("checkstyle")
id("org.openrewrite.rewrite") version("6.28.3")
}
rewrite {
activeRecipe("org.openrewrite.staticanalysis.CodeCleanup")
}
repositories {
mavenCentral() // rewrite is published to Maven Central
}
dependencies {
rewrite("org.openrewrite.recipe:rewrite-static-analysis:latest.release")
}
At this point, you're ready to fix Checkstyle policy violations by running mvn rewrite:run
or gradlew rewriteRun
.
OpenRewrite can be configured to use different checkstyle policies than your Checkstyle plugin. Follow the "No Checkstyle Plugin" instructions to override the location of the checkstyle configuration file.
No Checkstyle Plugin
If your build does not use either of the Gradle or Maven Checkstyle plugins, you can still configure the rewrite build plugins to use a checkstyle xml configuration file:
- Gradle
- Maven
plugins {
id("java")
id("org.openrewrite.rewrite") version("6.28.3")
}
rewrite {
activeRecipe("org.openrewrite.staticanalysis.CodeCleanup")
checkstyleConfigFile = file("checkstyle.xml")
}
repositories {
mavenCentral() // rewrite is published to Maven Central
}
dependencies {
rewrite("org.openrewrite.recipe:rewrite-static-analysis:latest.release")
}
<project>
<build>
<plugins>
<plugin>
<groupId>org.openrewrite.maven</groupId>
<artifactId>rewrite-maven-plugin</artifactId>
<version>5.47.0</version>
<configuration>
<activeRecipes>
<recipe>org.openrewrite.staticanalysis.CodeCleanup</recipe>
</activeRecipes>
<checkstyleConfigFile>checkstyle.xml</checkstyleConfigFile>
</configuration>
<dependencies>
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-static-analysis</artifactId>
<version>1.22.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
At this point, you're ready to fix Checkstyle policy violations by running mvn rewrite:run
or gradlew rewriteRun
.
Applying Refactors before Checkstyle
Depending on exactly how your build is configured, it might run Checkstyle before OpenRewrite. So the Checkstyle tool might report violations that would be fixed if your build were to run OpenRewrite first.
With this configuration, rewrite refactoring will be run as part of any build that runs checkstyle.
Gradle
In Gradle, Task.dependsOn() can be used to ensure that invoking one task always causes another task to run first. That means making all tasks of type org.gradle.api.plugins.quality.Checkstyle
depend on the rewriteRun
task provided by the OpenRewrite plugin.
plugins {
id("java")
id("checkstyle")
id("org.openrewrite.rewrite") version("6.28.3")
}
rewrite {
activeRecipe("org.openrewrite.staticanalysis.CodeCleanup")
checkstyleConfigFile = file("checkstyle.xml")
}
repositories {
mavenCentral() // rewrite is published to Maven Central
}
dependencies {
rewrite("org.openrewrite.recipe:rewrite-static-analysis:latest.release")
}
// In older versions of gradle, use tasks.get() instead of tasks.named()
def rewriteRunTask = tasks.named("rewriteRun")
// In a kotlin build script, use tasks.withType<Checkstyle>()
tasks.withType(Checkstyle) {
dependsOn(rewriteRunTask)
}
Maven
In Maven, the ordering of goals depends first on which phase of the Build Lifecycle they are declared in, then secondarily by the order in which plugins are declared. This means that the rewrite-maven-plugin
should be declared above the maven-checkstyle-plugin
in your pom.xml
and configured to execute within the same phase as you configure checkstyle to run its "check" goal.
<project>
<build>
<plugins>
<plugin>
<groupId>org.openrewrite.maven</groupId>
<artifactId>rewrite-maven-plugin</artifactId>
<version>5.47.0</version>
<configuration>
<activeRecipes>
<recipe>org.openrewrite.staticanalysis.CodeCleanup</recipe>
</activeRecipes>
</configuration>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-static-analysis</artifactId>
<version>1.22.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
</configuration>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Known Limitations
We don't have OpenRewrite recipes implemented for all publicly available policies. If you find a checkstyle policy violation you'd like automated, visit the rewrite repository and file an issue (or help out the community by contributing one yourself).
Checkstyle configuration loading only informs the behavior of recipes, not which recipes are active. Regardless of the presence or non-presence of Checkstyle configuration, OpenRewrite will never apply any refactoring you do not explicitly activate.
See how this recipe works across multiple open-source repositories
Run this recipe on OSS repos at scale with the Moderne SaaS.
The community edition of the Moderne platform enables you to easily run recipes across thousands of open-source repositories.
Please contact Moderne for more information about safely running the recipes on your own codebase in a private SaaS.