报告 IDE 扩展中不正确的伴生对象用法。

Kotlin 伴生对象始终会在您尝试加载其包含的类时创建,并且 IDE 扩展的创建成本应该很低。 插件中过多的类加载是 IDE 启动的一个大问题。

错误模式:


  class KotlinDocumentationProvider : AbstractDocumentationProvider(), ExternalDocumentationProvider {

      companion object {
          private val LOG = Logger.getInstance(KotlinDocumentationProvider::class.java)
          private val javaDocumentProvider = JavaDocumentationProvider()
      }
  }

这里 KotlinDocumentationProvider 是在 plugin.xml 中注册的扩展:


  <lang.documentationProvider language="JAVA"
                              implementationClass="org.jetbrains.kotlin.idea.KotlinDocumentationProvider"
                              order="first"/>

在此示例中,只要有人调用 new KotlinDocumentationProvider(),就会从磁盘加载 JavaDocumentationProvider

扩展实现中的 Kotlin 伴生对象只能包含记录器和简单常量。 其他声明可能会导致过多类加载或提前初始化开销大的资源(TokenSet、Regex 等)。 加载扩展类时。

这些声明必须存储在对象中或处于顶层,而不是存储在伴生对象中。

常见问题解答

如何重写 runConfigurationType?

将声明移到顶层:


  // 正确做法
  internal fun mnRunConfigurationType(): MnRunConfigurationType = runConfigurationType<MnRunConfigurationType>()

  internal class MnRunConfigurationType : ConfigurationType {
    companion object { // 错误做法
      fun getInstance(): MnRunConfigurationType = findConfigurationType(MnRunConfigurationType::class.java)
    }
  }

如何重写 FileType?

之前:


  internal class SpringBootImportsFileType : LanguageFileType(SPILanguage.INSTANCE, true) {
    companion object {
      val FILE_TYPE = SpringBootImportsFileType()
   }
  }

之后:


  internal object SpringBootImportsFileType : LanguageFileType(SPILanguage.INSTANCE, true) {

plugin.xml 中使用 INSTANCE fieldName:


  <fileType name="Spring Boot Imports"
              fieldName="INSTANCE"
              implementationClass="com.intellij.spring.boot.spi.SpringBootImportsFileType"/>

2023.2 最新变化