hbmartin/hbmartin-detekt-rules

GitHub: hbmartin/hbmartin-detekt-rules

一套面向 Kotlin 的 Detekt 自定义规则集,旨在通过静态分析在编译阶段捕获与可变性、不安全类型操作相关的潜在崩溃和 bug。

Stars: 5 | Forks: 1

# Hbmartin 的 detekt 规则 [![加入 KotlinLang 上的 #detekt 聊天室](https://img.shields.io/badge/%23detekt-slack-red.svg?logo=slack)](https://kotlinlang.slack.com/archives/C88E12QH4) [![PR 检查](https://static.pigsec.cn/wp-content/uploads/repos/cas/43/43eeb1155f704bf1e61ac69219a9fc40a576b1365f7ca580ea1c88e1d22bdf14.svg)](https://github.com/hbmartin/hbmartin-detekt-rules/actions/workflows/pre-merge.yml) [![codecov](https://codecov.io/github/hbmartin/hbmartin-detekt-rules/branch/main/graph/badge.svg?token=5CIMCMO3K3)](https://codecov.io/github/hbmartin/hbmartin-detekt-rules) [![CodeFactor](https://www.codefactor.io/repository/github/hbmartin/hbmartin-detekt-rules/badge)](https://www.codefactor.io/repository/github/hbmartin/hbmartin-detekt-rules) [![可维护性评级](https://sonarcloud.io/api/project_badges/measure?project=hbmartin_hbmartin-detekt-rules&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=hbmartin_intellij-build-webhook-notifier) [![Maven Central 版本](https://img.shields.io/maven-central/v/me.haroldmartin/hbmartin-detekt-rules)](https://central.sonatype.com/artifact/me.haroldmartin/hbmartin-detekt-rules) [![KDoc](https://img.shields.io/badge/KDoc-GitHub%20Pages-blue)](https://hbmartin.github.io/hbmartin-detekt-rules/) 这些是我个人的见解。有很多人也有类似的看法,但这些属于我。😄 ## 快速开始 在你的 `dependencies` 块中添加以下内容:(有关更多详细信息,请参阅[添加更多规则集](https://github.com/detekt/detekt#adding-more-rule-sets)) ``` detektPlugins("me.haroldmartin:hbmartin-detekt-rules:0.1.7") ``` 然后按照下方的章节将其添加到你的 detekt 配置中以激活规则。请注意,AvoidFirstOrLastOnList、AvoidMutableCollections 和 AvoidToIntOrThrowingConversions 规则需要激活[类型解析](https://detekt.dev/docs/gettingstarted/type-resolution)。 ## 类型解析 其中一些规则需要类型解析,这通常在运行 `detekt*Main` 任务时发生。有关更多详细信息(包括多平台项目的说明),请参阅 detekt 文档中的[使用类型解析](https://detekt.dev/docs/gettingstarted/type-resolution/)。 如果你依赖 `check` 任务来运行 detekt,你可以使用如下配置将默认的 detekt 检查替换为带有类型的检查: ``` tasks.named("check").configure { this.setDependsOn( this.dependsOn.filterNot { it is TaskProvider<*> && it.name == "detekt" } + tasks.named("detektMain"), ) } ``` ## 配置 将以下内容添加到你的 `detekt.yml` 中,并根据需要进行修改。除了显示的特定规则选项外,每个规则都支持 detekt 的标准选项,例如 `ignoreAnnotated` 和 `excludes` —— 例如,在 `NoNotNullOperator` 上设置 `ignoreAnnotated: ['Test']` 将允许在带有注解的测试函数中使用 `!!`。 ``` HbmartinRuleSet: AvoidFirstOrLastOnList: active: true # accessors to forbid; each must have an *OrNull equivalent methods: - 'first' - 'last' - 'single' - 'elementAt' - 'reduce' - 'reduceRight' - 'max' - 'min' - 'maxBy' - 'minBy' AvoidGlobalScope: active: true AvoidMutableCollections: active: true # set true to allow mutable collections in private declarations and function bodies allowPrivateAndLocal: false AvoidToIntOrThrowingConversions: active: true # String conversions to forbid; each must have an *OrNull equivalent methods: - 'toInt' - 'toLong' - 'toShort' - 'toByte' - 'toDouble' - 'toFloat' - 'toUInt' - 'toULong' - 'toUShort' - 'toUByte' - 'toBigDecimal' - 'toBigInteger' - 'toBooleanStrict' AvoidVarsExceptWithDelegate: active: true allowedDelegates: - 'remember\w*' - 'mutableState\w*' DontForceCast: active: true MutableTypeShouldBePrivate: active: true # regexes of mutable type names allowed to be exposed publicly allowedTypes: [] NoCallbacksInFunctions: active: true ignoreAnnotated: ['Composable'] allowExtensions: true allowReceivers: true allowInline: false NoDeferredResultInPublicApi: active: true NoLateinitVar: active: true # annotations that permit a lateinit var, e.g. ['Inject'] allowedAnnotations: [] NoNotNullOperator: active: true NoRunBlocking: active: true NoVarsInConstructor: active: true WhenBranchSingleLineOrBraces: active: true ``` ## 规则 ### 避免在列表首位或末位 查找在 `List`、`Array` 或 `Sequence` 上使用诸如 `.first()`、`.last()` 或 `.single()` 等会抛出异常的访问器的情况,包括安全调用、带谓词的调用以及方法引用。这些调用非常危险,因为如果不存在匹配的元素,它们会抛出 `NoSuchElementException`。建议使用 `*OrNull` 变体,例如 `.firstOrNull()` 或 `.lastOrNull()`。可以通过 `methods` 选项配置禁止使用的访问器集合。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/AvoidFirstOrLastOnListTest.kt)查看触发和不触发的示例。 ### 避免 Global Scope 查找使用 `GlobalScope` 的情况。在 `GlobalScope` 中启动的协程不绑定到任何生命周期,因此它们会导致工作泄漏、在失败时不会被取消,并且会掩盖崩溃。建议使用结构化的 `CoroutineScope`,例如在 Android 上的 `viewModelScope` 或 `lifecycleScope`。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/AvoidGlobalScopeTest.kt)查看触发和不触发的示例。 ### 避免 Mutable Collections 查找使用可变集合(例如 `MutableList<>`)的情况。这些情况极易导致 bug,建议使用函数式模式来创建根据需要修改的新列表。在标准库集合构建器(`buildList`、`buildSet`、`buildMap`)内部的使用以及来自 Java 互操作的平台类型不会被报告,并且 `allowPrivateAndLocal` 选项可以允许在私有声明和函数体中使用可变集合。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/AvoidMutableCollectionsTest.kt)查看触发和不触发的示例。 ### 避免 ToInt 或抛出异常的转换 查找诸如 `.toInt()` 等会在输入格式错误时抛出 `NumberFormatException` 的 `String` 转换操作。建议使用 `*OrNull` 变体(例如 `.toIntOrNull()`)并处理 `null` 情况。可以通过 `methods` 选项配置禁止使用的转换集合。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/AvoidToIntOrThrowingConversionsTest.kt)查看触发和不触发的示例。 ### 避免使用 Var(除非与 Delegate 一起使用) 查找使用可变 `var` 字段的情况。这些情况极易导致 bug,建议对任何可变状态使用 `Flow` 或某种响应式类型。对于通过[委托模式](https://kotlinlang.org/docs/delegation.html)实现的 `var` 存在例外情况,这在使用 Compose 时尤为常见。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/AvoidVarsExceptWithDelegateTest.kt)查看触发和不触发的示例。 ### 禁止强制转换 查找使用 `as` 进行强制转换的情况。这很可能导致崩溃,特别是在不可预见的情况下,建议改用 `as?` 进行安全转换。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/DontForceCastTest.kt)查看触发和不触发的示例。 ### Mutable 类型应为 Private 查找公开暴露的可变类型(例如 `MutableStateFlow<>`)。这很可能导致 bug,建议暴露不可变的 `Flow`(例如使用 `_mutableStateFlow.asStateFlow()`)或其他不可变类型。允许匹配 `allowedTypes` 选项中正则表达式的类型名称。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/MutableTypeShouldBePrivateTest.kt)查看触发和不触发的示例。 ### 函数中禁止 Callback 查找在函数中使用回调的情况。这可能会导致并发范式混乱,并且很容易导致 bug 或线程停滞,建议改用 suspend 函数。使用 `ignoreAnnotated` 配置可以允许在 `@Composable` 函数中使用回调。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/NoCallbacksInFunctionsTest.kt)查看触发和不触发的示例。 ### Public API 中禁止 DeferredResult 查找具有显式声明 `Deferred` 类型的公共函数和属性。返回 `Deferred` 会将并发实现泄露给调用者,并使崩溃难以追踪,建议使用返回已等待值的 suspend 函数。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/NoDeferredResultInPublicApiTest.kt)查看触发和不触发的示例。 ### 禁止 Lateinit Var 查找 `lateinit var` 属性。在初始化之前访问 `lateinit` 属性会因 `UninitializedPropertyAccessException` 而崩溃,并且 `lateinit` 强制要求可变性。建议使用构造函数参数、可为空的 `val` 或延迟初始化。对于确实需要 `lateinit` 的注解(例如 `@Inject`),可以使用 `allowedAnnotations` 选项允许。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/NoLateinitVarTest.kt)查看触发和不触发的示例。 ### 禁止 NotNull Operator 查找使用 `!!` 进行强制解包的情况。这很可能导致崩溃,建议改用 `?.` 或 `?:` 进行安全解包。否则 Kotlin 文档会嘲笑你是一个 [NPE 爱好者](https://kotlinlang.org/docs/null-safety.html#the-operator)。要在测试中允许使用 `!!`,请使用 `ignoreAnnotated: ['Test']` 或在此规则上设置 `excludes` 通配符。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/NoNotNullOperatorTest.kt)查看触发和不触发的示例。 ### 禁止 RunBlocking 查找对 `runBlocking` 的调用,它会阻塞当前线程直到其协程完成,并且在主线程上使用时可能会导致死锁或冻结 UI。建议暴露 suspend 函数并从结构化的 `CoroutineScope` 启动协程。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/NoRunBlockingTest.kt)查看触发和不触发的示例。 ### 构造函数中禁止 Vars 查找在构造函数中使用 `var` 的情况。这很可能导致 bug,请始终改用 `val`。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/NoVarsInConstructorTest.kt)查看触发和不触发的示例。 ### When 分支单行或使用大括号 一项样式规则,要求 when 表达式要么位于单行上,要么使用大括号。无论哪种情况,箭头后都应有一个空格。[点击此处](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/src/test/kotlin/me/haroldmartin/detektrules/WhenBranchSingleLineOrBracesTest.kt)查看触发和不触发的示例。 ## 贡献 * 加入并修改这个项目吧!首先使用 `git clone git@github.com:hbmartin/hbmartin-detekt-rules.git` 克隆它,然后在 IntelliJ 中打开并运行测试。 * 阅读 [detekt 文档](https://detekt.dev/docs/introduction/extensions/)以了解有关如何编写规则的更多信息。 * 每个规则类都包含带有 ``/`` 示例的 KDoc —— 在更新此 README 或默认的 `config.yml` 时,请将此 KDoc 视为权威描述。 * 欢迎提交 [PR](https://github.com/hbmartin/hbmartin-detekt-rules/pulls)和[错误报告 / 功能请求](https://github.com/hbmartin/hbmartin-detekt-rules/issues)! * 使用 detekt 进行检查,包括 ruleauthors 规则集,当然还有[在其自身上运行这些规则](https://github.com/hbmartin/hbmartin-detekt-rules/blob/main/build.gradle.kts#L20) 😏 * 以乐于助人、感恩和体贴的态度对待他人!请参阅 [JetBrains 行为准则](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct) ## 作者 * [Harold Martin](https://www.linkedin.com/in/harold-martin-98526971/) - harold.martin at gmail * 深受 [neeffect 的 kure-potlin](https://github.com/neeffect/kure-potlin)和 [Doist detekt-rules](https://github.com/Doist/detekt-rules)的启发
标签:Detekt, Kotlin, SOC Prime, 代码规范, 后台面板检测, 开发工具, 错误基检测, 静态代码分析