Often it is desirable to avoid a specific class without banning its entire package. java.util.Date
is a good example of this, as most of its methods are deprecated, but rejecting java.util
would leave the user unable to reference common classes like java.util.List
.
As of Checkstyle 7.8, we can fail the build when unwanted classes are imported through Gradle’s built-in checkstyle plugin. Setup is different for solo-project and multi-project builds. See the following links for a git diff of what is needed to enable this behavior:
Context
If I have a project that is committed to using java.time
, using java.util.Date
will only ever be an accident that can cause bugs and create confusion in the future. Gradle’s checkstyle plugin and the IllegalImport rule can help me formalize this intention as part of my build.
Solo-Project Setup
We’ll start with a simple example project that has imported a method from our unwanted package: sghill/fail-unwanted-class-imports.
Apply the plugin:
apply plugin: 'checkstyle'
The bundled version of the plugin is not recent enough, so we’ll need to upgrade that by specifying the dependency of at least 7.8 on the checkstyle
configuration:
checkstyle {
toolVersion '7.8.2'
}
The plugin is looking for configuration in ${project.projectDir}/config/checkstyle/checkstyle.xml
by default.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="TreeWalker">
<module name="IllegalImport">
<property name="illegalClasses" value="java.util.Date"/>
</module>
</module>
</module>
Now running ./gradlew build
fails our new :checkstyleTest
task:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':checkstyleTest'.
> Checkstyle rule violations were found. See the report at: file:///Users/sghill/code/build-well/fail-unwanted-class-imports/build/reports/checkstyle/test.html
Multi-Project Setup
We’re going to reuse the solo-project configuration in the same location for our multi-project setup. The default checkstyle file path is relative to the project
instead of the rootProject
, so we’ll need to do some task configuration. This is the way to share a checkstyle configuration:
allprojects {
apply plugin: 'checkstyle'
tasks.withType(Checkstyle) {
def path = "${rootProject.projectDir}/config/checkstyle/checkstyle.xml"
config resources.text.fromFile(path)
}
}
Now running ./gradlew build
gives us an errors from foundation
:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':foundation:checkstyleMain'.
> Checkstyle rule violations were found. See the report at: file:///Users/sghill/code/build-well/fail-unwanted-classes/foundation/build/reports/checkstyle/main.html
Versions
This example has been tested against the following versions:
Date | Gradle | Checkstyle | Solo-Project | Multi-Project |
---|---|---|---|---|
2017-07-01 | 4.0 | 7.8.2 | output | output |
2017-07-01 | 3.5.1 | 7.8.2 | output | output |
2017-07-01 | 3.4.1 | 7.8.2 | output | output |
2017-07-01 | 3.3 | 7.8.2 | output | output |