Scripting: do not start multiple request when related file was changed

This commit is contained in:
Natalia Selezneva
2019-12-13 12:45:38 +03:00
parent fba17d5b9a
commit 38b0de4ab6
5 changed files with 55 additions and 15 deletions
@@ -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<GradleScriptInputsWatcher>().areAffectedFilesUpToDate(file, timeStamp)
if (actualStamp.sections != this.sections) return false
if (actualStamp.relatedFilesTimeStamp == this.relatedFilesTimeStamp) return true
return project.service<GradleScriptInputsWatcher>().areRelatedFilesUpToDate(file, inputsTimeStamp)
}
}
@@ -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
}
}
@@ -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
}
}
@@ -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<GradleScriptInputsWatcher>().lastModifiedFileTimeStamp(file)
GradleKotlinScriptConfigurationInputs(result.toString(), file.timeStamp, relatedFilesTimeStamp)
} else null
}
}
@@ -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()