Show notification "Gradle projects need to be imported" when build.gradle.kts file changed

^KT-19165 Fixed
This commit is contained in:
Natalia Selezneva
2018-02-12 13:01:54 +03:00
parent 63aeaf9cd5
commit 790cf1aa58
5 changed files with 131 additions and 1 deletions
@@ -62,6 +62,16 @@ class ScriptDefinitionsManager(private val project: Project): ScriptDefinitionPr
updateDefinitions()
}
fun getDefinitionsBy(contributor: ScriptDefinitionContributor): List<KotlinScriptDefinition> = lock.write {
val notLoadedYet = definitions.isEmpty()
if (notLoadedYet) return emptyList()
if (contributor !in definitionsByContributor) error("Unknown contributor: ${contributor.id}")
if (contributor.isError()) return emptyList()
return definitionsByContributor[contributor] ?: emptyList()
}
private fun currentDefinitions(): List<KotlinScriptDefinition> {
val hasDefinitions = definitions.isNotEmpty()
when {
@@ -107,7 +107,7 @@ class ScriptDependenciesUpdater(
}
}
private fun requestUpdate(files: Iterable<VirtualFile>) {
fun requestUpdate(files: Iterable<VirtualFile>) {
files.forEach { file ->
if (!file.isValid) {
cache.delete(file)
@@ -71,6 +71,8 @@ class GradleScriptDefinitionsContributor(private val project: Project): ScriptDe
}
}
project.messageBus.connect(project).subscribe(GradleSettingsListener.TOPIC, listener)
ServiceManager.getService(project, ScriptModificationListener::class.java)
}
override fun getDefinitions(): List<KotlinScriptDefinition> {
@@ -0,0 +1,115 @@
/*
* Copyright 2000-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.core.script
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.Result
import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.event.DocumentEvent
import com.intellij.openapi.editor.event.DocumentListener
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.vfs.newvfs.BulkFileListener
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
import com.intellij.psi.PsiDocumentManager
import com.intellij.util.ui.update.MergingUpdateQueue
import com.intellij.util.ui.update.MergingUpdateQueue.ANY_COMPONENT
import com.intellij.util.ui.update.Update
import org.jetbrains.plugins.gradle.service.project.GradleAutoImportAware
class ScriptModificationListener(private val project: Project) {
private val changedDocuments = HashSet<Document>()
private val changedDocumentsQueue = MergingUpdateQueue("ScriptModificationListener: Scripts queue", 1000, false, ANY_COMPONENT, project)
init {
showNotificationIfScriptChangedListener()
saveScriptAfterModificationListener()
}
private fun showNotificationIfScriptChangedListener() {
project.messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, object : BulkFileListener.Adapter() {
override fun after(events: List<VFileEvent>) {
if (ApplicationManager.getApplication().isUnitTestMode) return
val modifiedScripts = events.mapNotNull {
it.file?.takeIf { isGradleScript(it) }
}
// Workaround for IDEA-182367 (fixed in IDEA 181.3666)
if (modifiedScripts.isNotEmpty()) {
if (modifiedScripts.any {
GradleAutoImportAware().getAffectedExternalProjectPath(it.path, project) != null
}) {
return
}
ExternalProjectsManager.getInstance(project).externalProjectsWatcher.markDirty(project.basePath)
}
}
})
}
private fun saveScriptAfterModificationListener() {
// partially copied from ExternalSystemProjectsWatcherImpl before fix will be implemented in IDEA:
// "Gradle projects need to be imported" notification should be shown when kotlin script is modified
val busConnection = project.messageBus.connect(changedDocumentsQueue)
changedDocumentsQueue.activate()
EditorFactory.getInstance().eventMulticaster.addDocumentListener(object : DocumentListener {
override fun documentChanged(event: DocumentEvent) {
if (project.isDisposed) return
val doc = event.document
val file = FileDocumentManager.getInstance().getFile(doc) ?: return
if (isGradleScript(file)) {
synchronized(changedDocuments) {
changedDocuments.add(doc)
}
changedDocumentsQueue.queue(object : Update(this) {
override fun run() {
var copy: Array<Document> = emptyArray()
synchronized(changedDocuments) {
copy = changedDocuments.toTypedArray()
changedDocuments.clear()
}
ExternalSystemUtil.invokeLater(project) {
object : WriteAction<Any>() {
override fun run(result: Result<Any>) {
for (each in copy) {
PsiDocumentManager.getInstance(project).commitDocument(each)
(FileDocumentManager.getInstance() as? FileDocumentManagerImpl)?.saveDocument(each, false)
}
}
}.execute()
}
}
})
}
}
}, busConnection)
}
private fun isGradleScript(file: VirtualFile): Boolean {
if (!ProjectRootManager.getInstance(project).fileIndex.isInContent(file)) return false
val contributor = ScriptDefinitionContributor.find<GradleScriptDefinitionsContributor>(project) ?: return false
return ScriptDefinitionsManager.getInstance(project).getDefinitionsBy(contributor).any {
it.isScript(file.name)
}
}
}
+3
View File
@@ -341,6 +341,9 @@
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.util.ProjectJob"
serviceImplementation="org.jetbrains.kotlin.idea.core.util.ProjectJob"/>
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.ScriptModificationListener"
serviceImplementation="org.jetbrains.kotlin.idea.core.script.ScriptModificationListener"/>
<errorHandler implementation="org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter"/>
<internalFileTemplate name="Kotlin File"/>