.gradle.kts: fix freezes by avoiding fs walking
^KT-36502 Fixed
This commit is contained in:
+3
-9
@@ -9,16 +9,12 @@ import com.intellij.openapi.externalSystem.service.project.autoimport.AsyncFileC
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.openapi.vfs.VirtualFileManager
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
|
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
fun addVfsListener(watcher: GradleScriptInputsWatcher) {
|
fun addVfsListener(watcher: GradleScriptInputsWatcher) {
|
||||||
VirtualFileManager.getInstance().addAsyncFileListener(
|
VirtualFileManager.getInstance().addAsyncFileListener(
|
||||||
object : AsyncFileChangeListenerBase() {
|
object : AsyncFileChangeListenerBase() {
|
||||||
|
|
||||||
private var files: Set<String> = Collections.emptySet()
|
|
||||||
|
|
||||||
override fun isRelevant(path: String): Boolean {
|
override fun isRelevant(path: String): Boolean {
|
||||||
return isInAffectedGradleProjectFiles(files, path)
|
return isInAffectedGradleProjectFiles(watcher.project, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateFile(file: VirtualFile, event: VFileEvent) {
|
override fun updateFile(file: VirtualFile, event: VFileEvent) {
|
||||||
@@ -28,11 +24,9 @@ fun addVfsListener(watcher: GradleScriptInputsWatcher) {
|
|||||||
// do nothing
|
// do nothing
|
||||||
override fun prepareFileDeletion(file: VirtualFile) {}
|
override fun prepareFileDeletion(file: VirtualFile) {}
|
||||||
override fun apply() {}
|
override fun apply() {}
|
||||||
override fun reset() {
|
override fun reset() {}
|
||||||
files = getAffectedGradleProjectFiles(watcher.project)
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
watcher.project,
|
watcher.project
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+9
-7
@@ -5,26 +5,28 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||||
|
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
import com.intellij.openapi.vfs.VirtualFileManager
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener
|
import com.intellij.openapi.vfs.newvfs.BulkFileListener
|
||||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
|
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
|
||||||
|
import com.intellij.util.concurrency.SequentialTaskExecutor
|
||||||
|
|
||||||
fun addVfsListener(watcher: GradleScriptInputsWatcher) {
|
fun addVfsListener(watcher: GradleScriptInputsWatcher) {
|
||||||
watcher.project.messageBus.connect().subscribe(
|
watcher.project.messageBus.connect().subscribe(
|
||||||
VirtualFileManager.VFS_CHANGES,
|
VirtualFileManager.VFS_CHANGES,
|
||||||
object : BulkFileListener {
|
object : BulkFileListener {
|
||||||
|
private val executor =
|
||||||
|
SequentialTaskExecutor.createSequentialApplicationPoolExecutor("GradleScriptInputsWatcherVfsChangesExecutor")
|
||||||
|
|
||||||
override fun after(events: List<VFileEvent>) {
|
override fun after(events: List<VFileEvent>) {
|
||||||
ApplicationManager.getApplication().executeOnPooledThread {
|
executor.submit(Runnable {
|
||||||
if (watcher.project.isDisposed) return@executeOnPooledThread
|
if (watcher.project.isDisposed) return@Runnable
|
||||||
val files = getAffectedGradleProjectFiles(watcher.project)
|
|
||||||
for (event in events) {
|
for (event in events) {
|
||||||
val file = event.file ?: return@executeOnPooledThread
|
val file = event.file ?: continue
|
||||||
if (isInAffectedGradleProjectFiles(files, event.path)) {
|
if (isInAffectedGradleProjectFiles(watcher.project, event.path)) {
|
||||||
watcher.fileChanged(event.path, file.timeStamp)
|
watcher.fileChanged(event.path, file.timeStamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-9
@@ -9,16 +9,12 @@ import com.intellij.openapi.externalSystem.autoimport.AsyncFileChangeListenerBas
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.openapi.vfs.VirtualFileManager
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
|
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
fun addVfsListener(watcher: GradleScriptInputsWatcher) {
|
fun addVfsListener(watcher: GradleScriptInputsWatcher) {
|
||||||
VirtualFileManager.getInstance().addAsyncFileListener(
|
VirtualFileManager.getInstance().addAsyncFileListener(
|
||||||
object : AsyncFileChangeListenerBase() {
|
object : AsyncFileChangeListenerBase() {
|
||||||
|
|
||||||
private var files: Set<String> = Collections.emptySet();
|
|
||||||
|
|
||||||
override fun isRelevant(path: String): Boolean {
|
override fun isRelevant(path: String): Boolean {
|
||||||
return isInAffectedGradleProjectFiles(files, path)
|
return isInAffectedGradleProjectFiles(watcher.project, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateFile(file: VirtualFile, event: VFileEvent) {
|
override fun updateFile(file: VirtualFile, event: VFileEvent) {
|
||||||
@@ -27,11 +23,9 @@ fun addVfsListener(watcher: GradleScriptInputsWatcher) {
|
|||||||
|
|
||||||
// do nothing
|
// do nothing
|
||||||
override fun apply() {}
|
override fun apply() {}
|
||||||
override fun init() {
|
override fun init() {}
|
||||||
files = getAffectedGradleProjectFiles(watcher.project)
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
watcher.project,
|
watcher.project
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+6
-1
@@ -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.CachedConfigurationInputs
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationSnapshot
|
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.getGradleScriptInputsStamp
|
||||||
|
import org.jetbrains.kotlin.idea.scripting.gradle.saveGradleProjectRootsAfterImport
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
||||||
@@ -55,7 +56,11 @@ class KotlinDslScriptModelDataService : AbstractProjectDataService<ProjectData,
|
|||||||
gradleKotlinBuildScripts.clear()
|
gradleKotlinBuildScripts.clear()
|
||||||
|
|
||||||
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||||
val projectSettings = gradleSettings.getLinkedProjectSettings(projectData?.linkedExternalProjectPath ?: return) ?: return
|
val projectRoot = projectData?.linkedExternalProjectPath ?: return
|
||||||
|
val projectSettings = gradleSettings.getLinkedProjectSettings(projectRoot) ?: return
|
||||||
|
|
||||||
|
saveGradleProjectRootsAfterImport(projectSettings.modules.takeIf { it.isNotEmpty() } ?: setOf(projectRoot))
|
||||||
|
|
||||||
val gradleExeSettings = ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>(
|
val gradleExeSettings = ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>(
|
||||||
project,
|
project,
|
||||||
projectSettings.externalProjectPath,
|
projectSettings.externalProjectPath,
|
||||||
|
|||||||
@@ -12,14 +12,12 @@ import com.intellij.openapi.util.registry.Registry
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
import com.intellij.util.io.systemIndependentPath
|
|
||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtScriptInitializer
|
import org.jetbrains.kotlin.psi.KtScriptInitializer
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
|
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.settings.GradleProjectSettings
|
||||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
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 isGradleKotlinScript(virtualFile: VirtualFile) = virtualFile.name.endsWith(".gradle.kts")
|
||||||
|
|
||||||
fun isInAffectedGradleProjectFiles(project: Project, filePath: String): Boolean {
|
fun isInAffectedGradleProjectFiles(project: Project, filePath: String): Boolean {
|
||||||
// fast path
|
if (filePath.endsWith("/gradle.properties")) return true
|
||||||
if (!filePath.contains("gradle")) return false
|
if (filePath.endsWith("/gradle-wrapper.properties")) return true
|
||||||
|
|
||||||
val affectedFiles = getAffectedGradleProjectFiles(project)
|
if (filePath.endsWith(".gradle") || filePath.endsWith(".gradle.kts")) {
|
||||||
return isInAffectedGradleProjectFiles(affectedFiles, filePath)
|
if (ApplicationManager.getApplication().isUnitTestModeWithoutAffectedGradleProjectFilesCheck) {
|
||||||
}
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fun isInAffectedGradleProjectFiles(files: Set<String>, filePath: String): Boolean {
|
return filePath.substringBeforeLast("/") in getGradleProjectsRoots(project)
|
||||||
if (ApplicationManager.getApplication().isUnitTestModeWithoutAffectedGradleProjectFilesCheck) {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return filePath in files
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAffectedGradleProjectFiles(project: Project): Set<String> {
|
private var cachedGradleProjectsRoots: Set<String>? = null
|
||||||
|
|
||||||
|
private fun getGradleProjectsRoots(project: Project): Set<String> {
|
||||||
|
if (cachedGradleProjectsRoots == null) {
|
||||||
|
cachedGradleProjectsRoots = computeGradleProjectRoots(project)
|
||||||
|
}
|
||||||
|
return cachedGradleProjectsRoots ?: emptySet()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveGradleProjectRootsAfterImport(roots: Set<String>) {
|
||||||
|
cachedGradleProjectsRoots = roots
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeGradleProjectRoots(project: Project): Set<String> {
|
||||||
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||||
if (gradleSettings.getLinkedProjectsSettings().isEmpty()) return setOf()
|
if (gradleSettings.getLinkedProjectsSettings().isEmpty()) return setOf()
|
||||||
|
|
||||||
val projectSettings = gradleSettings.getLinkedProjectsSettings().filterIsInstance<GradleProjectSettings>().firstOrNull()
|
val projectSettings = gradleSettings.getLinkedProjectsSettings().filterIsInstance<GradleProjectSettings>().firstOrNull()
|
||||||
?: return setOf()
|
?: return setOf()
|
||||||
|
|
||||||
return ExternalSystemApiUtil.getAllManagers()
|
return projectSettings.modules.takeIf { it.isNotEmpty() } ?: setOf(projectSettings.externalProjectPath)
|
||||||
.filterIsInstance<GradleManager>()
|
|
||||||
.firstOrNull()
|
|
||||||
?.getAffectedExternalProjectFiles(projectSettings.externalProjectPath, project)
|
|
||||||
?.mapTo(mutableSetOf()) { it.toPath().systemIndependentPath }
|
|
||||||
?: setOf()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGradleScriptInputsStamp(
|
fun getGradleScriptInputsStamp(
|
||||||
|
|||||||
Reference in New Issue
Block a user