Scripting: check if affected scripts are changed using file modification stamp instead of mark them out of date in cache
^KT-35205 Fixed
This commit is contained in:
+6
-3
@@ -5,16 +5,19 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||||
|
|
||||||
|
import com.intellij.openapi.components.service
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs
|
import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
data class GradleKotlinScriptConfigurationInputs(
|
data class GradleKotlinScriptConfigurationInputs(
|
||||||
val buildScriptAndPluginsSections: String
|
val buildScriptAndPluginsSections: String,
|
||||||
|
val timeStamp: Long
|
||||||
) : CachedConfigurationInputs {
|
) : CachedConfigurationInputs {
|
||||||
override fun isUpToDate(project: Project, file: VirtualFile, ktFile: KtFile?): Boolean {
|
override fun isUpToDate(project: Project, file: VirtualFile, ktFile: KtFile?): Boolean {
|
||||||
val actualStamp = getGradleScriptInputsStamp(project, file, ktFile)
|
val actualStamp = getGradleScriptInputsStamp(project, file, ktFile) ?: return false
|
||||||
return actualStamp == this
|
return actualStamp.buildScriptAndPluginsSections == this.buildScriptAndPluginsSections
|
||||||
|
&& project.service<GradleScriptInputsWatcher>().areAffectedFilesUpToDate(file, timeStamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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.externalSystem.service.project.autoimport.ConfigurationFileCrcFactory
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import org.jetbrains.plugins.gradle.settings.GradleLocalSettings
|
||||||
|
import java.nio.file.Paths
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class GradleScriptInputsWatcher(val project: Project) {
|
||||||
|
private val comparator = Comparator<VirtualFile> { f1, f2 -> (f1.timeStamp - f2.timeStamp).toInt() }
|
||||||
|
|
||||||
|
private val storage = TreeSet(comparator)
|
||||||
|
|
||||||
|
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(file).create()
|
||||||
|
if (calculateCrc != stamp) {
|
||||||
|
addToStorage(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addToStorage(file: VirtualFile) {
|
||||||
|
if (storage.contains(file)) {
|
||||||
|
storage.remove(file)
|
||||||
|
}
|
||||||
|
storage.add(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun areAffectedFilesUpToDate(file: VirtualFile, timeStamp: Long): Boolean {
|
||||||
|
if (storage.isEmpty()) return true
|
||||||
|
|
||||||
|
val iterator = storage.descendingIterator()
|
||||||
|
if (!iterator.hasNext()) return true
|
||||||
|
|
||||||
|
var lastModifiedFile = iterator.next()
|
||||||
|
while (lastModifiedFile == file && iterator.hasNext()) {
|
||||||
|
lastModifiedFile = iterator.next()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastModifiedFile == file) return true
|
||||||
|
|
||||||
|
return lastModifiedFile.timeStamp <= timeStamp
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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.externalSystem.service.project.autoimport.ConfigurationFileCrcFactory
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import org.jetbrains.plugins.gradle.settings.GradleLocalSettings
|
||||||
|
import java.nio.file.Paths
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class GradleScriptInputsWatcher(val project: Project) {
|
||||||
|
private val comparator = Comparator<VirtualFile> { f1, f2 -> (f1.timeStamp - f2.timeStamp).toInt() }
|
||||||
|
|
||||||
|
private val storage = TreeSet(comparator)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
addToStorage(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addToStorage(file: VirtualFile) {
|
||||||
|
if (storage.contains(file)) {
|
||||||
|
storage.remove(file)
|
||||||
|
}
|
||||||
|
storage.add(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun areAffectedFilesUpToDate(file: VirtualFile, timeStamp: Long): Boolean {
|
||||||
|
if (storage.isEmpty()) return true
|
||||||
|
|
||||||
|
val iterator = storage.descendingIterator()
|
||||||
|
if (!iterator.hasNext()) return true
|
||||||
|
|
||||||
|
var lastModifiedFile = iterator.next()
|
||||||
|
while (lastModifiedFile == file && iterator.hasNext()) {
|
||||||
|
lastModifiedFile = iterator.next()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastModifiedFile == file) return true
|
||||||
|
|
||||||
|
return lastModifiedFile.timeStamp <= timeStamp
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-3
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||||
|
|
||||||
|
import com.intellij.openapi.components.service
|
||||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
@@ -34,10 +35,8 @@ open class GradleScriptListener(project: Project) : ScriptChangeListener(project
|
|||||||
if (file != null) {
|
if (file != null) {
|
||||||
// *.gradle.kts file was changed
|
// *.gradle.kts file was changed
|
||||||
updater.ensureUpToDatedConfigurationSuggested(file)
|
updater.ensureUpToDatedConfigurationSuggested(file)
|
||||||
updater.postponeConfigurationReload(ScriptConfigurationCacheScope.Except(file))
|
|
||||||
} else {
|
|
||||||
updater.postponeConfigurationReload(ScriptConfigurationCacheScope.All)
|
|
||||||
}
|
}
|
||||||
|
project.service<GradleScriptInputsWatcher>().addToStorage(vFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isApplicable(vFile: VirtualFile): Boolean {
|
override fun isApplicable(vFile: VirtualFile): Boolean {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ fun getGradleScriptInputsStamp(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GradleKotlinScriptConfigurationInputs(result.toString())
|
GradleKotlinScriptConfigurationInputs(result.toString(), file.timeStamp)
|
||||||
} else null
|
} else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+38
@@ -103,6 +103,44 @@ class GradleScriptInputsWatcherTest : AbstractScriptConfigurationLoadingTest() {
|
|||||||
assertConfigurationUpToDate(testFiles.settings)
|
assertConfigurationUpToDate(testFiles.settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testChangeOutsideSectionsInvalidatesOtherFiles() {
|
||||||
|
assertAndLoadInitialConfiguration(testFiles.buildKts)
|
||||||
|
assertAndLoadInitialConfiguration(testFiles.settings)
|
||||||
|
|
||||||
|
changeBuildKtsOutsideSections()
|
||||||
|
|
||||||
|
assertConfigurationUpToDate(testFiles.buildKts)
|
||||||
|
assertConfigurationUpdateWasDone(testFiles.settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testChangeInsideSectionsInvalidatesOtherFiles() {
|
||||||
|
assertAndLoadInitialConfiguration(testFiles.buildKts)
|
||||||
|
assertAndLoadInitialConfiguration(testFiles.settings)
|
||||||
|
|
||||||
|
changeBuildKtsInsideSections()
|
||||||
|
|
||||||
|
assertConfigurationUpdateWasDone(testFiles.buildKts)
|
||||||
|
assertConfigurationUpdateWasDone(testFiles.settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testChangeInsideNonKtsFileInvalidatesOtherFiles() {
|
||||||
|
assertAndLoadInitialConfiguration(testFiles.buildKts)
|
||||||
|
|
||||||
|
changePropertiesFile()
|
||||||
|
|
||||||
|
assertConfigurationUpdateWasDone(testFiles.buildKts)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testTwoFilesChanged() {
|
||||||
|
assertAndLoadInitialConfiguration(testFiles.buildKts)
|
||||||
|
assertAndLoadInitialConfiguration(testFiles.settings)
|
||||||
|
|
||||||
|
changePropertiesFile()
|
||||||
|
changeSettingsKtsOutsideSections()
|
||||||
|
|
||||||
|
assertConfigurationUpdateWasDone(testFiles.settings)
|
||||||
|
}
|
||||||
|
|
||||||
fun testFileAttributes() {
|
fun testFileAttributes() {
|
||||||
assertAndLoadInitialConfiguration(testFiles.buildKts)
|
assertAndLoadInitialConfiguration(testFiles.buildKts)
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,8 @@
|
|||||||
This setting currently affects only HMPP projects. You may need to delete existing test configurations for the change to take place."
|
This setting currently affects only HMPP projects. You may need to delete existing test configurations for the change to take place."
|
||||||
defaultValue="true"
|
defaultValue="true"
|
||||||
restartRequired="false"/>
|
restartRequired="false"/>
|
||||||
|
|
||||||
|
<projectService serviceImplementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptInputsWatcher"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<actions>
|
<actions>
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
This setting currently affects only HMPP projects. You may need to delete existing test configurations for the change to take place."
|
This setting currently affects only HMPP projects. You may need to delete existing test configurations for the change to take place."
|
||||||
defaultValue="true"
|
defaultValue="true"
|
||||||
restartRequired="false"/>
|
restartRequired="false"/>
|
||||||
|
|
||||||
|
<projectService serviceImplementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptInputsWatcher"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<actions>
|
<actions>
|
||||||
|
|||||||
Reference in New Issue
Block a user