skip to content

Quality Tooling

The tooling that gates a Kotlin build: formatters, static analyzers, explicit-API mode, and binary-compatibility checks. Mentioning these signals that you think about codebases, not just code.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

explore

questions

21

What is detekt and what does running the `detekt` Gradle task do for a Kotlin project?

level: juniorimportance: must knowfreq 62%

answer

  1. Static analysis = reads code, doesn't run it
  2. Gradle plugin id io.gitlab.arturbosch.detekt adds `detekt` task
  3. Parses .kt into PSI/AST, runs rule sets
  4. Reports: HTML/XML/SARIF/TXT under build/reports/detekt
  5. Smells + complexity (detekt) vs formatting (ktlint)

basics

~10 s

detekt is a static analysis tool for Kotlin. It scans your source code without running it and reports code smells, overly complex functions, and style problems so you can fix them.

solid answer

~40 s

detekt is a static code analyzer for Kotlin that inspects source files at compile-time (no execution) for code smells, complexity, naming, and potential bugs. You apply the `io.gitlab.arturbosch.detekt` Gradle plugin, which adds a `detekt` task. Running `./gradlew detekt` parses each `.kt` file into an AST/PSI tree, runs enabled rules, and emits findings as console output plus reports (HTML, XML/Checkstyle, SARIF, plain TXT) under `build/reports/detekt`. By default it fails the build when findings exceed the configured `maxIssues` threshold (or any if zero), making it a quality gate. Rules are organized into rule sets (complexity, style, potential-bugs, etc.) and configured via `detekt.yml`. It complements ktlint, which focuses purely on formatting, whereas detekt targets smells and complexity.

code

kotlin · 9 lines
kotlin
plugins {
    id("io.gitlab.arturbosch.detekt") version "1.23.7"
}

detekt {
    buildUponDefaultConfig = true
    config.setFrom(files("$rootDir/detekt.yml"))
}
// ./gradlew detekt  -> findings + build/reports/detekt/detekt.html

go deeper

for a junior

Knows detekt is a Kotlin static analyzer that flags smells/complexity and runs via a Gradle task.

for a middle

Can name rule sets and report formats, and explains how it acts as a build-failing quality gate.

for a senior

Distinguishes detekt from ktlint by responsibility, knows PSI-based analysis and threshold configuration.

for a principal

Frames detekt within an overall quality-gate strategy across modules/CI and weighs its value vs false positives.

## What detekt is **detekt** is a *static analysis* tool for Kotlin. "Static" means it analyzes your source code **without running it** — it reads the text, parses it into a syntax tree, and applies rules. Contrast this with *dynamic* analysis (running tests, profilers) which needs the program to execute. It finds **code smells** (patterns that hint at deeper problems, e.g. a function that's too long), **complexity** issues (deeply nested code, too many branches), naming violations, and likely bugs (e.g. an empty `catch` block). ## How you run it You apply the Gradle plugin: ```kotlin plugins { id("io.gitlab.arturbosch.detekt") version "1.23.7" } detekt { config.setFrom("$rootDir/detekt.yml") buildUponDefaultConfig = true } ``` This registers a `detekt` task. Running `./gradlew detekt`: 1. Collects `.kt` source files. 2. Parses each into a **PSI** tree (Program Structure Interface — the Kotlin/IntelliJ AST representation). 3. Runs every **enabled rule** against the tree. 4. Reports each **finding** (rule id, file, line, message). 5. **Fails the build** if findings exceed the threshold — turning it into a *quality gate*. ## Rule sets Rules are grouped into **rule sets**: `complexity`, `style`, `potential-bugs`, `coroutines`, `naming`, `exceptions`, `performance`, and more. Each rule has a unique id (e.g. `LongMethod`, `MagicNumber`, `TooGenericExceptionCaught`). ## Reports Reports land under `build/reports/detekt/`: HTML (human-friendly), XML (Checkstyle format for CI), SARIF (for GitHub code scanning), and TXT. ## detekt vs ktlint - **ktlint** = pure formatting/style (indentation, import order). It can auto-format. - **detekt** = code smells and complexity. It mostly *reports* (limited autocorrect for some rules via `autoCorrect`). Many projects run both. detekt is the deeper "is this code healthy?" check.

  • Does detekt run your tests or execute the code?
    No. It is purely static — it parses and analyzes source text only, so it is fast and needs no running application.
  • Where do you see the results?
    In the console and as report files under build/reports/detekt (HTML, XML, SARIF, TXT).

