Show notification if there are more than one script definition applicable for one script file (KT-24466)

^KT-24466 Fixed
This commit is contained in:
Natalia Selezneva
2018-07-31 10:06:34 +03:00
parent 99e1d4ab45
commit 02c1ae62c3
10 changed files with 116 additions and 0 deletions
@@ -124,6 +124,8 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
updateDefinitions()
}
fun getAllDefinitions() = currentDefinitions
override fun getDefaultScriptDefinition(): KotlinScriptDefinition {
return StandardIdeScriptDefinition(project)
}
@@ -154,6 +156,12 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
// TODO: clear by script type/definition
ServiceManager.getService(project, ScriptDependenciesCache::class.java).clear()
ApplicationManager.getApplication().invokeLater {
if (!project.isDisposed) {
EditorNotifications.getInstance(project).updateAllNotifications()
}
}
}
private fun ScriptDefinitionContributor.safeGetDefinitions(): List<KotlinScriptDefinition> {
@@ -19,6 +19,11 @@ import com.intellij.util.xmlb.XmlSerializerUtil
class KotlinScriptingSettings : PersistentStateComponent<KotlinScriptingSettings> {
var isAutoReloadEnabled = false
/**
* true if notification about multiple script definition applicable for one script file is suppressed
*/
var suppressDefinitionsCheck = false
override fun loadState(state: KotlinScriptingSettings) {
XmlSerializerUtil.copyBean(state, this)
}
+1
View File
@@ -417,6 +417,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<lang.commenter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinCommenter"/>
<lang.psiStructureViewFactory language="kotlin" implementationClass="org.jetbrains.kotlin.idea.structureView.KotlinStructureViewFactory"/>
<structureViewBuilder order="first" key="CLASS" factoryClass="org.jetbrains.kotlin.idea.structureView.KtClsStructureViewBuilderProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.script.configutation.MultipleScriptDefinitionsChecker"/>
<lang.foldingBuilder language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinFoldingBuilder"/>
<lang.formatter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.formatter.KotlinFormattingModelBuilder"/>
+1
View File
@@ -415,6 +415,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<lang.commenter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinCommenter"/>
<lang.psiStructureViewFactory language="kotlin" implementationClass="org.jetbrains.kotlin.idea.structureView.KotlinStructureViewFactory"/>
<structureViewBuilder order="first" key="CLASS" factoryClass="org.jetbrains.kotlin.idea.structureView.KtClsStructureViewBuilderProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.script.configutation.MultipleScriptDefinitionsChecker"/>
<lang.foldingBuilder language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinFoldingBuilder"/>
<lang.formatter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.formatter.KotlinFormattingModelBuilder"/>
+1
View File
@@ -416,6 +416,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<lang.commenter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinCommenter"/>
<lang.psiStructureViewFactory language="kotlin" implementationClass="org.jetbrains.kotlin.idea.structureView.KotlinStructureViewFactory"/>
<structureViewBuilder order="first" key="CLASS" factoryClass="org.jetbrains.kotlin.idea.structureView.KtClsStructureViewBuilderProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.script.configutation.MultipleScriptDefinitionsChecker"/>
<lang.foldingBuilder language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinFoldingBuilder"/>
<lang.formatter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.formatter.KotlinFormattingModelBuilder"/>
+1
View File
@@ -417,6 +417,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<lang.commenter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinCommenter"/>
<lang.psiStructureViewFactory language="kotlin" implementationClass="org.jetbrains.kotlin.idea.structureView.KotlinStructureViewFactory"/>
<structureViewBuilder order="first" key="CLASS" factoryClass="org.jetbrains.kotlin.idea.structureView.KtClsStructureViewBuilderProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.script.configutation.MultipleScriptDefinitionsChecker"/>
<lang.foldingBuilder language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinFoldingBuilder"/>
<lang.formatter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.formatter.KotlinFormattingModelBuilder"/>
+1
View File
@@ -415,6 +415,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<lang.commenter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinCommenter"/>
<lang.psiStructureViewFactory language="kotlin" implementationClass="org.jetbrains.kotlin.idea.structureView.KotlinStructureViewFactory"/>
<structureViewBuilder order="first" key="CLASS" factoryClass="org.jetbrains.kotlin.idea.structureView.KtClsStructureViewBuilderProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.script.configutation.MultipleScriptDefinitionsChecker"/>
<lang.foldingBuilder language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinFoldingBuilder"/>
<lang.formatter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.formatter.KotlinFormattingModelBuilder"/>
+1
View File
@@ -415,6 +415,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<lang.commenter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinCommenter"/>
<lang.psiStructureViewFactory language="kotlin" implementationClass="org.jetbrains.kotlin.idea.structureView.KotlinStructureViewFactory"/>
<structureViewBuilder order="first" key="CLASS" factoryClass="org.jetbrains.kotlin.idea.structureView.KtClsStructureViewBuilderProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.script.configutation.MultipleScriptDefinitionsChecker"/>
<lang.foldingBuilder language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinFoldingBuilder"/>
<lang.formatter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.formatter.KotlinFormattingModelBuilder"/>
+1
View File
@@ -416,6 +416,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<lang.commenter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinCommenter"/>
<lang.psiStructureViewFactory language="kotlin" implementationClass="org.jetbrains.kotlin.idea.structureView.KotlinStructureViewFactory"/>
<structureViewBuilder order="first" key="CLASS" factoryClass="org.jetbrains.kotlin.idea.structureView.KtClsStructureViewBuilderProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.script.configutation.MultipleScriptDefinitionsChecker"/>
<lang.foldingBuilder language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinFoldingBuilder"/>
<lang.formatter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.formatter.KotlinFormattingModelBuilder"/>
@@ -0,0 +1,96 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.script.configutation
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.Ref
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiManager
import com.intellij.ui.EditorNotificationPanel
import com.intellij.ui.EditorNotifications
import com.intellij.ui.HyperlinkLabel
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
import org.jetbrains.kotlin.idea.core.script.StandardIdeScriptDefinition
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.script.KotlinScriptDefinition
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
import org.jetbrains.kotlin.scripting.compiler.plugin.KotlinScriptDefinitionAdapterFromNewAPIBase
class MultipleScriptDefinitionsChecker(private val project: Project) : EditorNotifications.Provider<EditorNotificationPanel>() {
override fun getKey(): Key<EditorNotificationPanel> =
KEY
override fun createNotificationPanel(file: VirtualFile, fileEditor: FileEditor): EditorNotificationPanel? {
if (file.fileType != KotlinFileType.INSTANCE) return null
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return null
if (!ktFile.isScript()) return null
if (KotlinScriptingSettings.getInstance(ktFile.project).suppressDefinitionsCheck) return null
val allApplicableDefinitions = ScriptDefinitionsManager.getInstance(project)
.getAllDefinitions()
.filter { it !is StandardIdeScriptDefinition && it.isScript(ktFile.name) }
.toList()
if (allApplicableDefinitions.size < 2) return null
return createNotification(
ktFile,
allApplicableDefinitions
)
}
companion object {
private val KEY = Key.create<EditorNotificationPanel>("MultipleScriptDefinitionsChecker")
private fun createNotification(psiFile: KtFile, defs: List<KotlinScriptDefinition>): EditorNotificationPanel {
return EditorNotificationPanel().apply {
setText("Multiple script definitions are applicable for this script. ${defs.first().name} is used")
createComponentActionLabel("Show all") {
val list = JBPopupFactory.getInstance().createListPopup(
object : BaseListPopupStep<KotlinScriptDefinition>(null, defs) {
override fun getTextFor(value: KotlinScriptDefinition): String {
return when (value) {
is KotlinScriptDefinitionFromAnnotatedTemplate -> {
value.name + " (${value.scriptFilePattern})"
}
is KotlinScriptDefinitionAdapterFromNewAPIBase -> {
value.name + " (${value.fileExtension})"
}
is StandardIdeScriptDefinition -> {
value.name + " (${KotlinParserDefinition.STD_SCRIPT_EXT})"
}
else -> value.name
}
}
}
)
list.showUnderneathOf(it)
}
createComponentActionLabel("Ignore") {
KotlinScriptingSettings.getInstance(psiFile.project).suppressDefinitionsCheck = true
EditorNotifications.getInstance(psiFile.project).updateAllNotifications()
}
}
}
private fun EditorNotificationPanel.createComponentActionLabel(labelText: String, callback: (HyperlinkLabel) -> Unit) {
val label: Ref<HyperlinkLabel> = Ref.create()
label.set(createActionLabel(labelText) {
callback(label.get())
})
}
}
}