hbmartin/hbmartin-detekt-rules
GitHub: hbmartin/hbmartin-detekt-rules
一套面向 Kotlin 的 Detekt 自定义规则集,旨在通过静态分析在编译阶段捕获与可变性、不安全类型操作相关的潜在崩溃和 bug。
Stars: 5 | Forks: 1
# Hbmartin 的 detekt 规则
[](https://kotlinlang.slack.com/archives/C88E12QH4)
[](https://github.com/hbmartin/hbmartin-detekt-rules/actions/workflows/pre-merge.yml)
[](https://codecov.io/github/hbmartin/hbmartin-detekt-rules)
[](https://www.codefactor.io/repository/github/hbmartin/hbmartin-detekt-rules)
[](https://sonarcloud.io/dashboard?id=hbmartin_intellij-build-webhook-notifier)
[](https://central.sonatype.com/artifact/me.haroldmartin/hbmartin-detekt-rules)
[](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, 代码规范, 后台面板检测, 开发工具, 错误基检测, 静态代码分析