diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt index 832aaf3d2fb..342b8d72c36 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt @@ -9,16 +9,12 @@ import com.intellij.openapi.externalSystem.service.project.autoimport.AsyncFileC import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.newvfs.events.VFileEvent -import java.util.* fun addVfsListener(watcher: GradleScriptInputsWatcher) { VirtualFileManager.getInstance().addAsyncFileListener( object : AsyncFileChangeListenerBase() { - - private var files: Set = Collections.emptySet() - override fun isRelevant(path: String): Boolean { - return isInAffectedGradleProjectFiles(files, path) + return isInAffectedGradleProjectFiles(watcher.project, path) } override fun updateFile(file: VirtualFile, event: VFileEvent) { @@ -28,11 +24,9 @@ fun addVfsListener(watcher: GradleScriptInputsWatcher) { // do nothing override fun prepareFileDeletion(file: VirtualFile) {} override fun apply() {} - override fun reset() { - files = getAffectedGradleProjectFiles(watcher.project) - } + override fun reset() {} }, - watcher.project, + watcher.project ) } \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt.191 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt.191 index 3026fefe43a..01160790959 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt.191 +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt.191 @@ -5,26 +5,28 @@ package org.jetbrains.kotlin.idea.scripting.gradle -import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.newvfs.BulkFileListener import com.intellij.openapi.vfs.newvfs.events.VFileEvent +import com.intellij.util.concurrency.SequentialTaskExecutor fun addVfsListener(watcher: GradleScriptInputsWatcher) { watcher.project.messageBus.connect().subscribe( VirtualFileManager.VFS_CHANGES, object : BulkFileListener { + private val executor = + SequentialTaskExecutor.createSequentialApplicationPoolExecutor("GradleScriptInputsWatcherVfsChangesExecutor") + override fun after(events: List) { - ApplicationManager.getApplication().executeOnPooledThread { - if (watcher.project.isDisposed) return@executeOnPooledThread - val files = getAffectedGradleProjectFiles(watcher.project) + executor.submit(Runnable { + if (watcher.project.isDisposed) return@Runnable for (event in events) { - val file = event.file ?: return@executeOnPooledThread - if (isInAffectedGradleProjectFiles(files, event.path)) { + val file = event.file ?: continue + if (isInAffectedGradleProjectFiles(watcher.project, event.path)) { watcher.fileChanged(event.path, file.timeStamp) } } - } + }) } } ) diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt.201 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt.201 index e3659086bc5..16509e41bfe 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt.201 +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt.201 @@ -9,16 +9,12 @@ import com.intellij.openapi.externalSystem.autoimport.AsyncFileChangeListenerBas import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.newvfs.events.VFileEvent -import java.util.* fun addVfsListener(watcher: GradleScriptInputsWatcher) { VirtualFileManager.getInstance().addAsyncFileListener( object : AsyncFileChangeListenerBase() { - - private var files: Set = Collections.emptySet(); - override fun isRelevant(path: String): Boolean { - return isInAffectedGradleProjectFiles(files, path) + return isInAffectedGradleProjectFiles(watcher.project, path) } override fun updateFile(file: VirtualFile, event: VFileEvent) { @@ -27,11 +23,9 @@ fun addVfsListener(watcher: GradleScriptInputsWatcher) { // do nothing override fun apply() {} - override fun init() { - files = getAffectedGradleProjectFiles(watcher.project) - } + override fun init() {} }, - watcher.project, + watcher.project ) } \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelDataService.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelDataService.kt index 17e095867a5..7a712a52245 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelDataService.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelDataService.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationSnapshot import org.jetbrains.kotlin.idea.scripting.gradle.getGradleScriptInputsStamp +import org.jetbrains.kotlin.idea.scripting.gradle.saveGradleProjectRootsAfterImport import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource @@ -55,7 +56,11 @@ class KotlinDslScriptModelDataService : AbstractProjectDataService( project, projectSettings.externalProjectPath, diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/utils.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/utils.kt index da1ab66e612..f860b66e699 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/utils.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/utils.kt @@ -12,14 +12,12 @@ import com.intellij.openapi.util.registry.Registry import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.* import com.intellij.psi.impl.source.tree.LeafPsiElement -import com.intellij.util.io.systemIndependentPath import org.gradle.util.GradleVersion import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtScriptInitializer import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType -import org.jetbrains.plugins.gradle.GradleManager import org.jetbrains.plugins.gradle.settings.GradleProjectSettings import org.jetbrains.plugins.gradle.util.GradleConstants @@ -28,34 +26,41 @@ private val sections = arrayListOf("buildscript", "plugins", "initscript", "plug fun isGradleKotlinScript(virtualFile: VirtualFile) = virtualFile.name.endsWith(".gradle.kts") fun isInAffectedGradleProjectFiles(project: Project, filePath: String): Boolean { - // fast path - if (!filePath.contains("gradle")) return false + if (filePath.endsWith("/gradle.properties")) return true + if (filePath.endsWith("/gradle-wrapper.properties")) return true - val affectedFiles = getAffectedGradleProjectFiles(project) - return isInAffectedGradleProjectFiles(affectedFiles, filePath) -} + if (filePath.endsWith(".gradle") || filePath.endsWith(".gradle.kts")) { + if (ApplicationManager.getApplication().isUnitTestModeWithoutAffectedGradleProjectFilesCheck) { + return true + } -fun isInAffectedGradleProjectFiles(files: Set, filePath: String): Boolean { - if (ApplicationManager.getApplication().isUnitTestModeWithoutAffectedGradleProjectFilesCheck) { - return true + return filePath.substringBeforeLast("/") in getGradleProjectsRoots(project) } - return filePath in files + return false } -fun getAffectedGradleProjectFiles(project: Project): Set { +private var cachedGradleProjectsRoots: Set? = null + +private fun getGradleProjectsRoots(project: Project): Set { + if (cachedGradleProjectsRoots == null) { + cachedGradleProjectsRoots = computeGradleProjectRoots(project) + } + return cachedGradleProjectsRoots ?: emptySet() +} + +fun saveGradleProjectRootsAfterImport(roots: Set) { + cachedGradleProjectsRoots = roots +} + +private fun computeGradleProjectRoots(project: Project): Set { val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID) if (gradleSettings.getLinkedProjectsSettings().isEmpty()) return setOf() val projectSettings = gradleSettings.getLinkedProjectsSettings().filterIsInstance().firstOrNull() ?: return setOf() - return ExternalSystemApiUtil.getAllManagers() - .filterIsInstance() - .firstOrNull() - ?.getAffectedExternalProjectFiles(projectSettings.externalProjectPath, project) - ?.mapTo(mutableSetOf()) { it.toPath().systemIndependentPath } - ?: setOf() + return projectSettings.modules.takeIf { it.isNotEmpty() } ?: setOf(projectSettings.externalProjectPath) } fun getGradleScriptInputsStamp(