확장 프로그램 내에서 컴패니언 객체가 잘못 사용된 위치를 보고합니다.

Kotlin 컴패니언 객체는 항상 포함하는 클래스를 로드하려고 시도할 때 생성되며 확장 지점 구현은 생성 비용이 적습니다. 플러그인에서 과도한 클래스 로딩은 IDE 시작 시 큰 문제를 야기합니다.

잘못된 패턴:


  class KotlinDocumentationProvider : AbstractDocumentationProvider(), ExternalDocumentationProvider {

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

여기에서 KotlinDocumentationProviderplugin.xml에 등록된 확장입니다.


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

이 예시에서 JavaDocumentationProvidernew KotlinDocumentationProvider()가 호출될 때 디스크에서 로드됩니다.

확장 지점 구현 내의 Kotlin 컴패니언 객체는 로거와 간단한 상수만 포함할 수 있습니다. 다른 선언으로 인해 과도한 클래스 로드가 일어나거나 무거운 리소스(TokenSet, Regex 등)가 조기에 초기화될 수 있습니다 일찍 초기화될 수 있습니다. @JvmStatic으로 표시된 선언도 컴패니언 객체의 추가 클래스를 생성하며 비용이 큰 연산을 발생시킬 수 있습니다.

이러한 선언은 컴패니언 객체가 아닌 최상위 수준이나 객체에 저장해야 합니다.

자주 하는 질문

ConfigurationType을 재작성하고 실행하는 방법

선언을 최상위 수준으로 옮기세요.


  // 올바른 방법: 최상위 fun 사용
  internal fun mnRunConfigurationType(): MnRunConfigurationType = runConfigurationType<MnRunConfigurationType>()

  internal class MnRunConfigurationType : ConfigurationType {
    companion object { // DON'T
      fun getInstance(): MnRunConfigurationType = runConfigurationType<MnRunConfigurationType>()
    }
    .

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"/>

CounterUsagesCollector 재작성 방법

내부 API

전:


  class AntActionsUsagesCollector : CounterUsagesCollector() {
    override fun getGroup(): EventLogGroup = GROUP

    companion object {
      private val GROUP = EventLogGroup("build.ant.actions", 1)

      @JvmField
      val runSelectedBuildAction = GROUP.registerEvent("RunSelectedBuild")
   }
}

후:


 object AntActionsUsagesCollector : CounterUsagesCollector() {
  override fun getGroup(): EventLogGroup = GROUP

  private val GROUP = EventLogGroup("build.ant.actions", 1)

  @JvmField
  val runSelectedBuildAction = GROUP.registerEvent("RunSelectedBuild")
}

2023.3의 새로운 기능