gradle scripts: custom notification wording gradle with default scripting support (gradle older then 6.0)

This commit is contained in:
Sergey Rostov
2020-06-18 20:46:49 +03:00
parent 37fbc75008
commit 9f4569e5a1
13 changed files with 178 additions and 208 deletions
@@ -1,118 +0,0 @@
/*
* 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.core.script
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.Ref
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.ui.EditorNotificationPanel
import com.intellij.ui.HyperlinkLabel
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
import org.jetbrains.kotlin.idea.core.util.KotlinIdeaCoreBundle
import org.jetbrains.kotlin.psi.UserDataProperty
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
object LoadScriptConfigurationNotificationFactory {
fun showNotification(file: VirtualFile, project: Project, onClick: () -> Unit): Boolean {
file.addLoadConfigurationNotificationPanel(project, onClick)
return true
}
fun hideNotification(file: VirtualFile, project: Project): Boolean {
file.removeLoadConfigurationNotificationPanel(project)
return true
}
@TestOnly
fun hasNotification(file: VirtualFile, project: Project): Boolean {
return FileEditorManager.getInstance(project).getSelectedEditor(file)?.notificationPanel != null
}
@TestOnly
fun performSuggestedLoading(file: VirtualFile, project: Project): Boolean {
val notificationPanel = FileEditorManager.getInstance(project).getSelectedEditor(file)?.notificationPanel
?: return false
notificationPanel.onClick.invoke()
return true
}
private fun VirtualFile.removeLoadConfigurationNotificationPanel(project: Project) {
withSelectedEditor(project) { manager ->
notificationPanel?.let {
manager.removeTopComponent(this, it)
}
notificationPanel = null
}
}
private fun VirtualFile.addLoadConfigurationNotificationPanel(
project: Project,
onClick: () -> Unit
) {
withSelectedEditor(project) { manager ->
val existingPanel = notificationPanel
if (existingPanel != null) {
existingPanel.onClick = onClick
return@withSelectedEditor
}
val panel = NewLoadConfigurationNotificationPanel(onClick, project, this@addLoadConfigurationNotificationPanel)
notificationPanel = panel
manager.addTopComponent(this, panel)
}
}
private fun VirtualFile.withSelectedEditor(project: Project, f: FileEditor.(FileEditorManager) -> Unit) {
ApplicationManager.getApplication().invokeLater {
if (project.isDisposed) return@invokeLater
val fileEditorManager = FileEditorManager.getInstance(project)
fileEditorManager.getAllEditors(this).forEach {
f(it, fileEditorManager)
}
}
}
private var FileEditor.notificationPanel: NewLoadConfigurationNotificationPanel?
by UserDataProperty<FileEditor, NewLoadConfigurationNotificationPanel>(Key.create("load.script.configuration.panel"))
private class NewLoadConfigurationNotificationPanel(
var onClick: () -> Unit,
project: Project,
file: VirtualFile
) : EditorNotificationPanel() {
init {
setText(KotlinIdeaCoreBundle.message("notification.text.script.configuration.has.been.changed"))
createComponentActionLabel(KotlinIdeaCoreBundle.message("notification.action.text.load.script.configuration")) {
onClick()
file.removeLoadConfigurationNotificationPanel(project)
}
createComponentActionLabel(KotlinIdeaCoreBundle.message("notification.action.text.enable.auto.reload")) {
onClick()
file.removeLoadConfigurationNotificationPanel(project)
val scriptDefinition = file.findScriptDefinition(project) ?: return@createComponentActionLabel
KotlinScriptingSettings.getInstance(project).setAutoReloadConfigurations(scriptDefinition, true)
}
}
private fun EditorNotificationPanel.createComponentActionLabel(labelText: String, callback: (HyperlinkLabel) -> Unit) {
val label: Ref<HyperlinkLabel> = Ref.create()
val action = Runnable {
callback(label.get())
}
label.set(createActionLabel(labelText, action))
}
}
}
@@ -177,8 +177,11 @@ class DefaultScriptingSupport(manager: CompositeScriptConfigurationManager) : De
val autoReloadEnabled = KotlinScriptingSettings.getInstance(project).autoReloadConfigurations(scriptDefinition)
val forceSkipNotification = skipNotification || autoReloadEnabled
// sync loaders can do something, let's recheck
val isFirstLoadActual = getCachedConfigurationState(virtualFile)?.applied != null
val intercepted = !forceSkipNotification && async.any {
it.interceptBackgroundLoading(virtualFile) {
it.interceptBackgroundLoading(virtualFile, isFirstLoadActual) {
runAsyncLoaders(file, virtualFile, scriptDefinition, listOf(it), true)
}
}
@@ -263,7 +266,7 @@ class DefaultScriptingSupport(manager: CompositeScriptConfigurationManager) : De
setLoadedConfiguration(file, newResult)
LoadScriptConfigurationNotificationFactory.hideNotification(file, project)
hideInterceptedNotification(file)
val newConfiguration = newResult.configuration
if (newConfiguration == null) {
@@ -340,7 +343,7 @@ class DefaultScriptingSupport(manager: CompositeScriptConfigurationManager) : De
}
// this notification can be shown before something will be in cache
LoadScriptConfigurationNotificationFactory.hideNotification(file, project)
hideInterceptedNotification(file)
}
fun updateScriptDefinitionsReferences() {
@@ -348,12 +351,18 @@ class DefaultScriptingSupport(manager: CompositeScriptConfigurationManager) : De
cache.allApplied().forEach { (file, _) ->
saveReports(file, listOf())
file.removeScriptDependenciesNotificationPanel(project)
LoadScriptConfigurationNotificationFactory.hideNotification(file, project)
hideInterceptedNotification(file)
}
cache.clear()
}
fun hideInterceptedNotification(file: VirtualFile) {
loaders.forEach {
it.hideInterceptedNotification(file)
}
}
companion object {
fun getInstance(project: Project) =
(ScriptConfigurationManager.getInstance(project) as CompositeScriptConfigurationManager).default
@@ -17,7 +17,9 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
interface ScriptConfigurationLoader {
fun shouldRunInBackground(scriptDefinition: ScriptDefinition): Boolean = false
fun interceptBackgroundLoading(file: VirtualFile, doLoad: () -> Unit): Boolean = false
fun interceptBackgroundLoading(file: VirtualFile, isFirstLoad: Boolean, doLoad: () -> Unit): Boolean = false
fun hideInterceptedNotification(file: VirtualFile) = Unit
/**
* Implementation should load configuration and call `context.suggestNewConfiguration` or `saveNewConfiguration`.