How to Add Spotless Code Formatter to your Android Project?
Steps-by-steps guide to add spotless code formatter to your Android project for both Kotlin script (KTS) and Groovy build Gradle files
I have been seeing this spotless in many open-source codes, and it turns out it is a pretty popular coding style plugin for the Gradle build system used in Android development.
So I gave it a try and use it in my project. Here are the steps I took to add this spotless plugin to my existing projects, which consist of both Kotlin script (KTS) and Groovy build Gradle files.
1. Add com.diffplug.spotless Plugin
Add com.diffplug.spotless
in the project-level build.gradle/.kts.
KTS
plugins {
/*...*/
id("com.diffplug.spotless") version "6.19.0" apply false
}
Groovy
plugins {
/*...*/
id 'com.diffplug.spotless' version '6.19.0' apply false
}
2. Configure the Spotless
Add the following at the end of your project-level build.gradle/.kts.
KTS
subprojects {
apply(plugin = "com.diffplug.spotless")
configure<com.diffplug.gradle.spotless.SpotlessExtension> {
kotlin {
target("**/*.kt")
targetExclude("$buildDir/**/*.kt")
ktlint()
licenseHeaderFile(rootProject.file("spotless/copyright.kt"))
}
kotlinGradle {
target("*.gradle.kts")
ktlint()
}
}
}
Groovy
subprojects {
apply plugin: 'com.diffplug.spotless'
spotless {
kotlin {
target '**/*.kt'
targetExclude("$buildDir/**/*.kt")
ktlint()
licenseHeaderFile rootProject.file('spotless/copyright.kt')
}
groovyGradle {
target '*.gradle'
greclipse()
}
}
}
Few notes:
target("**/*.kt")
is needed to include all the Kotlin files in the subdirectories.**
indicates the subdirectories.licenseHeaderFile
adds the copyright text header in every Kotlin file. An example of thespotless/copyright.kt
file can be found here.Don't need to explicitly use
**
intarget("*.gradle.kts")
, it includes the subdirectories already.
3. Run the Spotless Code Formatter
Run the following commands in your Android Studio terminal.
To check without making changes:
.\gradlew spotlessCheck
To check and apply the changes:
.\gradlew spotlessApply
spotlessCheck is a bit useless to me. I usually just run the spotlessApply directly.
It won't apply the change directly if it encounters errors. Some of the errors I get are
Wildcard Imports is Used
rule: standard:no-wildcard-imports
Wildcard import
java.lang.AssertionError: Error on line: 5, column: 1
rule: standard:no-wildcard-imports
Wildcard import
No Whitespace Start of Function Body
rule: standard:function-start-of-body-spacing
Expected a single white space before start of function body
java.lang.AssertionError: Error on line: 7, column: 57
rule: standard:function-start-of-body-spacing
Expected a single white space before start of function body
After you fix all the errors, it applies the copyright header and default coding style to your files.
4. Automate spotlessApply in Build
If you're lazy to run .\gradlew spotlessApply every time, you can automate it whenever you build an Android project.
Add this in your project-level build.gradle/.kts file to run the spotlessApply task before the preBuild task.
KTS / Groovy
subprojects {
/*...*/
afterEvaluate {
tasks.named("preBuild") {
dependsOn("spotlessApply")
}
}
}
Issues Faced with Spotless
Official document sucks - I follow the doc here. No, it doesn't work!
One error at a time - No kidding, I have many wildcard imports in my project. I have to fix each error and rerun the spotlessApply to get to the next errors. Luckily, I can search the file content instead of relying on the spotless.
Can't disable the rule - I tried, but I didn't get it working. So I have no idea whether this is feasible. This is no documentation on this at all.
[Updated - Feb 17, 2024]: When I updated the spotless version to from "6.19.0"
to "6.25.0", I got the following error:"Function name should start with a lowercase letter (except factory methods) and use camel case"
To fix that, you need to create a new .editorconfig in your project root directory and add this
ktlint_function_naming_ignore_when_annotated_with=Composable
.editorconfilg example
# https://editorconfig.org/
# This configuration is used by ktlint when spotless invokes it
[*.{kt,kts}]
ktlint_function_naming_ignore_when_annotated_with=Composable
However, the Android Studio has this warning indicates the ktlint_function_naming_ignore_when_annotated_with
is not supported, but it is incorrect. So, I guess, you can ignore this warning.
Warning:(5, 1) The property is not supported
Example
GitHub Repository: Demo_CleanEmptyCompose
master branch (KTS)
master_groovy branch (Groovy)