# 6 posts tagged with "guides" | Detekt

Skip to main content

# 6 posts tagged with "guides"

View All Tags

## Recipe: diff your detekt config with the default one

September 27, 2020 · One min read

detekt's `./gradlew detektGenerateConfig` task copies the default configuration file to the location specified by the `config` property.

    detekt {
      ...
      config = files(...)
      ...
    }

When the file on this location already exists, your configuration won't be overwritten, and the task is a noop.

When we release a new version, some users like to generate the default one to compare changed properties. This can be done by running the detekt cli with the `--generate-config --config [/new/location]` flags. When already using Gradle, we can write a custom task and share this procedure with the team:

    import io.gitlab.arturbosch.detekt.DetektGenerateConfigTask

    val createDetektConfigForDiff by tasks.registering(DetektGenerateConfigTask::class) {
        description = "Generate newest default detekt config"
        config.setFrom(buildDir.resolve("detekt-diff.yaml"))

        doFirst {
          // optionally delete the old config diff file first
        }
    }

The last step involves calling your favorite diff tool (e.g. `diff detekt-diff.yaml my_config.yaml`) or using an online service like `http://incaseofstairs.com/jsdiff/`.

Likewise we can diff the default config of detekt version X with the default config of detekt version X-1. This will tell us which properties are new in version X.

## Howto: make detekt silent

August 14, 2019 · One min read

detekt's reporting mechanism relies on implementations of ConsoleReport's. The cli module and therefore the Gradle plugin implement a bunch of this reports.

A typical detekt report will look like following:

There are many different parts which might or might not interest you. If one part is not important to you, it can be excluded in the yaml configuration file. A silent configuration would exclude all possible processors and reports:

    processors:
      active: true
      exclude:
        - 'DetektProgressListener'
        - 'FunctionCountProcessor'
        - 'PropertyCountProcessor'
        - 'ClassCountProcessor'
        - 'PackageCountProcessor'
        - 'KtFileCountProcessor'

    console-reports:
      active: true
      exclude:
        - 'ProjectStatisticsReport'
        - 'ComplexityReport'
        - 'NotificationReport'
        - 'FindingsReport'
        - 'BuildFailureReport'

Running with this config won't produce any console messages:

Just verify that the `./report.txt` is not empty ;).

We might find detekt's `FindingsReport` too verbose and just want to print one message line per finding. This can be achieved by implementing a custom `ConsoleReport`.

    class SingleLineFindingsReport : ConsoleReport() {

        override fun render(detektion: Detektion): String? =
            detektion.findings.values
                .flatten()
                .joinToString("\n") { "${it.id} - ${it.message} - ${it.entity.location.file}" }
    }

Combined with our silent configuration only messages are printed when findings are actually found:

See the extension documention on how to let detekt know about your custom report.

## Howto: using snapshot releases of detekt

June 29, 2019 · One min read

detekt uses bintray for releases and artifactory for snapshots. To configure snapshot usage in your gradle plugin apply the following changes to your build file:

    detekt {
        // if a new release of detekt stays binary compatible with a previous
        // release, just change the 'toolVersion'
        toolVersion = "1.0.0-RC16-20190629.171442-3"
        config = files("$projectDir/detekt/config.yml")
        baseline = file("$projectDir/baseline.xml")

        reports {
            html {
                enabled = true
                destination = file("$rootDir/detekt.html")
            }
        }
    }

    // this changes may be necessary if detekt's core modules like 'cli, core, api or rules'
    // change in a way that is not binary compatible to older releases
    dependencies {
        // use the detekt configuration for only official detekt modules
        detekt "io.gitlab.arturbosch.detekt:detekt-cli:1.0.0-RC16-20190629.171442-3"
        detekt "io.gitlab.arturbosch.detekt:detekt-core:1.0.0-RC16-20190629.171442-3"
        detekt "io.gitlab.arturbosch.detekt:detekt-api:1.0.0-RC16-20190629.171442-3"
        ...
        // use detektPlugins for detekt plugins - custom or official like the formatting one
        detektPlugins "io.gitlab.arturbosch.detekt:detekt-formatting:1.0.0-RC16-20190629.171442-3"
    }

## Howto: migrating from the *test-pattern*

June 8, 2019 · 2 min read

Starting with RC15 the test-pattern is obsolete. This post shows how to leverage rule path excludes to achieve the same functionality.

