lst: release trackers on VirtualFile invalidation

Fix issue with duplicated trackers registered in ChangeListWorker,
if one VirtualFile was moved on top of another VirtualFile.

EA-116756 - assert: ChangeListWorker.registerChangeTracker
EA-116749 - assert: ChangeListWorker.unregisterChangeTracker
This commit is contained in:
Aleksey Pivovarov
2018-08-20 16:36:05 +03:00
parent 93f6cfdec5
commit 8262d4e658
2 changed files with 72 additions and 11 deletions
@@ -641,21 +641,37 @@ class LineStatusTrackerManager(
if (!partialChangeListsEnabled) return
synchronized(LOCK) {
if (file.isDirectory) {
for (data in trackers.values) {
if (VfsUtil.isAncestor(file, data.tracker.virtualFile, false)) {
reregisterTrackerInCLM(data)
}
}
}
else {
val document = fileDocumentManager.getCachedDocument(file) ?: return
val data = trackers[document] ?: return
forEachTrackerUnder(file) { data ->
reregisterTrackerInCLM(data)
}
}
}
override fun fileDeleted(event: VirtualFileEvent) {
if (!partialChangeListsEnabled) return
synchronized(LOCK) {
forEachTrackerUnder(event.file) { data ->
releaseTracker(data.tracker.document)
}
}
}
private fun forEachTrackerUnder(file: VirtualFile, action: (TrackerData) -> Unit) {
if (file.isDirectory) {
for (data in trackers.values) {
if (VfsUtil.isAncestor(file, data.tracker.virtualFile, false)) {
action(data)
}
}
}
else {
val document = fileDocumentManager.getCachedDocument(file) ?: return
val data = trackers[document] ?: return
action(data)
}
}
}
private inner class MyDocumentListener : DocumentListener {
@@ -236,6 +236,51 @@ class LineStatusTrackerManagerTest : BaseLineStatusTrackerManagerTest() {
}
}
fun `test tracker when file is moved on top of another file`() {
createChangelist("Test #1")
createChangelist("Test #2")
val file1 = addLocalFile(FILE_1, "a_b_c_d_e")
val file2 = addLocalFile(FILE_2, "a_b_c_d_e")
setBaseVersion(FILE_1, "a1_b_c_d_e1")
setBaseVersion(FILE_2, "a1_b_c_d_e1")
refreshCLM()
file1.withOpenedEditor {
val tracker = file1.tracker as PartialLocalLineStatusTracker
lstm.waitUntilBaseContentsLoaded()
val ranges = tracker.getRanges()!!
tracker.moveToChangelist(ranges[0], "Test #2".asListNameToList())
}
file2.withOpenedEditor {
val tracker = file2.tracker as PartialLocalLineStatusTracker
lstm.waitUntilBaseContentsLoaded()
val ranges = tracker.getRanges()!!
tracker.moveToChangelist(ranges[1], "Test #2".asListNameToList())
}
releaseUnneededTrackers()
assertNotNull(file1.tracker)
assertNotNull(file2.tracker)
runWriteAction {
file1.delete(this)
file2.rename(this, file1.name)
}
assertNull(file1.tracker)
refreshCLM()
lstm.waitUntilBaseContentsLoaded()
file2.moveAllChangesTo("Test #1")
releaseUnneededTrackers()
assertNull(file2.tracker)
}
fun `test tracker changes moves - empty tracker`() {
createChangelist("Test #1")
createChangelist("Test #2")