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

ยท

3 min read

How to Add Spotless Code Formatter to your Android Project?

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 the spotless/copyright.kt file can be found here.

  • Don't need to explicitly use ** in target("*.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

Did you find this article valuable?

Support Vincent Tsen - AndroidDev Blog by becoming a sponsor. Any amount is appreciated!

ย