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 new file mode 100644 index 00000000000..66ec30ba410 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt @@ -0,0 +1,33 @@ +/* + * 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 + +import com.intellij.openapi.externalSystem.service.project.autoimport.AsyncFileChangeListenerBase +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.openapi.vfs.newvfs.events.VFileEvent + +fun addVfsListener(watcher: GradleScriptInputsWatcher) { + VirtualFileManager.getInstance().addAsyncFileListener( + object : AsyncFileChangeListenerBase() { + override fun isRelevant(path: String): Boolean { + val files = getAffectedGradleProjectFiles(watcher.project) + return isInAffectedGradleProjectFiles(files, path) + } + + override fun updateFile(file: VirtualFile, event: VFileEvent) { + watcher.fileChanged(event.path, file.timeStamp) + } + + // do nothing + override fun prepareFileDeletion(file: VirtualFile) {} + override fun apply() {} + override fun reset() {} + + }, + 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 new file mode 100644 index 00000000000..3026fefe43a --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt.191 @@ -0,0 +1,31 @@ +/* + * 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 + +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 + +fun addVfsListener(watcher: GradleScriptInputsWatcher) { + watcher.project.messageBus.connect().subscribe( + VirtualFileManager.VFS_CHANGES, + object : BulkFileListener { + override fun after(events: List) { + ApplicationManager.getApplication().executeOnPooledThread { + if (watcher.project.isDisposed) return@executeOnPooledThread + val files = getAffectedGradleProjectFiles(watcher.project) + for (event in events) { + val file = event.file ?: return@executeOnPooledThread + if (isInAffectedGradleProjectFiles(files, event.path)) { + watcher.fileChanged(event.path, file.timeStamp) + } + } + } + } + } + ) +} \ No newline at end of file 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 new file mode 100644 index 00000000000..3ccd693666c --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/AsyncFileChangeListenerHelper.kt.201 @@ -0,0 +1,32 @@ +/* + * 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 + +import com.intellij.openapi.externalSystem.autoimport.AsyncFileChangeListenerBase +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.openapi.vfs.newvfs.events.VFileEvent + +fun addVfsListener(watcher: GradleScriptInputsWatcher) { + VirtualFileManager.getInstance().addAsyncFileListener( + object : AsyncFileChangeListenerBase() { + override fun isRelevant(path: String): Boolean { + val files = getAffectedGradleProjectFiles(watcher.project) + return isInAffectedGradleProjectFiles(files, path) + } + + override fun updateFile(file: VirtualFile, event: VFileEvent) { + watcher.fileChanged(event.path, file.timeStamp) + } + + // do nothing + override fun apply() {} + override fun init() {} + + }, + watcher.project, + ) +} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt index a1ffe481f28..479c05ab4db 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt @@ -7,15 +7,8 @@ package org.jetbrains.kotlin.idea.scripting.gradle import com.intellij.openapi.components.* import com.intellij.openapi.project.Project -import com.intellij.openapi.util.io.FileUtil 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.util.PathUtil import org.jetbrains.annotations.TestOnly -import org.junit.Assert.assertEquals -import org.junit.Test @State( name = "KotlinBuildScriptsModificationInfo", @@ -25,43 +18,22 @@ class GradleScriptInputsWatcher(val project: Project) : PersistentStateComponent private var storage = Storage() fun startWatching() { - project.messageBus.connect().subscribe( - VirtualFileManager.VFS_CHANGES, - object : BulkFileListener { - override fun after(events: List) { - if (project.isDisposed) return - - val files = getAffectedGradleProjectFiles(project) - for (event in events) { - val file = event.file ?: return - if (isInAffectedGradleProjectFiles(files, event.path)) { - storage.fileChanged(file, file.timeStamp) - } - } - } - }) + addVfsListener(this) } fun areRelatedFilesUpToDate(file: VirtualFile, timeStamp: Long): Boolean { - return storage.lastModifiedTimeStampExcept(file) < timeStamp + return storage.lastModifiedTimeStampExcept(file.path) < timeStamp } class Storage { private val lastModifiedFiles = LastModifiedFiles() - fun lastModifiedTimeStampExcept(file: VirtualFile): Long { - val fileId = getFileId(file) - return lastModifiedFiles.lastModifiedTimeStampExcept(fileId) + fun lastModifiedTimeStampExcept(filePath: String): Long { + return lastModifiedFiles.lastModifiedTimeStampExcept(filePath) } - fun fileChanged(file: VirtualFile, ts: Long) { - val fileId = getFileId(file) - lastModifiedFiles.fileChanged(ts, fileId) - } - - private fun getFileId(file: VirtualFile): String { - val canonized = PathUtil.getCanonicalPath(file.path) - return FileUtil.toSystemIndependentName(canonized) + fun fileChanged(filePath: String, ts: Long) { + lastModifiedFiles.fileChanged(ts, filePath) } } @@ -73,13 +45,12 @@ class GradleScriptInputsWatcher(val project: Project) : PersistentStateComponent this.storage = state } + fun fileChanged(filePath: String, ts: Long) { + storage.fileChanged(filePath, ts) + } + @TestOnly fun clearAndRefillState() { loadState(project.service().state) } - - @TestOnly - fun fileChanged(file: VirtualFile, ts: Long) { - storage.fileChanged(file, ts) - } } \ No newline at end of file diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcherTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcherTest.kt index bb7c8c4814c..5a62fe03543 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcherTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcherTest.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.scripting.gradle import com.intellij.openapi.components.service +import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiFile import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationLoadingTest @@ -194,8 +195,8 @@ open class GradleScriptInputsWatcherTest : AbstractScriptConfigurationLoadingTes changeSettingsKtsOutsideSections() val ts = System.currentTimeMillis() - project.service().fileChanged(testFiles.buildKts.virtualFile, ts) - project.service().fileChanged(testFiles.settings.virtualFile, ts) + markFileChanged(testFiles.buildKts.virtualFile, ts) + markFileChanged(testFiles.settings.virtualFile, ts) assertConfigurationUpdateWasDone(testFiles.settings) assertConfigurationUpdateWasDone(testFiles.buildKts) @@ -206,8 +207,8 @@ open class GradleScriptInputsWatcherTest : AbstractScriptConfigurationLoadingTes assertAndLoadInitialConfiguration(testFiles.settings) val ts = System.currentTimeMillis() - project.service().fileChanged(testFiles.buildKts.virtualFile, ts) - project.service().fileChanged(testFiles.settings.virtualFile, ts) + markFileChanged(testFiles.buildKts.virtualFile, ts) + markFileChanged(testFiles.settings.virtualFile, ts) changePropertiesFile() @@ -215,6 +216,10 @@ open class GradleScriptInputsWatcherTest : AbstractScriptConfigurationLoadingTes assertConfigurationUpdateWasDone(testFiles.buildKts) } + private fun markFileChanged(virtualFile: VirtualFile, ts: Long) { + project.service().fileChanged(virtualFile.path, ts) + } + fun testLoadedConfigurationWhenExternalFileChanged() { assertAndLoadInitialConfiguration(testFiles.buildKts)