detekt is a spell-and-grammar checker for code health: it reads your draft and flags awkward, risky, or overly tangled passages without ever 'running' the story.

saying these in an interview costs you the question

  • Saying detekt runs the program or executes tests
  • Confusing detekt with ktlint by claiming its main job is formatting
  • Not knowing it is applied as a Gradle (or Maven/CLI) plugin
  • Thinking findings never affect the build outcome

context

open as a page

What is ktlint, and what is the difference between the ktlintCheck and ktlintFormat Gradle tasks?

level: juniorimportance: must knowfreq 70%

basics

~10 s

ktlint is a tool that checks and fixes Kotlin code style. ktlintCheck only reports problems and fails the build; ktlintFormat automatically rewrites your files to fix the fixable ones.

open as a page

Explain the relationship between the apiDump and apiCheck tasks and the typical developer workflow when you intentionally change a public API.

level: middleimportance: must knowfreq 40%

basics

~20 s

apiCheck compares your current public API to the saved file and fails if they differ. apiDump regenerates that saved file. When you intentionally change the API, you run apiDump and commit the updated file so the check passes again.

open as a page

How does `detekt.yml` work, and what do `buildUponDefaultConfig` and `--build-upon-default-config` mean when configuring rules?

level: middleimportance: must knowfreq 55%

basics

~10 s

detekt.yml is a YAML file where you turn rules on or off and set their thresholds. With buildUponDefaultConfig, your file only overrides the defaults instead of replacing them entirely.

open as a page

How do you enable Explicit API mode in a Kotlin Gradle build, and what is the difference between strict and warning levels?

level: middleimportance: must knowfreq 40%

basics

~10 s

In your Gradle build script's kotlin block, call explicitApi() for strict mode (build fails) or explicitApiWarning() for warnings only. Under the hood it passes a -Xexplicit-api compiler flag.

open as a page

What is the kotlinx binary-compatibility-validator, and what problem does it solve for a Kotlin library?

level: juniorimportance: should knowfreq 35%

basics

~20 s

It is a tool that records your library's public API into text files. If a change accidentally removes or alters that public API, the build fails, warning you before you break code that depends on your library.

open as a page

What is Kotlin's Explicit API mode, and what two things does it require library authors to do?

level: juniorimportance: should knowfreq 35%

basics

~10 s

It's a compiler mode for libraries. It forces you to write the visibility keyword (like public) and the return type on everything your library exposes, so nothing leaks out by accident.

open as a page

How do you wire BCV into a Gradle library so CI enforces it, and how do you exclude an experimental package or a generated class from the dump?

level: middleimportance: should knowfreq 25%

basics

~20 s

Apply the BCV Gradle plugin; it adds apiCheck to the standard check task, so any CI running ./gradlew check enforces it. To exclude things, use the apiValidation block to ignore packages, classes, or annotation markers.

open as a page

What is a detekt baseline file, how do you generate it, and how should it be used when adopting detekt on a legacy codebase?

level: middleimportance: should knowfreq 48%

basics

~10 s

A baseline is a file that records all existing detekt findings so they get ignored from now on. It lets you adopt detekt without fixing everything first, while still catching new problems.

open as a page

How do you configure detekt reports (SARIF, XML, HTML) and integrate detekt into CI so it gates merges and surfaces findings in code review?

level: middleimportance: should knowfreq 38%

basics

~20 s

