From 396bb2b5d02c9965ee5d965b7f7dc62a87ffbd7e Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 6 Nov 2014 23:40:14 +0100 Subject: [PATCH 1/3] proper synchronization in write --- .../history/core/changes/ChangeSet.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/platform/lvcs-impl/src/com/intellij/history/core/changes/ChangeSet.java b/platform/lvcs-impl/src/com/intellij/history/core/changes/ChangeSet.java index b6da7fb9d6a6..c9a75530871b 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/changes/ChangeSet.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/changes/ChangeSet.java @@ -19,6 +19,7 @@ package com.intellij.history.core.changes; import com.intellij.history.core.Content; import com.intellij.history.core.StreamUtil; import com.intellij.history.utils.LocalHistoryLog; +import com.intellij.openapi.util.Ref; import com.intellij.util.Producer; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; @@ -60,15 +61,27 @@ public class ChangeSet { isLocked = true; } - public void write(DataOutput out) throws IOException { + public void write(final DataOutput out) throws IOException { out.writeLong(myId); StreamUtil.writeStringOrNull(out, myName); out.writeLong(myTimestamp); - out.writeInt(myChanges.size()); - for (Change c : myChanges) { - StreamUtil.writeChange(out, c); - } + final Ref ref = new Ref(); + accessChanges(new Runnable() { + @Override + public void run() { + try { + out.writeInt(myChanges.size()); + for (Change c : myChanges) { + StreamUtil.writeChange(out, c); + } + } + catch (IOException e) { + ref.set(e); + } + } + }); + if (ref.get() != null) throw ref.get(); } public void setName(@Nullable String name) { From 4277ef15f740dc177098da34288990de7323f5d6 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 6 Nov 2014 23:43:12 +0100 Subject: [PATCH 2/3] separate stacks for undo / redo for light virtual files (potentially they can have no document) --- .../DocumentReferenceByLightVirtualFile.java | 49 +++++++++++++++ .../impl/DocumentReferenceByVirtualFile.java | 3 +- .../impl/DocumentReferenceManagerImpl.java | 12 +++- .../command/impl/UndoRedoStacksHolder.java | 61 +++++++++++++------ 4 files changed, 103 insertions(+), 22 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceByLightVirtualFile.java diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceByLightVirtualFile.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceByLightVirtualFile.java new file mode 100644 index 000000000000..d1dde6a49acd --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceByLightVirtualFile.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.command.impl; + +import com.intellij.openapi.command.undo.DocumentReference; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.LightVirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +class DocumentReferenceByLightVirtualFile implements DocumentReference { + private LightVirtualFile myFile; + + DocumentReferenceByLightVirtualFile(@NotNull LightVirtualFile file) { + myFile = file; + } + + @Override + @Nullable + public Document getDocument() { + return FileDocumentManager.getInstance().getDocument(myFile); + } + + @Override + @NotNull + public VirtualFile getFile() { + return myFile; + } + + @Override + public String toString() { + return myFile.toString(); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceByVirtualFile.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceByVirtualFile.java index db56ab7a8fdb..271bf8f84c12 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceByVirtualFile.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceByVirtualFile.java @@ -19,7 +19,6 @@ import com.intellij.openapi.command.undo.DocumentReference; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.testFramework.LightVirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,7 +32,7 @@ public class DocumentReferenceByVirtualFile implements DocumentReference { @Override @Nullable public Document getDocument() { - assert myFile.isValid() || myFile instanceof LightVirtualFile : "should not be called on references to deleted file: " + myFile; + assert myFile.isValid() : "should not be called on references to deleted file: " + myFile; return FileDocumentManager.getInstance().getDocument(myFile); } diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceManagerImpl.java index 5f226ed07608..020ed90d9ad8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceManagerImpl.java @@ -46,6 +46,7 @@ public class DocumentReferenceManagerImpl extends DocumentReferenceManager imple private final Map myDocToRef = new WeakKeyWeakValueHashMap(); private static final Key> FILE_TO_REF_KEY = Key.create("FILE_TO_REF_KEY"); + private static final Key FILE_TO_STRONG_REF_KEY = Key.create("FILE_TO_STRONG_REF_KEY"); private final Map myDeletedFilePathToRef = new WeakValueHashMap(); @Override @@ -132,7 +133,16 @@ public class DocumentReferenceManagerImpl extends DocumentReferenceManager imple @Override public DocumentReference create(@NotNull VirtualFile file) { assertInDispatchThread(); - assert file.isValid() || file instanceof LightVirtualFile : "file is invalid: " + file; + + if (file instanceof LightVirtualFile) { + DocumentReference reference = file.getUserData(FILE_TO_STRONG_REF_KEY); + if (reference == null) { + file.putUserData(FILE_TO_STRONG_REF_KEY, reference = new DocumentReferenceByLightVirtualFile((LightVirtualFile)file)); + } + return reference; + } + + assert file.isValid() : "file is invalid: " + file; DocumentReference result = SoftReference.dereference(file.getUserData(FILE_TO_REF_KEY)); if (result == null) { diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoStacksHolder.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoStacksHolder.java index 529fddd24a5d..742e3cb9cb23 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoStacksHolder.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoStacksHolder.java @@ -19,6 +19,7 @@ import com.intellij.openapi.command.undo.DocumentReference; import com.intellij.openapi.command.undo.DocumentReferenceManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolder; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.containers.HashMap; @@ -35,7 +36,8 @@ class UndoRedoStacksHolder { private final LinkedList myGlobalStack = new LinkedList(); private final Map> myDocumentStacks = new HashMap>(); - private final List myDocumentsWithStacks = new WeakList(); + private final WeakList myDocumentsWithStacks = new WeakList(); + private final WeakList myLightVirtualFilesWithStacks = new WeakList(); public UndoRedoStacksHolder(boolean isUndo) { myUndo = isUndo; @@ -43,17 +45,25 @@ class UndoRedoStacksHolder { @NotNull LinkedList getStack(@NotNull DocumentReference r) { - VirtualFile file = r.getFile(); - return file != null && !(file instanceof LightVirtualFile) ? doGetStackForFile(r) : doGetStackForDocument(r); + return r.getFile() != null ? doGetStackForFile(r) : doGetStackForDocument(r); } @NotNull private LinkedList doGetStackForFile(@NotNull DocumentReference r) { - LinkedList result = myDocumentStacks.get(r); - if (result == null) { - result = new LinkedList(); - myDocumentStacks.put(r, result); + LinkedList result; + VirtualFile file = r.getFile(); + + if (file instanceof LightVirtualFile) { + result = addWeaklyTrackedEmptyStack((LightVirtualFile)file, myLightVirtualFilesWithStacks); } + else { + result = myDocumentStacks.get(r); + if (result == null) { + result = new LinkedList(); + myDocumentStacks.put(r, result); + } + } + return result; } @@ -63,12 +73,15 @@ class UndoRedoStacksHolder { // itself to avoid memory leaks caused by holding stacks of all documents, ever created, here. // And to know, what documents do exist now, we have to maintain weak reference list of them. - Document d = r.getDocument(); - LinkedList result = d.getUserData(STACK_IN_DOCUMENT_KEY); + return addWeaklyTrackedEmptyStack(r.getDocument(), myDocumentsWithStacks); + } + + private LinkedList addWeaklyTrackedEmptyStack(T holder, WeakList allHolders) { + LinkedList result; + result = holder.getUserData(STACK_IN_DOCUMENT_KEY); if (result == null) { - result = new LinkedList(); - d.putUserData(STACK_IN_DOCUMENT_KEY, result); - myDocumentsWithStacks.add(d); + holder.putUserData(STACK_IN_DOCUMENT_KEY, result = new LinkedList()); + allHolders.add(holder); } return result; } @@ -164,15 +177,20 @@ class UndoRedoStacksHolder { } - Set docsToDrop = new THashSet(); - for (Document each : myDocumentsWithStacks) { - LinkedList stack = each.getUserData(STACK_IN_DOCUMENT_KEY); + cleanWeaklyTrackedEmptyStacks(myDocumentsWithStacks); + cleanWeaklyTrackedEmptyStacks(myLightVirtualFilesWithStacks); + } + + private void cleanWeaklyTrackedEmptyStacks(WeakList stackHolders) { + Set holdersToDrop = new THashSet(); + for (T holder : stackHolders) { + LinkedList stack = holder.getUserData(STACK_IN_DOCUMENT_KEY); if (stack != null && stack.isEmpty()) { - each.putUserData(STACK_IN_DOCUMENT_KEY, null); - docsToDrop.add(each); + holder.putUserData(STACK_IN_DOCUMENT_KEY, null); + holdersToDrop.add(holder); } } - myDocumentsWithStacks.removeAll(docsToDrop); + stackHolders.removeAll(holdersToDrop); } private void clearStacksFrom(@NotNull UndoableGroup from) { @@ -217,8 +235,13 @@ class UndoRedoStacksHolder { private void collectLocalAffectedDocuments(@NotNull Collection result) { result.addAll(myDocumentStacks.keySet()); + DocumentReferenceManager documentReferenceManager = DocumentReferenceManager.getInstance(); + for (Document each : myDocumentsWithStacks) { - result.add(DocumentReferenceManager.getInstance().create(each)); + result.add(documentReferenceManager.create(each)); + } + for (LightVirtualFile each : myLightVirtualFilesWithStacks) { + result.add(documentReferenceManager.create(each)); } } From 5c003f8a24de6893c4820f8a73ce788bc243c17e Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Fri, 7 Nov 2014 02:03:51 +0300 Subject: [PATCH 3/3] tweak transparent progress indicator position in case of tabbed editors --- .../intellij/openapi/wm/impl/status/InfoAndProgressPanel.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java index 0aa196baedef..383b74acb4f2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java @@ -40,6 +40,7 @@ import com.intellij.openapi.wm.StatusBar; import com.intellij.openapi.wm.StatusBarWidget; import com.intellij.openapi.wm.ex.ProgressIndicatorEx; import com.intellij.ui.Gray; +import com.intellij.ui.TabbedPaneWrapper; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.labels.LinkLabel; import com.intellij.ui.components.labels.LinkListener; @@ -414,6 +415,8 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge @NotNull private static Component getAnchor(@NotNull JRootPane pane) { + Component tabWrapper = UIUtil.findComponentOfType(pane, TabbedPaneWrapper.TabWrapper.class); + if (tabWrapper != null) return tabWrapper; Component splitters = UIUtil.findComponentOfType(pane, EditorsSplitters.class); if (splitters != null) return splitters; FileEditorManagerEx ex = FileEditorManagerEx.getInstanceEx(ProjectUtil.guessCurrentProject(pane));