Add modCounter to invalidate synthetic file cache
#KT-35186 Fixed
This commit is contained in:
+4
-9
@@ -44,7 +44,6 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.project.*
|
||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.contextWithCompositeExceptionTracker
|
||||
import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener
|
||||
import org.jetbrains.kotlin.idea.caches.trackers.outOfBlockModificationCount
|
||||
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
|
||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesModificationTracker
|
||||
@@ -255,13 +254,9 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
val settings = specialModuleInfo.platformSettings(specialModuleInfo.platform ?: targetPlatform)
|
||||
|
||||
// Dummy files created e.g. by J2K do not receive events.
|
||||
val dependenciesForSyntheticFileCache = if (files.all { it.originalFile != it }) {
|
||||
emptyList()
|
||||
} else {
|
||||
listOf(ModificationTracker {
|
||||
files.sumByLong { it.modificationStamp }
|
||||
})
|
||||
}
|
||||
val dependencyTrackerForSyntheticFileCache = if (files.all { it.originalFile != it }) {
|
||||
ModificationTracker { files.sumByLong { it.outOfBlockModificationCount } }
|
||||
} else ModificationTracker { files.sumByLong { it.modificationStamp } }
|
||||
|
||||
val resolverDebugName =
|
||||
"$resolverForSpecialInfoName $specialModuleInfo for files ${files.joinToString { it.name }} for platform $targetPlatform"
|
||||
@@ -282,7 +277,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
syntheticFiles = files,
|
||||
reuseDataFrom = reuseDataFrom,
|
||||
moduleFilter = moduleFilter,
|
||||
dependencies = dependenciesForSyntheticFileCache,
|
||||
dependencies = listOf(dependencyTrackerForSyntheticFileCache),
|
||||
invalidateOnOOCB = true,
|
||||
allModules = allModules
|
||||
)
|
||||
|
||||
+21
-32
@@ -92,20 +92,18 @@ class KotlinCodeBlockModificationListener(
|
||||
val changedElements = changeSet.changedElements
|
||||
|
||||
// skip change if it contains only virtual/fake change
|
||||
if (changedElements.isNotEmpty() &&
|
||||
// ignore formatting (whitespaces etc) change
|
||||
(isFormattingChange(changeSet) ||
|
||||
// ignore comment change
|
||||
isCommentChange(changeSet) ||
|
||||
changedElements.all { !it.psi.isPhysical })
|
||||
) return
|
||||
if (changedElements.isNotEmpty()) {
|
||||
// ignore formatting (whitespaces etc)
|
||||
if (isFormattingChange(changeSet) || isCommentChange(changeSet)) return
|
||||
}
|
||||
|
||||
val inBlockChange = inBlockModifications(changedElements)
|
||||
val inBlockElements = inBlockModifications(changedElements)
|
||||
|
||||
if (!inBlockChange) {
|
||||
val physical = ktFile.isPhysical
|
||||
if (inBlockElements.isEmpty()) {
|
||||
messageBusConnection.deliverImmediately()
|
||||
|
||||
if (ktFile.isPhysical && !isReplLine(ktFile.virtualFile)) {
|
||||
if (physical && !isReplLine(ktFile.virtualFile)) {
|
||||
if (isLanguageTrackerEnabled) {
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, true)
|
||||
@@ -116,7 +114,9 @@ class KotlinCodeBlockModificationListener(
|
||||
}
|
||||
}
|
||||
|
||||
incOutOfBlockModificationCount(ktFile)
|
||||
ktFile.incOutOfBlockModificationCount()
|
||||
} else if (physical) {
|
||||
inBlockElements.forEach { it.containingKtFile.addInBlockModifiedItem(it) }
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -165,37 +165,20 @@ class KotlinCodeBlockModificationListener(
|
||||
return file.getUserData(KOTLIN_CONSOLE_KEY) == true
|
||||
}
|
||||
|
||||
private fun incOutOfBlockModificationCount(file: KtFile) {
|
||||
file.clearInBlockModifications()
|
||||
|
||||
val count = file.getUserData(FILE_OUT_OF_BLOCK_MODIFICATION_COUNT) ?: 0
|
||||
file.putUserData(FILE_OUT_OF_BLOCK_MODIFICATION_COUNT, count + 1)
|
||||
}
|
||||
|
||||
private fun incFileModificationCount(file: KtFile) {
|
||||
val tracker = file.getUserData(PER_FILE_MODIFICATION_TRACKER)
|
||||
?: file.putUserDataIfAbsent(PER_FILE_MODIFICATION_TRACKER, SimpleModificationTracker())
|
||||
tracker.incModificationCount()
|
||||
}
|
||||
|
||||
private fun inBlockModifications(elements: Array<ASTNode>): Boolean {
|
||||
private fun inBlockModifications(elements: Array<ASTNode>): List<KtElement> {
|
||||
// When a code fragment is reparsed, Intellij doesn't do an AST diff and considers the entire
|
||||
// contents to be replaced, which is represented in a POM event as an empty list of changed elements
|
||||
if (elements.isEmpty()) return false
|
||||
|
||||
val inBlockElements = mutableSetOf<KtElement>()
|
||||
for (element in elements) {
|
||||
// skip fake PSI elements like `IntellijIdeaRulezzz$`
|
||||
val psi = element.psi
|
||||
if (!psi.isPhysical) continue
|
||||
|
||||
val modificationScope = getInsideCodeBlockModificationScope(psi) ?: return false
|
||||
|
||||
inBlockElements.add(modificationScope.blockDeclaration)
|
||||
return elements.mapNotNull { element ->
|
||||
val modificationScope = getInsideCodeBlockModificationScope(element.psi) ?: return emptyList()
|
||||
modificationScope.blockDeclaration
|
||||
}
|
||||
|
||||
inBlockElements.forEach { it.containingKtFile.addInBlockModifiedItem(it) }
|
||||
return inBlockElements.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun isCommentChange(changeSet: TreeChangeEvent): Boolean =
|
||||
@@ -359,6 +342,12 @@ private val FILE_OUT_OF_BLOCK_MODIFICATION_COUNT = Key<Long>("FILE_OUT_OF_BLOCK_
|
||||
|
||||
val KtFile.outOfBlockModificationCount: Long by NotNullableUserDataProperty(FILE_OUT_OF_BLOCK_MODIFICATION_COUNT, 0)
|
||||
|
||||
private fun KtFile.incOutOfBlockModificationCount() {
|
||||
clearInBlockModifications()
|
||||
|
||||
val count = getUserData(FILE_OUT_OF_BLOCK_MODIFICATION_COUNT) ?: 0
|
||||
putUserData(FILE_OUT_OF_BLOCK_MODIFICATION_COUNT, count + 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* inBlockModifications is a collection of block elements those have in-block modifications
|
||||
|
||||
Reference in New Issue
Block a user