$30 off During Our Annual Pro Sale. View Details »

22 - Detekt 1.22.0

22 - Detekt 1.22.0

Do you know Detekt? We are a static analyzer for Kotlin.
Our mission: spot bugs, antipatterns, and potential errors in your Kotlin code.

Detekt is helping millions of Kotlin developers around the globe to spot bugs before they reach production. What took us here is a vibrant community of users & contributors that are helping us build this ecosystem of tools.

In this talk, I will walk you through 22 goodies, tips and rules we released in 2022 for maintaining an elegant and beautiful Kotlin codebase.

Nicola Corti

January 01, 2023
Tweet

More Decks by Nicola Corti

Other Decks in Technology

Transcript

  1. 2
    2

    View Slide

  2. 22
    Nicola Corti


    @cortinico

    View Slide

  3. Nicola Corti
    Kotlin GDE


    Detekt Maintainer


    twitter.com/cortinico


    [email protected]


    github.com/cortinico


    ncorti.com
    The Developers’ Bakery Podcast

    thebakery.dev


    View Slide

  4. 22

    View Slide

  5. 1.7.22
    1.22.0
    2022 🎅

    View Slide

  6. What is ?

    View Slide

  7. What is ?

    View Slide

  8. What is ?

    View Slide

  9. ~200 Rules

    View Slide

  10. UnnecessaryNotNullCheck
    1
    fun main() {

    val santa = "🎅"

    println(requireNotNull(santa))

    }

    Remove unnecessary not
    -
    null checks on
    non
    -
    null types.

    View Slide

  11. UnnecessaryNotNullCheck
    1
    fun main() {

    val santa = "🎅"

    println(santa)

    }

    View Slide

  12. CanBeNonNullable
    2
    var song: String? = "All I want for Christmas”

    fun sing() {

    song = "is you!"

    }

    Variable can be changed to non
    -
    nullable, as it is
    never set to null.

    View Slide

  13. CanBeNonNullable
    2
    var song: String = "All I want for Christmas”

    fun sing() {

    song = "is you!"

    }

    View Slide

  14. NullCheckOnMutableProperty
    3
    var snow: String? = null

    if (snow
    !=
    null) {

    println("Let it $snow")

    }

    Checking nullability on a mutable property is not useful
    because the property may be set to null afterwards.

    View Slide

  15. AlsoCouldBeApply
    4
    Rudolph().also {

    it.nose = "Red"

    it.glows()

    }

    When an `also` block contains only
    `it`
    -
    started expressions, simplify it

    View Slide

  16. AlsoCouldBeApply
    4
    Rudolph().apply {

    nose = "Red"

    glows()

    }

    View Slide

  17. ElseCaseInsteadOfExhaustiveWhen
    5
    enum class Cake {

    PANDORO,

    PANETTONE,

    STOLLEN

    }

    when(cake) {

    Cake.PANDORO
    ->
    {}

    Cake.PANETTONE
    ->
    {}

    else
    ->
    {}

    }

    A `when` expression that
    has an exhaustive set of
    cases should not contain
    an `else` case.

    View Slide

  18. ElseCaseInsteadOfExhaustiveWhen
    5
    enum class Cake {

    PANDORO,

    PANETTONE,

    STOLLEN

    }

    when(cake) {

    Cake.PANDORO
    ->
    {}

    Cake.PANETTONE
    ->
    {}

    Cake.STOLLEN
    ->
    {}

    }

    View Slide

  19. NullableBooleanCheck
    6
    var snows: Boolean? = checkWeather()

    if (snows
    ?:
    true) {

    //
    it snows

    }
    Nullable boolean check should use
    `
    = =
    ` rather than `
    ? :
    `

    View Slide

  20. NullableBooleanCheck
    6
    var snows: Boolean? = checkWeather()

    if (snows
    ==
    true) {

    //
    it snows

    }

    View Slide

  21. CouldBeSequence
    7
    listOf(1, 2, 3, 4)

    .map { it * 2 }

    .filter { it < 4 }

    .map { it * it }
    Several chained collection operations
    that should be a sequence.

    View Slide

  22. CouldBeSequence
    7
    listOf(1, 2, 3, 4)

    .asSequence()

    .map { it*2 }

    .filter { it < 4 }

    .map { it*it }

    .toList()

    View Slide

  23. NestedScopeFunctions
    8
    class Santa(var name: String = "")

    class Deer(var color: String = "")

    Santa().apply {

    Deer().apply {

    name = "🎅"

    color = "🔴"

    }

    }

    Over
    -
    using scope functions makes


    code confusing, hard to read


    and bug prone

    View Slide

  24. ForbiddenSuppress
    9
    @Suppress("UNCHECKED_CAST")

    class Santa(var name: String = "")

    Cannot @Suppress UNCHECKED_CAST due
    to the current conf
    i
    guration

    View Slide

  25. UnnecessaryBackticks
    10
    class `Santa`()

    Backticks are unnecessary

    View Slide

  26. 11
    val answer = 42

    This expression contains a magic number.
    Consider def
    i
    ning it to a well named

    View Slide

  27. 11
    fun myFunctionThatForWhateverReasonUsesMagicNumber() {

    val answer = 42

    }

    ignoreFunction

    View Slide

  28. 12
    fun xmasView(text: String, onClick: ()
    ->
    Unit) {

    //
    Render Xmas time!

    }

    View Slide

  29. 12
    fun XmasView(text: String, onClick: ()
    ->
    Unit) {

    //
    Render Xmas time!

    }

    View Slide

  30. 12
    @Composable

    fun XmasView(text: String, onClick: ()
    ->
    Unit) {

    //
    Render Xmas time!

    }
    Function names should follow the naming
    convention set in the conf
    i
    guration.

    View Slide

  31. 12
    @Composable

    fun XmasView(text: String, onClick: ()
    ->
    Unit) {

    //
    Render Xmas time!

    }
    ignoreAnnotated

    View Slide

  32. 13 Compose

    View Slide

  33. Better HTML Reports
    14

    View Slide

  34. Markdown Reports
    15

    View Slide

  35. ge.detekt.dev
    16

    View Slide

  36. libraries
    17
    libraries:

    active: true

    ForbiddenPublicDataClass:

    active: true

    ignorePackages:

    - '*.internal'

    - '*.internal.*'

    LibraryCodeMustSpecifyReturnType:

    active: true

    LibraryEntitiesShouldNotBePublic:

    active: true

    View Slide

  37. libraries
    17
    libraries:

    active: true

    ForbiddenPublicDataClass:

    active: true

    ignorePackages:

    - '*.internal'

    - '*.internal.*'

    LibraryCodeMustSpecifyReturnType:

    active: true

    LibraryEntitiesShouldNotBePublic:

    active: true

    View Slide

  38. ruleauthors
    18
    ruleauthors:

    active: true

    UseEntityAtName:

    active: true

    ViolatesTypeResolutionRequirements:

    active: true

    View Slide

  39. ruleauthors
    18
    ruleauthors:

    active: true

    UseEntityAtName:

    active: true

    ViolatesTypeResolutionRequirements:

    active: true

    View Slide

  40. detekt.dev
    19

    View Slide

  41. detekt.dev
    19

    View Slide

  42. detekt.dev
    19

    View Slide

  43. detekt.dev
    19

    View Slide

  44. Versioned Docs
    20

    View Slide

  45. Marketplace
    21

    View Slide


  46. 22

    View Slide

  47. 2
    2
    Nicola Corti


    @cortinico
    Thank you


    🙏

    View Slide

  48. View Slide

  49. 2
    2
    Nicola Corti


    @cortinico
    Thank you


    🙏

    View Slide