diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleKotlinScriptConfigurationInputs.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleKotlinScriptConfigurationInputs.kt index 0b26e3d0ed4..391706ffa90 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleKotlinScriptConfigurationInputs.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleKotlinScriptConfigurationInputs.kt @@ -11,13 +11,30 @@ import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs import org.jetbrains.kotlin.psi.KtFile +/** + * Up to date of gradle script depends on following factors: + * 1. It is out of date when essential [sections] are changed + * @see getGradleScriptInputsStamp + * 2. When some related file is changed (other gradle script, gradle.properties file) + * @see GradleScriptInputsWatcher.areRelatedFilesUpToDate + * + * [inputsTimeStamp] is needed to check if some related file was changed between updates + * [relatedFilesTimeStamp] is needed to check if we already loaded a configuration after the last related file change + * + * In case when [relatedFilesTimeStamp]s are equal there is no needs to check if related files were changed + */ data class GradleKotlinScriptConfigurationInputs( - val buildScriptAndPluginsSections: String, - val timeStamp: Long + val sections: String, + val inputsTimeStamp: Long, + val relatedFilesTimeStamp: Long ) : CachedConfigurationInputs { override fun isUpToDate(project: Project, file: VirtualFile, ktFile: KtFile?): Boolean { val actualStamp = getGradleScriptInputsStamp(project, file, ktFile) ?: return false - return actualStamp.buildScriptAndPluginsSections == this.buildScriptAndPluginsSections - && project.service().areAffectedFilesUpToDate(file, timeStamp) + + if (actualStamp.sections != this.sections) return false + + if (actualStamp.relatedFilesTimeStamp == this.relatedFilesTimeStamp) return true + + return project.service().areRelatedFilesUpToDate(file, inputsTimeStamp) } } \ 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 8c55b5027bb..c669388d64e 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 @@ -35,6 +35,12 @@ class GradleScriptInputsWatcher(val project: Project) { } } + fun lastModifiedFileTimeStamp(file: VirtualFile): Long = lastModifiedRelatedFile(file)?.timeStamp ?: 0 + + fun areRelatedFilesUpToDate(file: VirtualFile, timeStamp: Long): Boolean { + return lastModifiedFileTimeStamp(file) <= timeStamp + } + fun addToStorage(file: VirtualFile) { if (storage.contains(file)) { storage.remove(file) @@ -42,19 +48,19 @@ class GradleScriptInputsWatcher(val project: Project) { storage.add(file) } - fun areAffectedFilesUpToDate(file: VirtualFile, timeStamp: Long): Boolean { - if (storage.isEmpty()) return true + private fun lastModifiedRelatedFile(file: VirtualFile): VirtualFile? { + if (storage.isEmpty()) return null val iterator = storage.descendingIterator() - if (!iterator.hasNext()) return true + if (!iterator.hasNext()) return null var lastModifiedFile = iterator.next() while (lastModifiedFile == file && iterator.hasNext()) { lastModifiedFile = iterator.next() } - if (lastModifiedFile == file) return true + if (lastModifiedFile == file) return null - return lastModifiedFile.timeStamp <= timeStamp + return lastModifiedFile } } \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt.as34 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt.as34 index f9101acb4f1..394a7825e0d 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt.as34 +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptInputsWatcher.kt.as34 @@ -35,6 +35,12 @@ class GradleScriptInputsWatcher(val project: Project) { } } + fun lastModifiedFileTimeStamp(file: VirtualFile): Long = lastModifiedRelatedFile(file)?.timeStamp ?: 0 + + fun areRelatedFilesUpToDate(file: VirtualFile, timeStamp: Long): Boolean { + return lastModifiedFileTimeStamp(file) <= timeStamp + } + fun addToStorage(file: VirtualFile) { if (storage.contains(file)) { storage.remove(file) @@ -42,19 +48,19 @@ class GradleScriptInputsWatcher(val project: Project) { storage.add(file) } - fun areAffectedFilesUpToDate(file: VirtualFile, timeStamp: Long): Boolean { - if (storage.isEmpty()) return true + private fun lastModifiedRelatedFile(file: VirtualFile): VirtualFile? { + if (storage.isEmpty()) return null val iterator = storage.descendingIterator() - if (!iterator.hasNext()) return true + if (!iterator.hasNext()) return null var lastModifiedFile = iterator.next() while (lastModifiedFile == file && iterator.hasNext()) { lastModifiedFile = iterator.next() } - if (lastModifiedFile == file) return true + if (lastModifiedFile == file) return null - return lastModifiedFile.timeStamp <= timeStamp + return lastModifiedFile } } \ No newline at end of file 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 bb58ab08d30..fafa882424b 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 @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.idea.scripting.gradle +import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.openapi.util.registry.Registry import com.intellij.openapi.vfs.VirtualFile @@ -55,7 +56,8 @@ fun getGradleScriptInputsStamp( } } - GradleKotlinScriptConfigurationInputs(result.toString(), file.timeStamp) + val relatedFilesTimeStamp = project.service().lastModifiedFileTimeStamp(file) + GradleKotlinScriptConfigurationInputs(result.toString(), file.timeStamp, relatedFilesTimeStamp) } else null } } 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 94c2ca1f67c..99fd10ab715 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 @@ -182,6 +182,15 @@ class GradleScriptInputsWatcherTest : AbstractScriptConfigurationLoadingTest() { assertConfigurationUpdateWasDone(testFiles.buildKts) } + fun testLoadedConfigurationWhenExternalFileChanged() { + assertAndLoadInitialConfiguration(testFiles.buildKts) + + changePropertiesFile() + + assertConfigurationUpdateWasDone(testFiles.buildKts) + assertConfigurationUpToDate(testFiles.buildKts) + } + private fun assertConfigurationUpToDate(file: KtFile) { scriptConfigurationManager.updater.ensureUpToDatedConfigurationSuggested(file) assertNoBackgroundTasks()