Code Quality (Spotless & Detekt)
Relevant source files
The following files were used as context for generating this wiki page:
The Vocabri project employs a robust code quality system to ensure code consistency, readability, and maintainability. This is achieved through two primary Gradle plugins: Spotless for automated code formatting and Detekt for static code analysis. These tools are configured and applied across all modules via custom convention plugins located in the build-logic directory.
This system helps enforce a unified coding style, catch potential bugs and code smells early in the development process, and maintain a high standard of code health. The setup is centralized, making it easy to manage and apply consistently throughout the project.
System Architecture
The code quality tools are integrated into the Gradle build process through a custom ProjectConventionPlugin. This plugin applies both Spotless and Detekt configurations to every subproject, ensuring that all code is subject to the same formatting and analysis rules.
The following diagram illustrates how the convention plugin applies these configurations:
This diagram shows the ProjectConventionPlugin orchestrating the application of Spotless and Detekt configurations.
Sources: build-logic/convention/src/main/kotlin/ProjectConventionPlugin.kt:28-33
Spotless Configuration
Spotless is used for automatic code formatting across various file types in the project. The configuration is managed by the applySpotless extension function.
Sources: build-logic/convention/src/main/kotlin/com/vocabri/SpotlessConfiguration.kt
Formatted File Types
Spotless is configured to format a wide range of files, each with specific rules.
| Format Name | Target Files | Rules Applied |
|---|---|---|
misc | **/*.gradle, **/*.md, **/.gitignore | leadingTabsToSpaces, trimTrailingWhitespace, endWithNewline |
kotlin | **/*.kt (excluding build, tmp, resources, .gradle) | ktlint, licenseHeaderFile |
kts | **/*.kts (excluding build, tmp, resources, .gradle) | licenseHeaderFile |
xml | **/*.xml (excluding build, .gradle, .idea) | licenseHeaderFile |
json | **/*.json (excluding build, .gradle) | Default JSON formatting |
yaml | **/*.yml, **/*.yaml (excluding build, .gradle) | Default YAML formatting |
Sources: build-logic/convention/src/main/kotlin/com/vocabri/SpotlessConfiguration.kt:39-82
Kotlin Formatting with ktlint
For Kotlin files, Spotless uses ktlint as the formatter. The configuration includes specific overrides:
ktlint()
.editorConfigOverride(
mapOf(
"android" to "true",
"max_line_length" to "120",
),
)
Sources: build-logic/convention/src/main/kotlin/com/vocabri/SpotlessConfiguration.kt:54-60
This configuration ensures that Kotlin code adheres to standard conventions, with a maximum line length of 120 characters and Android-specific rules enabled.
License Headers
Spotless is also configured to automatically apply license headers to Kotlin (.kt, .kts) and XML (.xml) files. The license templates are located in the root project's .spotless/ directory.
- Kotlin:
licenseHeaderFile(rootProject.file(".spotless/license-kt")) - XML:
licenseHeaderFile(rootProject.file(".spotless/license-xml"), "(<[^!?])")
Sources: build-logic/convention/src/main/kotlin/com/vocabri/SpotlessConfiguration.kt:61, build-logic/convention/src/main/kotlin/com/vocabri/SpotlessConfiguration.kt:67, build-logic/convention/src/main/kotlin/com/vocabri/SpotlessConfiguration.kt:73
Detekt Configuration
Detekt is used for static analysis of the Kotlin codebase, identifying potential issues such as complexity, code smells, and style violations. The configuration is managed by the applyDetekt extension function.
Sources: build-logic/convention/src/main/kotlin/com/vocabri/DetektConfiguration.kt
Core Configuration
The Detekt plugin is applied to all subprojects with the following settings:
buildUponDefaultConfig:true(Custom rules are layered on top of Detekt's default ruleset).autoCorrect:true(Enables automatic correction of fixable issues).parallel:true(Runs analysis on files in parallel for better performance).config: The configuration file is specified as$rootDir/.detekt/detekt-config.yml.jvmTarget: Set to match the project's JVM target version.
Sources: build-logic/convention/src/main/kotlin/com/vocabri/DetektConfiguration.kt:43-49, build-logic/convention/src/main/kotlin/com/vocabri/DetektConfiguration.kt:58
Custom Rulesets
The project enhances Detekt's capabilities by including a custom ruleset for Jetpack Compose. This is added as a dependency to the detektPlugins configuration.
dependencies {
add("detektPlugins", libs.findLibrary("detekt.compose.rules").get())
}
The detekt.compose.rules library is defined in the version catalog.
Sources: build-logic/convention/src/main/kotlin/com/vocabri/DetektConfiguration.kt:52-54, gradle/libs.versions.toml:96
Reporting
Detekt is configured to generate reports in both XML and HTML formats upon execution. These reports are saved in the build/reports/detekt/ directory of each module. The build will fail if any issues are found (ignoreFailures = false).
Sources: build-logic/convention/src/main/kotlin/com/vocabri/DetektConfiguration.kt:60-64
Baseline Suppression
The project uses a baseline XML file to ignore pre-existing issues, allowing the team to focus on new code. The baseline for the app module is located at app/detekt-baseline.xml.
Currently, the following issues are suppressed in the baseline:
<CurrentIssues>
<ID>CyclomaticComplexMethod:AddWordViewModel.kt$AddWordViewModel$fun handleEvent(event: AddWordEvent)</ID>
<ID>TooManyFunctions:AddWordViewModel.kt$AddWordViewModel : ViewModel</ID>
</CurrentIssues>
This indicates that the handleEvent function in AddWordViewModel has high cyclomatic complexity and the AddWordViewModel class has too many functions, but these are currently accepted.
Sources: app/detekt-baseline.xml:26-29
Usage
The code quality tools can be run from the command line using Gradle wrapper scripts.
The following diagram shows the developer workflow for using these tools.
Commands
- Format code: To automatically format all files according to the Spotless configuration, run:
./gradlew spotlessApply - Static analysis: To run Detekt and generate reports, run:
./gradlew detekt
Sources: README.md:73-74