0

在我们之前的项目中,我们有一个名为 AbstractActor 的类要被继承来做特定的事情,我们的一些开发人员可能会将其引用保存为构造的 valOrVar 参数或 KTProperty,这最终导致了垃圾收集灾难,actor 不能被收集,因为它被引用并且内存使用率飙升。所以我的领导要求我创建一个新规则来防止这种情况发生,我尝试了很多方法,但我无法让 KClass 确定它是 isAssignableFrom 还是 isSubclassOf 到 AbstractActor 类。这是我创建的测试示例

class ActorRefTest {

  @Test
  fun noExplicitlyReferencingActorRule() {
    val env = createEnvironment()
    val findings = NoExplicitlyReferencingActorRule(Config.empty).compileAndLintWithContext(
      env.env, """
        package testRule
open class TypedActor : AbstractActor() {
  override fun receive(msg: Any) {
  
  }


}
class Typed1Actor : TypedActor() {
  


}

abstract class AbstractActor {
  abstract fun receive(msg: Any) 
}
//@Suppress("NoExplicitlyReferencingActorRule")
class ExplicitlyReferencingActor(val actor: Typed1Actor, val isEnabled: Boolean) {
//       lateinit var actor2: AbstractActor 
        val isEnabled : Boolean = false

}

        """.trimIndent()
    )
    findings.forEach {
      println(it)
    }
    assert(findings.isNotEmpty())
  }

}

这是我创建的规则

package testRuleSet

import io.gitlab.arturbosch.detekt.api.*
import io.gitlab.arturbosch.detekt.rules.identifierName
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.createTypeBindingForReturnType

class NoExplicitlyReferencingActorRule(config: Config) : Rule(config) {
  override val issue: Issue = Issue(
    javaClass.simpleName,
    Severity.Style,
    "Customized-NoExplicitlyReferencingActor",
    Debt.TEN_MINS,
  )

  override fun visitParameter(parameter: KtParameter) {
    super.visitParameter(parameter)
    if (parameter.hasValOrVar()) {
      if (validateDeclaration(parameter)) {
        reportCodeSmell(parameter)
      }
    }
  }

  private fun isSubClassOfAbsractActor(parameter: KtCallableDeclaration): Boolean {
    return parameter.createTypeBindingForReturnType(bindingContext)?.type?.constructor?.supertypes?.find {
      it.getJetTypeFqName(
        false
      ) == "testRule.AbstractActor"
    } != null
  }

  private fun validateDeclaration(declaration: KtCallableDeclaration): Boolean {
    if (bindingContext == BindingContext.EMPTY) {
      return false
    }
    return isSubClassOfAbsractActor(declaration)
  }

  override fun visitProperty(property: KtProperty) {
    super.visitProperty(property)
    if (property.isMember) {
      if (validateDeclaration(property)) {
        reportCodeSmell(property)
      }
    }
  }

  private fun reportCodeSmell(declaration: KtCallableDeclaration) {
    report(
      CodeSmell(
        issue,
        Entity.from(requireNotNull(declaration.colon)),
        "do not hold any subclass of AbsractActor as a explicit reference"
      )
    )
  }


}

根据我在堆栈跟踪中看到的内容,detekt 和编译器知道确切的包和标识符名称,但我无法正确理解,我在这里缺少什么?

4

0 回答 0