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 b724124dfef..c47fd2dfc47 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 @@ -6,15 +6,14 @@ package org.jetbrains.kotlin.idea.scripting.gradle import com.intellij.openapi.components.* -import com.intellij.openapi.externalSystem.service.project.autoimport.ConfigurationFileCrcFactory import com.intellij.openapi.project.Project import com.intellij.openapi.util.io.FileUtil -import com.intellij.openapi.vfs.VfsUtil 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.jetbrains.plugins.gradle.settings.GradleLocalSettings -import java.nio.file.Paths @State( name = "KotlinBuildScriptsModificationInfo", @@ -23,21 +22,22 @@ import java.nio.file.Paths class GradleScriptInputsWatcher(val project: Project) : PersistentStateComponent { private var storage = Storage() - init { - initStorage(project) - } + fun startWatching() { + project.messageBus.connect().subscribe( + VirtualFileManager.VFS_CHANGES, + object : BulkFileListener { + override fun after(events: List) { + if (project.isDisposed) return - private fun initStorage(project: Project) { - val localSettings = GradleLocalSettings.getInstance(project) - localSettings.externalConfigModificationStamps.forEach { (path, stamp) -> - val file = VfsUtil.findFile(Paths.get(path), true) - if (file != null && !file.isDirectory) { - val calculateCrc = ConfigurationFileCrcFactory(file).create() - if (calculateCrc != stamp) { - storage.fileChanged(file, file.timeStamp) + val files = getAffectedGradleProjectFiles(project) + for (event in events) { + val file = event.file ?: return + if (isInAffectedGradleProjectFiles(files, file)) { + storage.fileChanged(file, file.timeStamp) + } + } } - } - } + }) } fun areRelatedFilesUpToDate(file: VirtualFile, timeStamp: Long): Boolean { diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt.as35 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt.as35 deleted file mode 100644 index 152a3ced77c..00000000000 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt.as35 +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2010-2019 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.components.* -import com.intellij.openapi.externalSystem.service.project.autoimport.ConfigurationFileCrcFactory -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.io.FileUtil -import com.intellij.openapi.vfs.VfsUtil -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.util.PathUtil -import org.jetbrains.annotations.TestOnly -import org.jetbrains.plugins.gradle.settings.GradleLocalSettings -import java.nio.file.Paths - -@State( - name = "KotlinBuildScriptsModificationInfo", - storages = [Storage(StoragePathMacros.CACHE_FILE)] -) -class GradleScriptInputsWatcher(val project: Project) : PersistentStateComponent { - private var storage = Storage() - - init { - initStorage(project) - } - - private fun initStorage(project: Project) { - val localSettings = GradleLocalSettings.getInstance(project) - localSettings.externalConfigModificationStamps.forEach { (path, stamp) -> - val file = VfsUtil.findFile(Paths.get(path), true) - if (file != null && !file.isDirectory) { - val calculateCrc = ConfigurationFileCrcFactory(project, file).create() - if (calculateCrc != stamp) { - storage.fileChanged(file, file.timeStamp) - } - } - } - } - - fun lastModifiedFileTimeStamp(file: VirtualFile): Long = storage.lastModifiedTimeStampExcept(file) - - fun areRelatedFilesUpToDate(file: VirtualFile, timeStamp: Long): Boolean { - return lastModifiedFileTimeStamp(file) < timeStamp - } - - class Storage( - private var lastModifiedTS: Long = 0, - private var lastModifiedFiles: MutableSet = hashSetOf(), - private var previousModifiedTS: Long = 0, - private var previousModifiedFiles: MutableSet = hashSetOf() - ) { - fun lastModifiedTimeStampExcept(file: VirtualFile): Long { - val fileId = getFileId(file) - synchronized(this) { - if (lastModifiedFiles.contains(fileId) && lastModifiedFiles.size == 1) { - return previousModifiedTS - } - return lastModifiedTS - } - - } - - fun fileChanged(file: VirtualFile, ts: Long) { - val fileId = getFileId(file) - synchronized(this) { - when { - ts > lastModifiedTS -> { - previousModifiedFiles = lastModifiedFiles - previousModifiedTS = lastModifiedTS - - lastModifiedFiles = hashSetOf(fileId) - lastModifiedTS = ts - } - ts == lastModifiedTS -> { - lastModifiedFiles.add(fileId) - } - ts == previousModifiedTS -> { - previousModifiedFiles.add(fileId) - } - else -> {} - } - } - } - - private fun getFileId(file: VirtualFile): String { - val canonized = PathUtil.getCanonicalPath(file.path) - return FileUtil.toSystemIndependentName(canonized) - } - } - - override fun getState(): Storage { - return storage - } - - override fun loadState(state: Storage) { - this.storage = state - } - - @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/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptListener.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptListener.kt index 0a8b0d2fa58..8c65f66a58a 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptListener.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptListener.kt @@ -6,22 +6,18 @@ package org.jetbrains.kotlin.idea.scripting.gradle import com.intellij.openapi.components.service -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile -import com.intellij.util.io.systemIndependentPath -import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationCacheScope import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptChangeListener import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptConfigurationUpdater -import org.jetbrains.plugins.gradle.GradleManager -import org.jetbrains.plugins.gradle.settings.GradleProjectSettings -import org.jetbrains.plugins.gradle.util.GradleConstants open class GradleScriptListener(project: Project) : ScriptChangeListener(project) { + init { + // start GradleScriptInputsWatcher to track changes in gradle-configuration related files + project.service().startWatching() + } override fun editorActivated(vFile: VirtualFile, updater: ScriptConfigurationUpdater) { - if (!isGradleKotlinScript(vFile)) return - if (useScriptConfigurationFromImportOnly()) { // do nothing } else { @@ -36,10 +32,11 @@ open class GradleScriptListener(project: Project) : ScriptChangeListener(project // *.gradle.kts file was changed updater.ensureUpToDatedConfigurationSuggested(file) } - project.service().fileChanged(vFile, vFile.timeStamp) } override fun isApplicable(vFile: VirtualFile): Boolean { + if (!isGradleKotlinScript(vFile)) return false + return isInAffectedGradleProjectFiles(project, vFile) } } \ 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 d6f16ec1f7b..948e2fb1f42 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 @@ -5,14 +5,10 @@ package org.jetbrains.kotlin.idea.scripting.gradle -import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.service import com.intellij.psi.PsiFile import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager -import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptChangeListener -import org.jetbrains.kotlin.idea.core.script.isScriptChangesNotifierDisabled import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationLoadingTest -import org.jetbrains.kotlin.idea.script.addExtensionPointInTest import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.plugins.gradle.util.GradleConstants import java.io.File @@ -28,17 +24,11 @@ class GradleScriptInputsWatcherTest : AbstractScriptConfigurationLoadingTest() { override fun setUp() { super.setUp() - ApplicationManager.getApplication().isScriptChangesNotifierDisabled = false + // should be initialized explicitly because we do not have a real Gradle Project in this test + project.service().startWatching() } override fun setUpTestProject() { - addExtensionPointInTest( - ScriptChangeListener.LISTENER, - project, - TestGradleScriptListener(project), - testRootDisposable - ) - val rootDir = "idea/testData/script/definition/loading/gradle/" val settings: KtFile = addFileToProject(rootDir + GradleConstants.KOTLIN_DSL_SETTINGS_FILE_NAME) diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/TestGradleScriptListener.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/TestGradleScriptListener.kt deleted file mode 100644 index 9f5aaef169e..00000000000 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/TestGradleScriptListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2010-2019 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.project.Project -import com.intellij.openapi.vfs.VirtualFile - -internal class TestGradleScriptListener(project: Project) : GradleScriptListener(project) { - override fun isApplicable(vFile: VirtualFile): Boolean { - return true - } -} \ No newline at end of file