FIR IDE: do not consider OOBM in non-physical file as OOBM

This commit is contained in:
Ilya Kirillov
2021-03-01 15:57:38 +01:00
parent e2fc20e9a1
commit 9cca19d503
2 changed files with 62 additions and 9 deletions
@@ -18,6 +18,7 @@ import com.intellij.pom.event.PomModelEvent
import com.intellij.pom.event.PomModelListener
import com.intellij.pom.tree.TreeAspect
import com.intellij.pom.tree.events.TreeChangeEvent
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.source.tree.FileElement
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.idea.KotlinLanguage
@@ -68,16 +69,24 @@ internal class KotlinFirModificationTrackerService(project: Project) : Disposabl
override fun modelChanged(event: PomModelEvent) {
val changeSet = event.getChangeSet(treeAspect) as TreeChangeEvent? ?: return
if (changeSet.rootElement.psi.language != KotlinLanguage.INSTANCE) return
val psi = changeSet.rootElement.psi
if (psi.language != KotlinLanguage.INSTANCE) return
val changedElements = changeSet.changedElements
handleChangedElementsInAllModules(changedElements, changeSet)
handleChangedElementsInAllModules(changedElements, changeSet, psi)
}
private fun handleChangedElementsInAllModules(
changedElements: Array<out ASTNode>,
changeSet: TreeChangeEvent
changeSet: TreeChangeEvent,
changeSetRootElementPsi: PsiElement
) {
if (!changeSetRootElementPsi.isPhysical) {
/**
* Element which do not belong to a project should not cause OOBM
*/
return
}
if (changedElements.isEmpty()) {
incrementModificationCountForFileChange(changeSet)
} else {
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.trackers
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.ModificationTracker
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiDocumentManager
@@ -15,11 +17,14 @@ import com.intellij.testFramework.PsiTestUtil
import junit.framework.Assert
import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.util.rootManager
import org.jetbrains.kotlin.idea.util.sourceRoots
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.trackers.KotlinOutOfBlockModificationTrackerFactory
import org.jetbrains.kotlin.trackers.createModuleWithoutDependenciesOutOfBlockModificationTracker
import org.jetbrains.kotlin.trackers.createProjectWideOutOfBlockModificationTracker
import java.nio.file.Files
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.writeText
@@ -84,6 +89,40 @@ class KotlinModuleOutOfBlockTrackerTest : AbstractMultiModuleTest() {
)
}
fun testThatNonPhysicalFileChangeNotCausingBOOM() {
val moduleA = createModuleWithModificationTracker("a") {
listOf(
FileWithText("main.kt", "fun main() {}")
)
}
val moduleB = createModuleWithModificationTracker("b")
val moduleAWithTracker = ModuleWithModificationTracker(moduleA)
val moduleBWithTracker = ModuleWithModificationTracker(moduleB)
val projectWithModificationTracker = ProjectWithModificationTracker(project)
runWriteAction {
val nonPhysicalPsi = KtPsiFactory(moduleA.project).createFile("nonPhysical", "val a = c")
nonPhysicalPsi.add(KtPsiFactory(moduleA.project).createFunction("fun x(){}"))
}
Assert.assertFalse(
"Out of block modification count for module A should not change after non physical file change, modification count is ${moduleAWithTracker.modificationCount}",
moduleAWithTracker.changed()
)
Assert.assertFalse(
"Out of block modification count for module B should not change after non physical file change, modification count is ${moduleBWithTracker.modificationCount}",
moduleBWithTracker.changed()
)
Assert.assertFalse(
"Out of block modification count for project should not change after non physical file change, modification count is ${projectWithModificationTracker.modificationCount}",
projectWithModificationTracker.changed()
)
}
private fun Module.typeInFunctionBody(fileName: String, textAfterTyping: String) {
val file = "${sourceRoots.first().url}/$fileName"
val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!!
@@ -119,14 +158,19 @@ class KotlinModuleOutOfBlockTrackerTest : AbstractMultiModuleTest() {
private data class FileWithText(val name: String, val text: String)
private class ModuleWithModificationTracker(module: Module) {
private val modificationTracker = module.createModuleWithoutDependenciesOutOfBlockModificationTracker()
abstract class WithModificationTracker(protected val modificationTracker: ModificationTracker) {
private val initialModificationCount = modificationTracker.modificationCount
val modificationCount: Long
get() = modificationTracker.modificationCount
val modificationCount: Long get() = modificationTracker.modificationCount
fun changed(): Boolean =
modificationTracker.modificationCount != initialModificationCount
}
private class ModuleWithModificationTracker(module: Module) : WithModificationTracker(
module.createModuleWithoutDependenciesOutOfBlockModificationTracker()
)
private class ProjectWithModificationTracker(project: Project) : WithModificationTracker(
project.createProjectWideOutOfBlockModificationTracker()
)
}