detekt can output reports in several formats. SARIF is a standard JSON format that GitHub understands, so you upload it to show findings as annotations on pull requests. In CI you run the detekt task and fail the build on findings.

open as a page

Under Explicit API strict mode, which declarations get flagged and which are exempt? Give concrete examples.

level: middleimportance: should knowfreq 30%

basics

~10 s

It flags things visible outside your module — public and protected members that don't say their visibility, and public functions/properties with no written return type. Private, internal, local code, and overrides are left alone.

open as a page

How does ktlint use .editorconfig, and what are some rules you can tune there (e.g. code style, line length, import ordering)?

level: middleimportance: should knowfreq 55%

basics

~10 s

ktlint reads its limited settings from a .editorconfig file at the project root. There you set things like the code style flavor, max line length, indent size, and whether to allow certain rules.

open as a page

What are ktlint's standard and experimental rule sets, and how do you opt into experimental rules safely?

level: middleimportance: should knowfreq 40%

basics

~20 s

The standard rule set is the stable, default set of style rules. The experimental set holds newer rules that are off by default; you turn them on in .editorconfig when you want to try them.

open as a page

What exactly ends up in a .api dump, and what Kotlin constructs are excluded or need special handling (e.g. internal, @PublishedApi, inline)?

level: seniorimportance: should knowfreq 30%

basics

~20 s

The dump records everything reachable through your public API as JVM signatures: public and protected classes, methods, and fields. Truly internal or private things are excluded. Some inline-related members still leak into the binary API and show up.

open as a page

What is type resolution in detekt, why do some rules require it, and how do you enable it (and how does it differ from a plain `detekt` run)?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Some detekt rules need to know the real types of expressions, not just the text. That extra information is type resolution. You enable it by giving detekt the compiled classpath, which makes those advanced rules work.

open as a page

Explicit API mode and the Binary Compatibility Validator both guard a library's API. How do they differ, and why might you use both?

level: seniorimportance: should knowfreq 22%

basics

~20 s

Explicit API mode works while you type — it forces you to declare what's public and its type. Binary Compatibility Validator works at review time — it diffs a saved snapshot of your public API so accidental breaking changes show up. They cover different moments.

open as a page

How do you integrate ktlint into a CI quality gate, and how does a baseline help you adopt it on an existing codebase?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Run ktlintCheck in CI so the build fails on style violations. On a big legacy codebase, generate a baseline file that records existing violations so CI only fails on new ones, then fix the old ones gradually.

open as a page

A teammate argues 'apiCheck passed, so this release is safe.' Where does BCV's guarantee actually end, and what kinds of breaking changes can still slip through?

level: principalimportance: should knowfreq 22%

basics

~20 s

A passing apiCheck only means the recorded public API signatures didn't change. It can't see changes in behavior, inlined function bodies, constant values, or runtime contracts — so a release can still break consumers even when the check is green.

open as a page

How do you write a custom detekt rule and register it as a `RuleSetProvider`, and what core APIs are involved?

level: seniorimportance: nice to knowfreq 28%

basics

~20 s

You write a class that extends detekt's Rule, override the visit method for the code you care about, and report findings. Then you bundle it in a RuleSetProvider and put that module on detekt's plugin classpath.

open as a page

You lead a multi-module Kotlin library. Design an adoption strategy for Explicit API mode that doesn't paralyze the team, and explain the trade-offs.

level: seniorimportance: nice to knowfreq 14%

basics

~20 s

Turn it on as warnings first so nothing breaks, clean up module by module, then switch to strict and let CI enforce it. Apply it only to published modules, not apps or tests, and standardize the setting in one shared build convention.

open as a page

ktlint and detekt overlap on formatting. How do you decide which owns formatting, and how do you prevent ktlint disagreeing with IntelliJ's reformatter?

level: seniorimportance: nice to knowfreq 25%

basics

~20 s

Let ktlint own formatting and let detekt focus on code smells and complexity. To avoid fights with IntelliJ, point both ktlint and the IDE at the same .editorconfig so they format code the same way.

open as a page