【Java】Code Formatting with spotless
Created:
目次
Introduction
I tried spotless, a source code formatting tool. In this article, I mainly use it as a Gradle plugin and focus on formatting Java code, but spotless can also be used with Maven and supports formatting for many other languages.
Advantages of spotless Compared to Checkstyle
When it comes to Java code style tools, Checkstyle is a well-known option. However, Checkstyle basically only detects formatting violations and does not automatically fix them.
Many formatting tools for other languages automatically fix issues wherever possible, so compared to those tools, Checkstyle often feels inconvenient. spotless, on the other hand, not only detects issues but also automatically fixes them, which makes it much more convenient.
Although spotless is most commonly used for Java formatting, it actually supports a wide variety of file types. For example, it can also format YAML files. In some projects that use Checkstyle, Java code is strictly formatted, while YAML configuration files are messy and inconsistent. With spotless, you can format all of these files together in a unified way.
Basic Usage
The basic usage follows the official documentation. Here, I introduce how to use spotless as a Gradle plugin.
First, add the Gradle plugin dependency (as of July 12, 2024, the latest version is 7.0.0.BETA1) and configure formatting rules inside the spotless block.
As you can see in the example below, this configuration formats both Java and YAML files.
For the full list of available options, please refer to the official documentation.
plugins {
id("com.diffplug.gradle.spotless") version "7.0.0.BETA1"
}
spotless {
java {
// Format using Google Java Format.
// The argument specifies the Google Java Format version.
googleJavaFormat('1.22.0').aosp().reflowLongStrings()
formatAnnotations()
}
yaml {
target '**/*.yaml'
jackson()
}
}With this configuration, Gradle adds tasks such as spotlessApply (apply formatting) and spotlessCheck (check formatting without modifying files).
You can format the source code by running ./gradlew spotlessApply.
Since spotless also hooks into the check task, running ./gradlew check is sufficient for CI environments.
Investigated Topics
Although the documentation provides many configuration examples, it was not always clear what each option actually does. I investigated several of them in more detail.
Tab Indentation
Google Java Style specifies 2-space indentation (Block indentation: +2 spaces).
This is somewhat distinctive, and there may be cases where you want to use Google Java Format but change only this rule. In that case, you can add aosp().
AOSP stands for Android Open Source Project, and its style uses 4-space indentation.
One might question whether it makes sense to apply an Android style to ordinary Java source code, but in practice, the differences between standard Google Java Style and AOSP style seem to be limited to indentation and import order.
Given that, using aosp() is a good solution.
References:
reflowLongStrings
The official examples include configurations such as:
googleJavaFormat('1.8').aosp().reflowLongStrings().formatJavadoc(false).reorderImports(false).groupArtifact('com.google.googlejavaformat:google-java-format')What does reflowLongStrings actually do?
Consider the following string:
static final String ANOTHER_LONG_STRING =
"This is another long string but this line is under 100 characters "
+ "and this line is also under 100 characters "
+ "but this line is over 100 characters and will not be reformatted to under 100 characters using the intellij plugin but will be reformatted to under 100 characters using the jar.";Without reflowLongStrings, the string length is not adjusted (although indentation is corrected).
With reflowLongStrings enabled, the code is formatted as follows:
static final String ANOTHER_LONG_STRING =
"This is another long string but this line is under 100 characters and this line is"
+ " also under 100 characters but this line is over 100 characters and will not be"
+ " reformatted to under 100 characters using the intellij plugin but will be"
+ " reformatted to under 100 characters using the jar.";Without this option, the final long line remains unchanged, but with it enabled, each line is adjusted to stay within 100 characters.
Since Google Java Style specifies a 100-character line limit (Column limit: 100), enabling reflowLongStrings is generally recommended.
References:
- Google Java Format doesn’t reflow long strings
- Formatting code with intellij plugin and using the jar gives different results
When You Need Detailed Configuration
googleJavaFormat() allows some configuration via method chaining, but it does not seem to support fine-grained customization of individual rules.
If you want to use Google Java Format and apply detailed customizations, one approach is to avoid googleJavaFormat() and instead use Eclipse JDT formatting, which allows configuration via an external settings file.
The Gradle configuration looks like this:
java {
// As of now, 4.32 appears to be the latest version
eclipse('4.32').configFile('config/eclipse-prefs.xml')
}You then place the Eclipse JDT formatter configuration file in the config directory.
Although I am not very familiar with Eclipse JDT itself, the XML file provided in the Google Style Guide repository works well as a starting point.
You can customize it as needed. For example, changing the value of org.eclipse.jdt.core.formatter.tabulation.size to 4 results in 4-space indentation.
Reusing Checkstyle Configuration
If you are already using Checkstyle, you might want to reuse its configuration. However, Checkstyle configuration files are different from Eclipse JDT formatter settings.
According to an issue:
Nope. Checkstyle is for warning about problems, spotless focuses on automatically fixing problems. There are lots of things that you can warn about but can’t automatically fix, so the thing you are asking for will probably never happen.
Is there a tool to convert the checkstyle configuration file to the spotless configuration file
Because Checkstyle and spotless serve different purposes, there is no straightforward way to convert a Checkstyle configuration into a spotless configuration, and this is unlikely to change in the future. If you already have a heavily customized Checkstyle setup, the realistic approach is to manually translate the relevant rules into an Eclipse JDT formatter configuration.
Verification Repository
I tested spotless using this repository
The master branch is formatted using googleJavaFormat, while the eclipse branch is formatted using eclipse.