With version < RC15 the configuration file allowed to specify which paths should be mapped to test files so detekt would not run specific rule sets and rules on these test files:

    test-pattern: # Configure exclusions for test sources
      active: true
      patterns: # Test file regexes
        - '.*/test/.*'
        - '.*Test.kt'
        - '.*Spec.kt'
      exclude-rule-sets:
        - 'comments'
      exclude-rules:
        - 'NamingRules'
        - 'WildcardImport'
        - 'MagicNumber'
        - 'MaxLineLength'
        - 'LateinitUsage'
        - 'StringLiteralDuplication'
        - 'SpreadOperator'
        - 'TooManyFunctions'

This was an okay approach as we nowadays separate production code and test code. However more different kinds of source files can be identified. For example generated and library code.

With the new approach of offering path patterns on the rule and rule set level the user has much more freedom in defining which rule should run on which path.

If we do not care about documented test classes because we write our test code in a documenting way, we could simply exclude the `comments` rule set for following patterns:

    comments:
      ...
      excludes: "**/*Test.kt, **/*Spec.kt"

If we for example do not care about `MagicNumber`'s in test code, we can exclude our test files for this rule:

    style:
      ...
      MagicNumber:
        excludes: "**/*Test.kt, **/*Spec.kt"

Make sure to use globing patterns here as detekt does not support regular expressions anymore. This change was done to make use of the `java.nio.file` library when handling os-specific paths.

If you were using the default detekt configuration with the default test-pattern, you will not notice any changes when upgrading to >= RC15. All exclude-rules and exclude-rule-sets will now make use of `excludes: "**/test/**,**/*Test.kt,**/*Spec.kt"`.

## Howto: build upon the default yaml config file

March 3, 2019 · One min read

A common use case of detekt users was to build upon the default config file and use a second config file to override some defaults. Speaking in Gradle terms, this could look like following:

    detekt {
        ...
        config = files(
                project.rootDir.resolve("config/default-detekt-config.yml"),
                project.rootDir.resolve("config/our.yml")
        )
        baseline = project.rootDir.resolve("config/baseline.xml")
        ...
    }

Starting from RC13, two new commandline flags got introduced:

- `--fail-fast`
- and `--build-upon-default-config`
- (`buildUponDefaultConfig` and `failFast` properties for gradle setup)

Both options allow us to use the distributed `default-detekt-config.yml` as the backup configuration when no rule configuration is found in the specified configuration (`--config` or `config = ...`).
This allows us to simplify our detekt setup without copy-pasting a huge config file:

    detekt {
        ...
        buildUponDefaultConfig = true
        config = files(project.rootDir.resolve("config/our.yml"))
        baseline = project.rootDir.resolve("config/baseline.xml")
        ...
    }

{% include links.html %}

## Howto: configure detekt for gradle root project

March 3, 2019 · 2 min read

When configuring detekt for your Gradle based project, you basically have two options:

- for each sub module a new gradle task should be created
- or one uber-task analyzes your whole project

For the first option, please see how detekt itself creates a task for each module:

    subprojecs {
    ...
        detekt {
            debug = true
            toolVersion = usedDetektVersion
            buildUponDefaultConfig = true
            config = files(project.rootDir.resolve("reports/failfast.yml"))
            baseline = project.rootDir.resolve("reports/baseline.xml")

            reports {
                xml.enabled = true
                html.enabled = true
            }
        }
    }

Sometimes it makes sense to add an additional detekt task which runs over the whole project and produces one big report. Such a setup could look like the following in its simplest form:

    plugins {
        id "io.gitlab.arturbosch.detekt" version "1.0.0-RC14"
    }

    repositories {
        jcenter()
    }

    detekt {
        source = files(rootProject.rootDir)
        buildUponDefaultConfig = true
    }

Make sure to specify the `input` parameter or no sources are found and detekt won't run!

If you need more fine grained detekt tasks, you could register more tasks using the Detekt task as the base task. Using the Kotlin-Dsl it could look like this:

    val detektAll by tasks.registering(Detekt::class) {
        description = "Runs over whole code base without the starting overhead for each module."
        parallel = true
        buildUponDefaultConfig = true
        setSource(files(projectDir))
        config = files(project.rootDir.resolve("reports/failfast.yml"))
        include("**/*.kt")
        include("**/*.kts")
        exclude("resources/")
        exclude("build/")
        baseline.set(project.rootDir.resolve("reports/baseline.xml"))
        reports {
            xml.enabled = false
            html.enabled = false
        }
    }

{% include links.html %}