lst: track changelist for not-yet-initialized trackers

Fix issue, when file from non-active changelist would briefly jump
to active changelist and back when it's opened in Editor.

PartialTracker is immediately registered in CLM and is used to
determine file's changelist. But until its base content is loaded,
it has no changed blocks and "affected changelists" defaults to active changelist.
This commit is contained in:
Aleksey Pivovarov
2018-03-06 01:56:52 +03:00
parent 11a1e61de9
commit 33806f068e
5 changed files with 38 additions and 30 deletions
@@ -51,7 +51,8 @@ abstract class LineStatusTrackerBase<R : Range> {
var isReleased: Boolean = false
private set
private var isInitialized: Boolean = false
protected var isInitialized: Boolean = false
private set
protected val blocks: List<Block> get() = documentTracker.blocks
internal val LOCK: DocumentTracker.Lock get() = documentTracker.LOCK
@@ -93,7 +94,7 @@ abstract class LineStatusTrackerBase<R : Range> {
}
@CalledInAwt
fun setBaseRevision(vcsContent: CharSequence) {
open fun setBaseRevision(vcsContent: CharSequence) {
setBaseRevision(vcsContent, null)
}
@@ -160,13 +160,14 @@ public class ChangeListWorker {
myPartialChangeTrackers.put(filePath, tracker);
tracker.initChangeTracking(myDefault.id, ContainerUtil.map(myLists, list -> list.id));
ListData oldList = null;
Change change = getChangeForAfterPath(filePath);
if (change != null) {
removeChangeMapping(change);
oldList = removeChangeMapping(change);
}
tracker.initChangeTracking(myDefault.id, ContainerUtil.map(myLists, list -> list.id), oldList != null ? oldList.id : null);
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("[registerChangeTracker] path: %s", filePath));
}
@@ -769,7 +770,7 @@ public class ChangeListWorker {
ListData partialList = getDataById(listId);
if (myMainWorker && partialList == null) {
LOG.error(String.format("Unknown changelist %s", listId));
tracker.initChangeTracking(myDefault.id, ContainerUtil.map(myLists, list -> list.id));
tracker.initChangeTracking(myDefault.id, ContainerUtil.map(myLists, list -> list.id), null);
}
data.add(partialList != null ? partialList : myDefault);
}
@@ -1187,7 +1188,7 @@ public class ChangeListWorker {
}
@Override
public void initChangeTracking(@NotNull String defaultId, @NotNull List<String> changelistsIds) {
public void initChangeTracking(@NotNull String defaultId, @NotNull List<String> changelistsId, @Nullable String fileChangelistIds) {
throw new UnsupportedOperationException();
}
@@ -1220,7 +1221,7 @@ public class ChangeListWorker {
@NotNull
List<String> getAffectedChangeListsIds();
void initChangeTracking(@NotNull String defaultId, @NotNull List<String> changelistsIds);
void initChangeTracking(@NotNull String defaultId, @NotNull List<String> changelistsIds, @Nullable String fileChangelistId);
void defaultListChanged(@NotNull String oldListId, @NotNull String newListId);
@@ -73,6 +73,7 @@ class PartialLocalLineStatusTracker(project: Project,
private var defaultMarker: ChangeListMarker
private var currentMarker: ChangeListMarker? = null
private var initialChangeListId: String? = null
private val affectedChangeLists = HashSet<String>()
private val batchChangeTaskCounter: AtomicInteger = AtomicInteger()
@@ -116,6 +117,8 @@ class PartialLocalLineStatusTracker(project: Project,
newIds.add(block.marker.changelistId)
}
if (!isInitialized) initialChangeListId?.let { newIds.add(it) }
if (newIds.isEmpty()) {
if (affectedChangeLists.size == 1) {
newIds.add(affectedChangeLists.single())
@@ -143,7 +146,10 @@ class PartialLocalLineStatusTracker(project: Project,
}
@CalledInAwt
fun setBaseRevision(vcsContent: CharSequence, changelistId: String?) {
override fun setBaseRevision(vcsContent: CharSequence) {
val changelistId = if (!isInitialized) initialChangeListId else null
initialChangeListId = null
setBaseRevision(vcsContent) {
if (changelistId != null) {
changeListManager.executeUnderDataLock {
@@ -173,10 +179,12 @@ class PartialLocalLineStatusTracker(project: Project,
}
override fun initChangeTracking(defaultId: String, changelistsIds: List<String>) {
override fun initChangeTracking(defaultId: String, changelistsIds: List<String>, fileChangelistId: String?) {
documentTracker.writeLock {
defaultMarker = ChangeListMarker(defaultId)
if (!isInitialized) initialChangeListId = fileChangelistId
val idsSet = changelistsIds.toSet()
moveMarkers({ !idsSet.contains(it.marker.changelistId) }, defaultMarker)
@@ -195,6 +203,8 @@ class PartialLocalLineStatusTracker(project: Project,
documentTracker.writeLock {
if (!affectedChangeLists.contains(listId)) return@writeLock
if (!isInitialized && initialChangeListId == listId) initialChangeListId = null
moveMarkers({ it.marker.changelistId == listId }, defaultMarker)
if (affectedChangeLists.size == 1 && affectedChangeLists.contains(listId)) {
@@ -210,6 +220,8 @@ class PartialLocalLineStatusTracker(project: Project,
documentTracker.writeLock {
if (!affectedChangeLists.contains(fromListId)) return@writeLock
if (!isInitialized && initialChangeListId == fromListId) initialChangeListId = toListId
moveMarkers({ it.marker.changelistId == fromListId }, ChangeListMarker(toListId))
updateAffectedChangeLists(false)
@@ -218,6 +230,8 @@ class PartialLocalLineStatusTracker(project: Project,
override fun moveChangesTo(toListId: String) {
documentTracker.writeLock {
if (!isInitialized) initialChangeListId = toListId
moveMarkers({ true }, ChangeListMarker(toListId))
updateAffectedChangeLists(false)
@@ -391,18 +391,14 @@ class LineStatusTrackerManager(
@CalledInAwt
private fun installTracker(virtualFile: VirtualFile,
document: Document) {
private fun installTracker(virtualFile: VirtualFile, document: Document) {
if (!canGetBaseRevisionFor(virtualFile)) return
val changelistId = changeListManager.getChangeList(virtualFile)?.id
installTracker(virtualFile, document, changelistId)
doInstallTracker(virtualFile, document)
}
@CalledInAwt
private fun installTracker(virtualFile: VirtualFile,
document: Document,
oldChangesChangelistId: String?): LineStatusTracker<*>? {
private fun doInstallTracker(virtualFile: VirtualFile, document: Document): LineStatusTracker<*>? {
synchronized(LOCK) {
if (isDisposed) return null
if (trackers[document] != null) return null
@@ -418,7 +414,7 @@ class LineStatusTrackerManager(
trackers.put(document, data)
registerTrackerInCLM(data)
refreshTracker(tracker, changelistId = oldChangesChangelistId)
refreshTracker(tracker)
eventDispatcher.multicaster.onTrackerAdded(tracker)
log("Tracker installed", virtualFile)
@@ -471,10 +467,10 @@ class LineStatusTrackerManager(
}
@CalledInAwt
private fun refreshTracker(tracker: LineStatusTracker<*>, changelistId: String? = null) {
private fun refreshTracker(tracker: LineStatusTracker<*>) {
synchronized(LOCK) {
if (isDisposed) return
loader.scheduleRefresh(RefreshRequest(tracker.document, changelistId))
loader.scheduleRefresh(RefreshRequest(tracker.document))
log("Refresh queued", tracker.virtualFile)
}
@@ -583,20 +579,16 @@ class LineStatusTrackerManager(
}
val tracker = getLineStatusTracker(document)!!
if (tracker is PartialLocalLineStatusTracker) {
val changelist = request.changelistId ?: changeListManager.getChangeList(virtualFile)?.id
tracker.setBaseRevision(refreshData.text, changelist)
tracker.setBaseRevision(refreshData.text)
log("Loading finished: success", virtualFile)
if (tracker is PartialLocalLineStatusTracker) {
val state = fileStatesAwaitingRefresh.remove(tracker.virtualFile)
if (state != null) {
tracker.restoreState(state)
log("Loading finished: state restored", virtualFile)
}
}
else {
tracker.setBaseRevision(refreshData.text)
}
log("Loading finished: success", virtualFile)
}
}
}
@@ -688,7 +680,7 @@ class LineStatusTrackerManager(
if (changeList != null && !changeList.isDefault) {
log("Tracker install from DocumentListener: ", virtualFile)
val tracker = installTracker(virtualFile, document, changeList.id)
val tracker = doInstallTracker(virtualFile, document)
if (tracker is PartialLocalLineStatusTracker) {
tracker.replayChangesFromDocumentEvents(listOf(event))
}
@@ -779,7 +771,7 @@ class LineStatusTrackerManager(
private class ContentInfo(val revision: VcsRevisionNumber, val charset: Charset)
private class RefreshRequest(val document: Document, val changelistId: String? = null) {
private class RefreshRequest(val document: Document) {
override fun equals(other: Any?): Boolean = other is RefreshRequest && document == other.document
override fun hashCode(): Int = document.hashCode()
}
@@ -378,7 +378,7 @@ abstract class BaseLineStatusTrackerTestCase : LightPlatformTestCase() {
init {
resetChangelists()
partialTracker.initChangeTracking(defaultChangeListIds(), changeListIds())
partialTracker.initChangeTracking(defaultChangeListIds(), changeListIds(), null)
}
override fun destroy() {