KT-38027 Support Code Vision feature in Kotlin // experimental status
Feature received "experimental" status due to the low performance.
The root cause is slow find-usages functionality the feature is based
on. Once the later is improved Code-Vision should be revisited.
Previous commit of KT-38027 series contains production ready state.
To launch performance check again one needs to enable Code Vision in
AbstractPerformanceProjectsTest.setUp() with the following fun:
private fun enabledCodeVision() {
val codeVisionProvider = KotlinCodeVisionProvider()
val settings = codeVisionProvider.createSettings().apply {
showUsages = true
showInheritors = true
}
InlayHintsSettings.instance().storeSettings(codeVisionProvider.key,
KotlinLanguage.INSTANCE, settings)
}
This commit is contained in:
@@ -147,6 +147,16 @@
|
|||||||
defaultValue="true"
|
defaultValue="true"
|
||||||
restartRequired="false"/>
|
restartRequired="false"/>
|
||||||
|
|
||||||
|
<registryKey key="kotlin.code-vision.usages"
|
||||||
|
description="Enable Code-Vision usages search"
|
||||||
|
defaultValue="false"
|
||||||
|
restartRequired="false"/>
|
||||||
|
|
||||||
|
<registryKey key="kotlin.code-vision.inheritors"
|
||||||
|
description="Enable Code-Vision inheritors search"
|
||||||
|
defaultValue="false"
|
||||||
|
restartRequired="false"/>
|
||||||
|
|
||||||
<fileEditorProvider implementation="org.jetbrains.kotlin.idea.scratch.ui.KtScratchFileEditorProvider"/>
|
<fileEditorProvider implementation="org.jetbrains.kotlin.idea.scratch.ui.KtScratchFileEditorProvider"/>
|
||||||
|
|
||||||
<moduleBuilder builderClass="org.jetbrains.kotlin.tools.projectWizard.wizard.NewProjectWizardModuleBuilder"/>
|
<moduleBuilder builderClass="org.jetbrains.kotlin.tools.projectWizard.wizard.NewProjectWizardModuleBuilder"/>
|
||||||
|
|||||||
+4
-20
@@ -14,7 +14,6 @@ import com.intellij.internal.statistic.eventLog.FeatureUsageData
|
|||||||
import com.intellij.internal.statistic.service.fus.collectors.FUCounterUsageLogger
|
import com.intellij.internal.statistic.service.fus.collectors.FUCounterUsageLogger
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.ui.layout.panel
|
import com.intellij.ui.layout.panel
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
|
||||||
import javax.swing.JPanel
|
import javax.swing.JPanel
|
||||||
|
|
||||||
|
|
||||||
@@ -27,27 +26,12 @@ fun logUsageStatistics(project: Project?, groupId: String, eventId: String) =
|
|||||||
fun logUsageStatistics(project: Project?, groupId: String, eventId: String, data: FeatureUsageData) =
|
fun logUsageStatistics(project: Project?, groupId: String, eventId: String, data: FeatureUsageData) =
|
||||||
FUCounterUsageLogger.getInstance().logEvent(project, groupId, eventId, data)
|
FUCounterUsageLogger.getInstance().logEvent(project, groupId, eventId, data)
|
||||||
|
|
||||||
fun createImmediateConfigurable(settings: KotlinCodeVisionProvider.KotlinCodeVisionSettings): ImmediateConfigurable {
|
fun createImmediateConfigurable(): ImmediateConfigurable {
|
||||||
return object : ImmediateConfigurable {
|
return object : ImmediateConfigurable {
|
||||||
override fun createComponent(listener: ChangeListener): JPanel {
|
override fun createComponent(listener: ChangeListener): JPanel = panel {}
|
||||||
return panel {}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val cases: List<ImmediateConfigurable.Case>
|
override val cases: List<ImmediateConfigurable.Case> = emptyList()
|
||||||
get() = listOf(
|
|
||||||
ImmediateConfigurable.Case(
|
|
||||||
KotlinBundle.message("hints.title.codevision.usages"),
|
|
||||||
"usages",
|
|
||||||
settings::showUsages
|
|
||||||
),
|
|
||||||
ImmediateConfigurable.Case(
|
|
||||||
KotlinBundle.message("hints.title.codevision.inheritors"),
|
|
||||||
"inheritors",
|
|
||||||
settings::showInheritors
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
override val mainCheckboxText: String
|
override val mainCheckboxText: String = ""
|
||||||
get() = KotlinBundle.message("hints.title.codevision.show.hints.for")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-19
@@ -27,25 +27,8 @@ fun logUsageStatistics(project: Project?, groupId: String, eventId: String, data
|
|||||||
project?.let { FUCounterUsageLogger.getInstance().logEvent(project, groupId, eventId, data) }
|
project?.let { FUCounterUsageLogger.getInstance().logEvent(project, groupId, eventId, data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createImmediateConfigurable(settings: KotlinCodeVisionProvider.KotlinCodeVisionSettings): ImmediateConfigurable {
|
fun createImmediateConfigurable(): ImmediateConfigurable {
|
||||||
return object : ImmediateConfigurable {
|
return object : ImmediateConfigurable {
|
||||||
val usagesText = KotlinBundle.message("hints.title.codevision.usages")
|
override fun createComponent(listener: ChangeListener): JPanel = panel {}
|
||||||
val inheritorsText = KotlinBundle.message("hints.title.codevision.inheritors")
|
|
||||||
|
|
||||||
private val usagesField = JBCheckBox(usagesText, settings.showUsages)
|
|
||||||
private val inheritorsField = JBCheckBox(inheritorsText, settings.showInheritors)
|
|
||||||
|
|
||||||
override fun createComponent(listener: ChangeListener): JPanel {
|
|
||||||
usagesField.isSelected = settings.showUsages
|
|
||||||
usagesField.addActionListener { settings.showUsages = usagesField.isSelected }
|
|
||||||
|
|
||||||
inheritorsField.isSelected = settings.showInheritors
|
|
||||||
inheritorsField.addActionListener { settings.showInheritors = inheritorsField.isSelected }
|
|
||||||
|
|
||||||
return panel {
|
|
||||||
row { usagesField(pushX) }
|
|
||||||
row { inheritorsField(pushX) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+13
-9
@@ -8,14 +8,15 @@ package org.jetbrains.kotlin.idea.codeInsight.codevision
|
|||||||
import com.intellij.codeInsight.hints.*
|
import com.intellij.codeInsight.hints.*
|
||||||
import com.intellij.lang.Language
|
import com.intellij.lang.Language
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.util.registry.Registry
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
|
|
||||||
@Suppress("UnstableApiUsage")
|
@Suppress("UnstableApiUsage")
|
||||||
class KotlinCodeVisionProvider : InlayHintsProvider<KotlinCodeVisionProvider.KotlinCodeVisionSettings> {
|
class KotlinCodeVisionProvider : InlayHintsProvider<NoSettings> {
|
||||||
|
|
||||||
override val key: SettingsKey<KotlinCodeVisionSettings> = SettingsKey("CodeVision")
|
override val key: SettingsKey<NoSettings> = SettingsKey("CodeVision")
|
||||||
override val name: String = KotlinBundle.message("hints.title.codevision")
|
override val name: String = KotlinBundle.message("hints.title.codevision")
|
||||||
override val previewText: String? = null
|
override val previewText: String? = null
|
||||||
|
|
||||||
@@ -24,16 +25,19 @@ class KotlinCodeVisionProvider : InlayHintsProvider<KotlinCodeVisionProvider.Kot
|
|||||||
|
|
||||||
override fun isLanguageSupported(language: Language): Boolean = language is KotlinLanguage
|
override fun isLanguageSupported(language: Language): Boolean = language is KotlinLanguage
|
||||||
|
|
||||||
override fun createConfigurable(settings: KotlinCodeVisionSettings): ImmediateConfigurable = createImmediateConfigurable(settings)
|
override fun createConfigurable(settings: NoSettings): ImmediateConfigurable = createImmediateConfigurable()
|
||||||
|
|
||||||
override fun createSettings(): KotlinCodeVisionSettings = KotlinCodeVisionSettings()
|
override fun createSettings(): NoSettings = NoSettings()
|
||||||
|
|
||||||
override fun getCollectorFor(
|
override fun getCollectorFor(
|
||||||
file: PsiFile, editor: Editor, settings: KotlinCodeVisionSettings, sink: InlayHintsSink
|
file: PsiFile, editor: Editor, settings: NoSettings, sink: InlayHintsSink
|
||||||
): InlayHintsCollector? {
|
): InlayHintsCollector? {
|
||||||
if (!settings.showUsages && !settings.showInheritors) return null
|
|
||||||
return KotlinCodeVisionHintsCollector(editor, settings.showUsages, settings.showInheritors, usagesLimit, inheritorsLimit)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class KotlinCodeVisionSettings(var showUsages: Boolean = false, var showInheritors: Boolean = false)
|
val showUsages = Registry.`is`("kotlin.code-vision.usages", false)
|
||||||
|
val showInheritors = Registry.`is`("kotlin.code-vision.inheritors", false)
|
||||||
|
|
||||||
|
if (!showUsages && !showInheritors) return null
|
||||||
|
|
||||||
|
return KotlinCodeVisionHintsCollector(editor, showUsages, showInheritors, usagesLimit, inheritorsLimit)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+16
-14
@@ -6,13 +6,18 @@
|
|||||||
package org.jetbrains.kotlin.idea.codeInsight.codevision
|
package org.jetbrains.kotlin.idea.codeInsight.codevision
|
||||||
|
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.intellij.openapi.util.registry.Registry
|
||||||
import com.intellij.testFramework.utils.inlays.InlayHintsProviderTestCase
|
import com.intellij.testFramework.utils.inlays.InlayHintsProviderTestCase
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.codevision.KotlinCodeVisionProvider.KotlinCodeVisionSettings
|
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
open class AbstractKotlinCodeVisionProviderTest : InlayHintsProviderTestCase() { // Abstract- prefix is just a convention for GenerateTests
|
open class AbstractKotlinCodeVisionProviderTest : InlayHintsProviderTestCase() { // Abstract- prefix is just a convention for GenerateTests
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val INHERITORS_KEY = "kotlin.code-vision.inheritors"
|
||||||
|
const val USAGES_KEY = "kotlin.code-vision.usages"
|
||||||
|
}
|
||||||
|
|
||||||
fun doTest(testPath: String) { // named according to the convention imposed by GenerateTests
|
fun doTest(testPath: String) { // named according to the convention imposed by GenerateTests
|
||||||
assertThatActualHintsMatch(testPath)
|
assertThatActualHintsMatch(testPath)
|
||||||
}
|
}
|
||||||
@@ -27,21 +32,18 @@ open class AbstractKotlinCodeVisionProviderTest : InlayHintsProviderTestCase() {
|
|||||||
codeVisionProvider.usagesLimit = usagesLimit
|
codeVisionProvider.usagesLimit = usagesLimit
|
||||||
codeVisionProvider.inheritorsLimit = inheritorsLimit
|
codeVisionProvider.inheritorsLimit = inheritorsLimit
|
||||||
|
|
||||||
val mode: KotlinCodeVisionSettings = when (InTextDirectivesUtils.findStringWithPrefixes(fileContents, "// MODE: ")) {
|
when (InTextDirectivesUtils.findStringWithPrefixes(fileContents, "// MODE: ")) {
|
||||||
"inheritors" -> inheritorsEnabled()
|
"inheritors" -> mode(usages = false, inheritors = true)
|
||||||
"usages" -> usagesEnabled()
|
"usages" -> mode(usages = true, inheritors = false)
|
||||||
"usages-&-inheritors" -> usagesAndInheritorsEnabled()
|
"usages-&-inheritors" -> mode(usages = true, inheritors = true)
|
||||||
else -> codeVisionDisabled()
|
else -> mode(usages = false, inheritors = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
testProvider("kotlinCodeVision.kt", fileContents, codeVisionProvider, mode)
|
testProvider("kotlinCodeVision.kt", fileContents, codeVisionProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun usagesAndInheritorsEnabled(): KotlinCodeVisionSettings = KotlinCodeVisionSettings(showUsages = true, showInheritors = true)
|
private fun mode(usages: Boolean, inheritors: Boolean) {
|
||||||
|
Registry.get(USAGES_KEY).setValue(usages)
|
||||||
private fun inheritorsEnabled(): KotlinCodeVisionSettings = KotlinCodeVisionSettings(showUsages = false, showInheritors = true)
|
Registry.get(INHERITORS_KEY).setValue(inheritors)
|
||||||
|
}
|
||||||
private fun usagesEnabled(): KotlinCodeVisionSettings = KotlinCodeVisionSettings(showUsages = true, showInheritors = false)
|
|
||||||
|
|
||||||
private fun codeVisionDisabled(): KotlinCodeVisionSettings = KotlinCodeVisionSettings(showUsages = false, showInheritors = false)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user