如何编写Detekt规则禁止将AbstractActor子类引用声明为类属性
核心问题点
- 未声明需要类型解析:Detekt 自定义规则默认不会启用类型解析能力,你没有重写
requiresTypeAnalysis属性为true,导致bindingContext始终为空,类型判断逻辑直接跳过。 - API使用错误:你使用的
createTypeBindingForReturnType是用于获取函数/方法的返回类型绑定,对于构造参数、成员属性这类声明,应该使用createTypeBinding获取自身的类型绑定。 - 父类检查不完整:当前逻辑仅检查了类型的直接父类,没有递归遍历所有上层父类,无法匹配到
Typed1Actor这类间接继承AbstractActor的类型。 - 拼写错误:代码中多处把
AbstractActor误写为AbsractActor,会导致后续提示信息错误。
修正后的规则代码
package testRuleSet import io.gitlab.arturbosch.detekt.api.* import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.typeBinding.createTypeBinding import org.jetbrains.kotlin.types.KtType class NoExplicitlyReferencingActorRule(config: Config) : Rule(config) { override val issue: Issue = Issue( javaClass.simpleName, Severity.Style, "Customized-NoExplicitlyReferencingActor", Debt.TEN_MINS, ) // 关键:声明该规则需要类型解析,Detekt才会传入有效的bindingContext override val requiresTypeAnalysis: Boolean = true override fun visitParameter(parameter: KtParameter) { super.visitParameter(parameter) if (parameter.hasValOrVar() && validateDeclaration(parameter)) { reportCodeSmell(parameter) } } override fun visitProperty(property: KtProperty) { super.visitProperty(property) if (property.isMember && validateDeclaration(property)) { reportCodeSmell(property) } } private fun validateDeclaration(declaration: KtCallableDeclaration): Boolean { if (bindingContext == BindingContext.EMPTY) return false return isSubClassOfAbstractActor(declaration) } private fun isSubClassOfAbstractActor(declaration: KtCallableDeclaration): Boolean { val type = declaration.createTypeBinding(bindingContext)?.type ?: return false // 递归检查所有层级的父类 fun checkTypeRecursive(type: KtType): Boolean { if (type.getJetTypeFqName(false) == "testRule.AbstractActor") return true return type.constructor.supertypes.any { checkTypeRecursive(it) } } return checkTypeRecursive(type) } private fun reportCodeSmell(declaration: KtCallableDeclaration) { report( CodeSmell( issue, Entity.from(requireNotNull(declaration.colon)), "do not hold any subclass of AbstractActor as a explicit reference" ) ) } }
测试用例注意事项
如果你使用的是Detekt官方的测试工具套件,需要确保测试环境开启了类型解析能力,compileAndLintWithContext方法默认是支持类型解析的,只要规则声明了requiresTypeAnalysis = true就可以正常获取绑定上下文。
内容的提问来源于stack exchange,提问作者Munar Yesen
相关产品推荐
相关产品推荐

