IJPL-218636 [psi] send children-move events on moving file

GitOrigin-RevId: 5df2f1f7b007da16576e1d8604d845d7e044bd5d
This commit is contained in:
Max Medvedev
2025-11-18 14:32:05 +00:00
committed by intellij-monorepo-bot
parent 00ececf543
commit 22cf589ed8
2 changed files with 39 additions and 9 deletions
@@ -451,24 +451,38 @@ private class PsiVFSListener(private val project: Project) {
}
ApplicationManager.getApplication().runWriteAction(ExternalChangeActionUtil.externalChangeAction {
val treeEvent = PsiTreeChangeEventImpl(manager)
val isExcluded = vFile.isDirectory && Registry.`is`("ide.hide.excluded.files") && myProjectRootManager.fileIndex.isExcluded(vFile)
if (oldParentDir != null && !isExcluded) {
val eventChild = if (vFile.isDirectory) fileManager.findDirectory(vFile) else fileManager.findFile(vFile)
treeEvent.child = eventChild
if (newParentDir != null) {
treeEvent.oldParent = oldParentDir
treeEvent.newParent = newParentDir
manager.beforeChildMovement(treeEvent)
// a list of:
// - one or several not-null PsiFiles
// - one not-null PsiDirectory
// - single 'null' if corresponding PsiDirectory or PsiFile cannot be created
val eventChildren: List<PsiFileSystemItem?> = if (vFile.isDirectory) {
listOf(fileManager.findDirectory(vFile))
}
else {
treeEvent.parent = oldParentDir
manager.beforeChildRemoval(treeEvent)
fileManager.getCachedPsiFiles(vFile).ifEmpty { listOf(fileManager.findFile(vFile)) }
}
for (eventChild in eventChildren) {
val treeEvent = PsiTreeChangeEventImpl(manager)
treeEvent.child = eventChild
if (newParentDir != null) {
treeEvent.oldParent = oldParentDir
treeEvent.newParent = newParentDir
manager.beforeChildMovement(treeEvent)
}
else {
treeEvent.parent = oldParentDir
manager.beforeChildRemoval(treeEvent)
}
}
}
else {
// checked above
LOG.assertTrue(newParentDir != null)
val treeEvent = PsiTreeChangeEventImpl(manager)
treeEvent.parent = newParentDir
manager.beforeChildAddition(treeEvent)
}
@@ -40,6 +40,7 @@ internal class MultiversePsiEventTest {
private val module2 = projectFixture.moduleFixture("m2")
private val sourceRoot = sharedSourceRootFixture(module1, module2)
private val sourceRoot2 = sharedSourceRootFixture(module1, module2)
@Suppress("unused")
private val registerFakeLang = testFixture {
@@ -266,6 +267,21 @@ internal class MultiversePsiEventTest {
expectedEventNumber = 2
)
@Test
fun `test we receive 2 before-child-moved events on moving a file with 2 psi files`() = doChangeTest(
listenerFactory = { counter ->
object : PsiTreeChangeAdapter() {
override fun beforeChildMovement(event: PsiTreeChangeEvent) {
counter.incrementAndGet()
}
}
},
updateBlock = { file ->
file.move(this, sourceRoot2.get().virtualFile)
},
expectedEventNumber = 2
)
private fun doChangeTest(
listenerFactory: (AtomicInteger) -> PsiTreeChangeListener,
updateBlock: (file: VirtualFile) -> Unit,