From 3d86e92bf584bcc17b61bb6160b22a73848548be Mon Sep 17 00:00:00 2001 From: Sergey Rostov Date: Tue, 16 Jun 2020 19:35:08 +0300 Subject: [PATCH] gradle.kts standalone scripts: show actions inside single notification --- .../configuration/DefaultScriptingSupport.kt | 13 ++-- .../loader/ScriptConfigurationLoader.kt | 9 +-- .../GradleScriptNotificationProvider.kt | 23 ++++++- .../GradleLegacyScriptConfigurationLoader.kt | 25 +++++++- .../legacy/GradleStandaloneScriptActions.kt | 62 +++++++++++++++++++ idea/resources/META-INF/gradle.xml | 3 + idea/resources/META-INF/gradle.xml.201 | 3 + 7 files changed, 121 insertions(+), 17 deletions(-) create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/legacy/GradleStandaloneScriptActions.kt diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/DefaultScriptingSupport.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/DefaultScriptingSupport.kt index e20561f0079..ee7fdbf8077 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/DefaultScriptingSupport.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/DefaultScriptingSupport.kt @@ -175,14 +175,15 @@ class DefaultScriptingSupport(manager: CompositeScriptConfigurationManager) : De loaders.firstOrNull { it.loadDependencies(isFirstLoad, file, scriptDefinition, loadingContext) } } else { val autoReloadEnabled = KotlinScriptingSettings.getInstance(project).autoReloadConfigurations(scriptDefinition) - val postponeLoading = !skipNotification && !autoReloadEnabled && async.any { it.isPostponedLoad(virtualFile) } - val forceSkipNotification = skipNotification || autoReloadEnabled || postponeLoading + val forceSkipNotification = skipNotification || autoReloadEnabled - if (postponeLoading) { - LoadScriptConfigurationNotificationFactory.showNotification(virtualFile, project) { - runAsyncLoaders(file, virtualFile, scriptDefinition, async, forceSkipNotification) + val intercepted = !forceSkipNotification && async.any { + it.interceptBackgroundLoading(virtualFile) { + runAsyncLoaders(file, virtualFile, scriptDefinition, listOf(it), true) } - } else { + } + + if (!intercepted) { runAsyncLoaders(file, virtualFile, scriptDefinition, async, forceSkipNotification) } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/loader/ScriptConfigurationLoader.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/loader/ScriptConfigurationLoader.kt index d35702497b5..c52f99deb5d 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/loader/ScriptConfigurationLoader.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/loader/ScriptConfigurationLoader.kt @@ -15,15 +15,10 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition * @see [org.jetbrains.kotlin.idea.core.script.configuration.DefaultScriptConfigurationManager] for more details. */ interface ScriptConfigurationLoader { - /** - * Show notification before doing load - * - * (by default loading notification will be shown only after loading, to check that configuration is changed) - */ - fun isPostponedLoad(virtualFile: VirtualFile): Boolean = false - fun shouldRunInBackground(scriptDefinition: ScriptDefinition): Boolean = false + fun interceptBackgroundLoading(file: VirtualFile, doLoad: () -> Unit): Boolean = false + /** * Implementation should load configuration and call `context.suggestNewConfiguration` or `saveNewConfiguration`. * diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptNotificationProvider.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptNotificationProvider.kt index 8fe353181d0..cc4cb8e91c1 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptNotificationProvider.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptNotificationProvider.kt @@ -14,6 +14,8 @@ import com.intellij.ui.EditorNotificationPanel import com.intellij.ui.EditorNotifications import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle +import org.jetbrains.kotlin.idea.core.util.KotlinIdeaCoreBundle +import org.jetbrains.kotlin.idea.scripting.gradle.legacy.GradleStandaloneScriptActions import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsLocator.NotificationKind.* import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager import org.jetbrains.kotlin.idea.scripting.gradle.roots.Imported @@ -77,7 +79,26 @@ class GradleScriptNotificationProvider(private val project: Project) : contextHelp(KotlinIdeaGradleBundle.message("notification.notEvaluatedInLastImport.info")) } standalone -> EditorNotificationPanel().apply { - text(KotlinIdeaGradleBundle.message("notification.standalone.text")) + val actions = GradleStandaloneScriptActions.getInstance(project).byFile[file] + if (actions != null) { + text( + KotlinIdeaGradleBundle.message("notification.standalone.text") + + ". " + + KotlinIdeaCoreBundle.message("notification.text.script.configuration.has.been.changed") + ) + + + createActionLabel(KotlinIdeaCoreBundle.message("notification.action.text.load.script.configuration")) { + actions.reload() + } + + createActionLabel(KotlinIdeaCoreBundle.message("notification.action.text.enable.auto.reload")) { + actions.toggleAutoReload() + } + } else { + text(KotlinIdeaGradleBundle.message("notification.standalone.text")) + } + createActionLabel(KotlinIdeaGradleBundle.message("notification.standalone.disableScriptAction")) { rootsManager.updateStandaloneScripts { removeStandaloneScript(file.path) diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/legacy/GradleLegacyScriptConfigurationLoader.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/legacy/GradleLegacyScriptConfigurationLoader.kt index ace4243c23e..d81f7dfb3a0 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/legacy/GradleLegacyScriptConfigurationLoader.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/legacy/GradleLegacyScriptConfigurationLoader.kt @@ -10,7 +10,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch -import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager +import org.jetbrains.kotlin.idea.core.script.LoadScriptConfigurationNotificationFactory import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs import org.jetbrains.kotlin.idea.core.script.configuration.loader.DefaultScriptConfigurationLoader import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoadingContext @@ -30,7 +30,23 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition class GradleLegacyScriptConfigurationLoader(project: Project) : DefaultScriptConfigurationLoader(project) { private val buildRootsManager = GradleBuildRootsManager.getInstance(project) - override fun isPostponedLoad(virtualFile: VirtualFile): Boolean = isGradleKotlinScript(virtualFile) + override fun interceptBackgroundLoading(file: VirtualFile, doLoad: () -> Unit): Boolean { + if (!isGradleKotlinScript(file)) return false + val info = buildRootsManager.findScriptBuildRoot(file) ?: return false + + if (info.standalone) { + val actionsManager = GradleStandaloneScriptActions.getInstance(project) + val fileActions = actionsManager.ForFile(file, doLoad) + actionsManager.byFile[file] = fileActions + fileActions.updateNotification() + } else { + LoadScriptConfigurationNotificationFactory.showNotification(file, project) { + doLoad() + } + } + + return true + } override fun shouldRunInBackground(scriptDefinition: ScriptDefinition) = true @@ -44,13 +60,16 @@ class GradleLegacyScriptConfigurationLoader(project: Project) : DefaultScriptCon if (!isGradleKotlinScript(vFile)) return false + GradleStandaloneScriptActions.getInstance(project) + .byFile.remove(vFile)?.updateNotification() + if (!buildRootsManager.isAffectedGradleProjectFile(vFile.path)) { // not known gradle file and not configured as standalone script // skip return true } - // Gradle read files from FS + // Gradle read files from FS, so let's save all docs GlobalScope.launch(EDT(project)) { runWriteAction { FileDocumentManager.getInstance().saveAllDocuments() diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/legacy/GradleStandaloneScriptActions.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/legacy/GradleStandaloneScriptActions.kt new file mode 100644 index 00000000000..8cf5b1ce09d --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/legacy/GradleStandaloneScriptActions.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.scripting.gradle.legacy + +import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings +import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager +import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition + +class GradleStandaloneScriptActions(val project: Project) { + val byFile = mutableMapOf() + + inner class ForFile( + val file: VirtualFile, + private val doLoad: () -> Unit + ) { + private val scriptDefinition + get() = file.findScriptDefinition(project) + + val isAutoReloadAvailable: Boolean + val isAutoReloadEnabled: Boolean + + init { + val scriptDefinition = scriptDefinition + if (scriptDefinition != null) { + isAutoReloadAvailable = true + isAutoReloadEnabled = KotlinScriptingSettings.getInstance(project) + .autoReloadConfigurations(scriptDefinition) + } else { + isAutoReloadAvailable = false + isAutoReloadEnabled = false + } + } + + fun toggleAutoReload() { + KotlinScriptingSettings.getInstance(project).setAutoReloadConfigurations(scriptDefinition!!, !isAutoReloadEnabled) + updateNotification() + } + + fun reload() { + byFile.remove(file) + doLoad() + updateNotification() + } + + fun updateNotification() { + GradleBuildRootsManager.getInstance(project).updateNotifications(false) { + it == file.path + } + } + } + + companion object { + fun getInstance(project: Project) = + ServiceManager.getService(project, GradleStandaloneScriptActions::class.java) + } +} \ No newline at end of file diff --git a/idea/resources/META-INF/gradle.xml b/idea/resources/META-INF/gradle.xml index 23325075261..b0e2a296925 100644 --- a/idea/resources/META-INF/gradle.xml +++ b/idea/resources/META-INF/gradle.xml @@ -37,6 +37,9 @@ This setting currently affects only HMPP projects. You may need to delete existing test configurations for the change to take place." defaultValue="true" restartRequired="false"/> + + diff --git a/idea/resources/META-INF/gradle.xml.201 b/idea/resources/META-INF/gradle.xml.201 index bc1cec9a718..2022e33c2c2 100644 --- a/idea/resources/META-INF/gradle.xml.201 +++ b/idea/resources/META-INF/gradle.xml.201 @@ -39,6 +39,9 @@ This setting currently affects only HMPP projects. You may need to delete existing test configurations for the change to take place." defaultValue="true" restartRequired="false"/> + +