async commit in project view: IDEA-90321

This commit is contained in:
Alexey Kudravtsev
2012-08-31 11:51:15 +04:00
parent d334203fc5
commit cfb9b6eb48
11 changed files with 523 additions and 465 deletions
@@ -20,6 +20,7 @@ import com.intellij.ide.util.treeView.AbstractTreeStructure;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
@@ -130,6 +131,11 @@ public abstract class HierarchyTreeStructure extends AbstractTreeStructure {
public final boolean hasSomethingToCommit() {
return PsiDocumentManager.getInstance(myProject).hasUncommitedDocuments();
}
@NotNull
@Override
public ActionCallback asyncCommit() {
return asyncCommitDocuments(myProject);
}
protected abstract Object[] buildChildren(HierarchyNodeDescriptor descriptor);
@@ -21,7 +21,9 @@ import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.psi.PsiDocumentManager;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractProjectTreeStructure extends ProjectAbstractTreeStructureBase implements ViewSettings {
private final AbstractTreeNode myRoot;
@@ -48,6 +50,12 @@ public abstract class AbstractProjectTreeStructure extends ProjectAbstractTreeSt
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
}
@NotNull
@Override
public ActionCallback asyncCommit() {
return asyncCommitDocuments(myProject);
}
@Override
public final boolean hasSomethingToCommit() {
return !myProject.isDisposed()
@@ -62,6 +62,7 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
myPsiTreeChangeListener = new MyPsiTreeChangeListener();
myModelListener = new ModelListener() {
@Override
public void onModelChanged() {
addRootToUpdate();
}
@@ -76,6 +77,7 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
setCanYieldUpdate(!ApplicationManager.getApplication().isUnitTestMode());
}
@Override
public final void dispose() {
PsiManager.getInstance(myProject).removePsiTreeChangeListener(myPsiTreeChangeListener);
CopyPasteManager.getInstance().removeContentChangedListener(myCopyPasteListener);
@@ -83,10 +85,12 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
super.dispose();
}
@Override
protected final boolean isAlwaysShowPlus(NodeDescriptor nodeDescriptor) {
return ((AbstractTreeNode)nodeDescriptor).isAlwaysShowPlus();
}
@Override
protected final boolean isAutoExpandNode(NodeDescriptor nodeDescriptor) {
StructureViewModel model = myStructureModel;
if (model instanceof TreeModelWrapper) {
@@ -111,6 +115,7 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
return super.isAutoExpandNode(parent == null ? nodeDescriptor : parent);
}
@Override
protected final boolean isSmartExpand() {
StructureViewModel model = myStructureModel;
if (model instanceof TreeModelWrapper) {
@@ -122,6 +127,7 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
return false;
}
@Override
@NotNull
protected final ProgressIndicator createProgressIndicator() {
return new StatusBarProgress();
@@ -136,6 +142,7 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
myOutOfCodeBlockModificationCount = myModificationTracker.getOutOfCodeBlockModificationCount();
}
@Override
public void childRemoved(@NotNull PsiTreeChangeEvent event) {
PsiElement child = event.getOldChild();
if (child instanceof PsiWhiteSpace) return; //optimization
@@ -143,12 +150,14 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
childrenChanged();
}
@Override
public void childAdded(@NotNull PsiTreeChangeEvent event) {
PsiElement child = event.getNewChild();
if (child instanceof PsiWhiteSpace) return; //optimization
childrenChanged();
}
@Override
public void childReplaced(@NotNull PsiTreeChangeEvent event) {
/** Test comment */
PsiElement oldChild = event.getOldChild();
@@ -157,10 +166,12 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
childrenChanged();
}
@Override
public void childMoved(@NotNull PsiTreeChangeEvent event) {
childrenChanged();
}
@Override
public void childrenChanged(@NotNull PsiTreeChangeEvent event) {
childrenChanged();
}
@@ -172,6 +183,7 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
setupUpdateAlarm();
}
@Override
public void propertyChanged(@NotNull PsiTreeChangeEvent event) {
childrenChanged();
}
@@ -180,6 +192,7 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
private void setupUpdateAlarm() {
myUpdateAlarm.cancelAllRequests();
myUpdateAlarm.addRequest(new Runnable() {
@Override
public void run() {
if (!isDisposed() && !myProject.isDisposed()) {
addRootToUpdate();
@@ -189,14 +202,17 @@ public class StructureTreeBuilder extends AbstractTreeBuilder {
}
final void addRootToUpdate() {
AbstractTreeStructure structure = getTreeStructure();
if (structure.hasSomethingToCommit()) {
structure.commit();
}
((SmartTreeStructure)structure).rebuildTree();
getUpdater().addSubtreeToUpdate(getRootNode());
final AbstractTreeStructure structure = getTreeStructure();
structure.asyncCommit().doWhenDone(new Runnable() {
@Override
public void run() {
((SmartTreeStructure)structure).rebuildTree();
getUpdater().addSubtreeToUpdate(getRootNode());
}
});
}
@Override
@NotNull
protected final AbstractTreeNode createSearchingTreeNodeWrapper() {
return new StructureViewComponent.StructureViewTreeElementWrapper(null,null, null);
@@ -21,10 +21,12 @@ import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.AbstractTreeStructureBase;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.PsiTodoSearchHelper;
import com.intellij.psi.search.TodoPattern;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.Iterator;
@@ -123,14 +125,23 @@ public abstract class TodoTreeStructure extends AbstractTreeStructureBase implem
return element == getRootElement() || element == mySummaryElement;
}
@Override
public final void commit() {
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
}
@Override
public boolean hasSomethingToCommit() {
return PsiDocumentManager.getInstance(myProject).hasUncommitedDocuments();
}
@NotNull
@Override
public ActionCallback asyncCommit() {
return asyncCommitDocuments(myProject);
}
@Override
public final Object getRootElement(){
return myRootElement;
}
@@ -147,6 +158,7 @@ public abstract class TodoTreeStructure extends AbstractTreeStructureBase implem
return myTodoFilter;
}
@Override
public List<TreeStructureProvider> getProviders() {
return Collections.emptyList();
}
@@ -155,6 +167,7 @@ public abstract class TodoTreeStructure extends AbstractTreeStructureBase implem
myAreModulesShown = state;
}
@Override
public boolean isModulesShown() {
return myAreModulesShown;
}
@@ -44,15 +44,15 @@ public class AbstractTreeBuilder implements Disposable {
@NonNls private static final String TREE_BUILDER = "TreeBuilder";
public static final boolean DEFAULT_UPDATE_INACTIVE = true;
public AbstractTreeBuilder(JTree tree,
DefaultTreeModel treeModel,
public AbstractTreeBuilder(@NotNull JTree tree,
@NotNull DefaultTreeModel treeModel,
AbstractTreeStructure treeStructure,
@Nullable Comparator<NodeDescriptor> comparator) {
this(tree, treeModel, treeStructure, comparator, DEFAULT_UPDATE_INACTIVE);
}
public AbstractTreeBuilder(JTree tree,
DefaultTreeModel treeModel,
public AbstractTreeBuilder(@NotNull JTree tree,
@NotNull DefaultTreeModel treeModel,
AbstractTreeStructure treeStructure,
@Nullable Comparator<NodeDescriptor> comparator,
boolean updateIfInactive) {
@@ -63,10 +63,9 @@ public class AbstractTreeBuilder implements Disposable {
}
protected void init(final JTree tree,
final DefaultTreeModel treeModel,
final AbstractTreeStructure treeStructure,
protected void init(@NotNull JTree tree,
@NotNull DefaultTreeModel treeModel,
AbstractTreeStructure treeStructure,
@Nullable final Comparator<NodeDescriptor> comparator,
final boolean updateIfInactive) {
@@ -78,6 +77,7 @@ public class AbstractTreeBuilder implements Disposable {
setPassthroughMode(isUnitTestingMode());
}
@NotNull
protected AbstractTreeUi createUi() {
return new AbstractTreeUi();
}
@@ -131,10 +131,12 @@ public class AbstractTreeBuilder implements Disposable {
}
@NotNull
protected AbstractTreeNode createSearchingTreeNodeWrapper() {
return new AbstractTreeNodeWrapper();
}
@NotNull
public final AbstractTreeBuilder setClearOnHideDelay(final long clearOnHideDelay) {
if (isDisposed()) return this;
@@ -216,21 +218,19 @@ public class AbstractTreeBuilder implements Disposable {
return true;
}
@Nullable
public final JTree getTree() {
if (isDisposed()) return null;
return getUi().getTree();
}
@Nullable
public final AbstractTreeStructure getTreeStructure() {
if (isDisposed()) return null;
return getUi().getTreeStructure();
}
public final void setTreeStructure(final AbstractTreeStructure structure) {
public final void setTreeStructure(@NotNull AbstractTreeStructure structure) {
if (isDisposed()) return;
getUi().setTreeStructure(structure);
@@ -286,21 +286,21 @@ public class AbstractTreeBuilder implements Disposable {
final ActionCallback result = new ActionCallback();
getUi().invokeLaterIfNeeded(new Runnable() {
getUi().invokeLaterIfNeeded(false, new Runnable() {
@Override
public void run() {
if (!updateStructure) {
getUi().queueUpdate(element, false).notify(result);
}
else {
if (updateStructure) {
if (forceResort) {
getUi().incComparatorStamp();
}
getUi().queueUpdate(element, true).notify(result);
}
else {
getUi().queueUpdate(element, false).notify(result);
}
}
}, false);
});
return result;
@@ -339,7 +339,7 @@ public class AbstractTreeBuilder implements Disposable {
return null;
}
protected void expandNodeChildren(final DefaultMutableTreeNode node) {
protected void expandNodeChildren(@NotNull DefaultMutableTreeNode node) {
if (isDisposed()) return;
getUi().doExpandNodeChildren(node);
@@ -426,7 +426,7 @@ public class AbstractTreeBuilder implements Disposable {
}
}
protected void yield(Runnable runnable) {
protected void yield(@NotNull Runnable runnable) {
if (isDisposed()) return;
if (myUi.isPassthroughMode()) {
@@ -445,7 +445,7 @@ public class AbstractTreeBuilder implements Disposable {
return true;
}
protected void runBackgroundLoading(final Runnable runnable) {
protected void runBackgroundLoading(@NotNull final Runnable runnable) {
if (isDisposed()) return;
final Application app = ApplicationManager.getApplication();
@@ -462,7 +462,7 @@ public class AbstractTreeBuilder implements Disposable {
}
}
protected void updateAfterLoadedInBackground(Runnable runnable) {
protected void updateAfterLoadedInBackground(@NotNull Runnable runnable) {
if (isDisposed()) return;
if (myUi.isPassthroughMode()) {
@@ -473,12 +473,14 @@ public class AbstractTreeBuilder implements Disposable {
}
}
@NotNull
public final ActionCallback getIntialized() {
if (isDisposed()) return new ActionCallback.Rejected();
return myUi.getInitialized();
}
@NotNull
public final ActionCallback getReady(Object requestor) {
if (isDisposed()) return new ActionCallback.Rejected();
@@ -501,18 +503,21 @@ public class AbstractTreeBuilder implements Disposable {
getUi().expandAll(onDone);
}
@NotNull
public ActionCallback cancelUpdate() {
if (isDisposed()) return new ActionCallback.Rejected();
return getUi().cancelUpdate();
}
public ActionCallback batch(Progressive progressive) {
@NotNull
public ActionCallback batch(@NotNull Progressive progressive) {
if (isDisposed()) return new ActionCallback.Rejected();
return getUi().batch(progressive);
}
@NotNull
public AsyncResult<Object> revalidateElement(Object element) {
if (isDisposed()) return new AsyncResult.Rejected<Object>();
@@ -553,7 +558,7 @@ public class AbstractTreeBuilder implements Disposable {
myUi = null;
}
protected boolean updateNodeDescriptor(final NodeDescriptor descriptor) {
protected boolean updateNodeDescriptor(@NotNull NodeDescriptor descriptor) {
if (isDisposed()) return false;
AbstractTreeUi ui = getUi();
@@ -576,7 +581,7 @@ public class AbstractTreeBuilder implements Disposable {
}
@NotNull
public final <T> Set<T> getSelectedElements(Class<T> elementClass) {
public final <T> Set<T> getSelectedElements(@NotNull Class<T> elementClass) {
Set<T> result = new HashSet<T>();
for (Object o : getSelectedElements()) {
Object each = transformElement(o);
@@ -599,18 +604,18 @@ public class AbstractTreeBuilder implements Disposable {
}
@Nullable
public static AbstractTreeBuilder getBuilderFor(JTree tree) {
public static AbstractTreeBuilder getBuilderFor(@NotNull JTree tree) {
final WeakReference ref = (WeakReference)tree.getClientProperty(TREE_BUILDER);
return ref != null ? (AbstractTreeBuilder)ref.get() : null;
}
@Nullable
public final <T> Object accept(Class nodeClass, TreeVisitor<T> visitor) {
public final <T> Object accept(@NotNull Class nodeClass, @NotNull TreeVisitor<T> visitor) {
return accept(nodeClass, getRootElement(), visitor);
}
@Nullable
private <T> Object accept(Class nodeClass, Object element, TreeVisitor<T> visitor) {
private <T> Object accept(@NotNull Class nodeClass, Object element, @NotNull TreeVisitor<T> visitor) {
if (element == null) return null;
if (nodeClass.isAssignableFrom(element.getClass())) {
@@ -626,7 +631,7 @@ public class AbstractTreeBuilder implements Disposable {
return null;
}
public <T> boolean select(Class nodeClass, TreeVisitor<T> visitor, @Nullable Runnable onDone, boolean addToSelection) {
public <T> boolean select(@NotNull Class nodeClass, @NotNull TreeVisitor<T> visitor, @Nullable Runnable onDone, boolean addToSelection) {
final Object element = accept(nodeClass, visitor);
if (element != null) {
select(element, onDone, addToSelection);
@@ -647,13 +652,12 @@ public class AbstractTreeBuilder implements Disposable {
return app != null && app.isUnitTestMode();
}
public static boolean isToPaintSelection(JTree tree) {
public static boolean isToPaintSelection(@NotNull JTree tree) {
AbstractTreeBuilder builder = getBuilderFor(tree);
return builder == null || builder.getUi() == null || builder.getUi().isToPaintSelection();
}
class UserRunnable implements Runnable {
private final Runnable myRunnable;
public UserRunnable(Runnable runnable) {
@@ -16,7 +16,10 @@
package com.intellij.ide.util.treeView;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.psi.PsiDocumentManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,6 +35,30 @@ public abstract class AbstractTreeStructure {
public abstract void commit();
public abstract boolean hasSomethingToCommit();
@NotNull
public static ActionCallback asyncCommitDocuments(@NotNull Project project) {
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
if (!documentManager.hasUncommitedDocuments()) {
return new ActionCallback.Done();
}
final ActionCallback callback = new ActionCallback();
documentManager.performWhenAllCommitted(callback.createSetDoneRunnable());
return callback;
}
/**
* @return callback which is set to {@link ActionCallback#setDone()} when the tree structure is committed.
* By default it just calls {@link #commit()} synchronously but it is desirable to override it
* to provide asynchronous commit to the tree structure to make it more responsible.
* E.g. when you should commit all documents during the {@link #commit()},
* you can use {@link #asyncCommitDocuments(Project)} to do it asynchronously.
*/
@NotNull
public ActionCallback asyncCommit() {
if (hasSomethingToCommit()) commit();
return new ActionCallback.Done();
}
public boolean isToBuildChildrenInBackground(Object element){
return false;
}
@@ -47,63 +74,4 @@ public abstract class AbstractTreeStructure {
public AsyncResult<Object> revalidateElement(Object element) {
return new AsyncResult.Done<Object>(element);
}
public static class Delegate extends AbstractTreeStructure {
private final AbstractTreeStructure myDelegee;
public Delegate(AbstractTreeStructure delegee) {
myDelegee = delegee;
}
@Override
public Object getRootElement() {
return myDelegee.getRootElement();
}
@Override
public Object[] getChildElements(Object element) {
return myDelegee.getChildElements(element);
}
@Override
public Object getParentElement(Object element) {
return myDelegee.getParentElement(element);
}
@NotNull
@Override
public NodeDescriptor createDescriptor(Object element, NodeDescriptor parentDescriptor) {
return myDelegee.createDescriptor(element, parentDescriptor);
}
@Override
public void commit() {
myDelegee.commit();
}
@Override
public boolean hasSomethingToCommit() {
return myDelegee.hasSomethingToCommit();
}
@Override
public boolean isToBuildChildrenInBackground(Object element) {
return myDelegee.isToBuildChildrenInBackground(element);
}
@Override
public boolean isAlwaysLeaf(Object element) {
return myDelegee.isAlwaysLeaf(element);
}
@Override
public AsyncResult<Object> revalidateElement(Object element) {
return myDelegee.revalidateElement(element);
}
public AbstractTreeStructure getOriginalStructure() {
return myDelegee;
}
}
}
File diff suppressed because it is too large Load Diff
@@ -204,9 +204,14 @@ public class AbstractTreeUpdater implements Disposable, Activatable {
@Override
public void run() {
if (myTreeBuilder.getTreeStructure().hasSomethingToCommit()) {
myTreeBuilder.getTreeStructure().commit();
reQueueViewUpdateIfNeeded();
AbstractTreeStructure structure = myTreeBuilder.getTreeStructure();
if (structure.hasSomethingToCommit()) {
structure.asyncCommit().doWhenDone(new Runnable() {
@Override
public void run() {
reQueueViewUpdateIfNeeded();
}
});
return;
}
try {
@@ -222,7 +227,7 @@ public class AbstractTreeUpdater implements Disposable, Activatable {
});
}
private void queue(Update update) {
private void queue(@NotNull Update update) {
if (isReleased()) return;
myUpdateQueue.queue(update);
@@ -18,6 +18,7 @@ package com.intellij.ui.treeStructure.filtered;
import com.intellij.ide.util.treeView.AbstractTreeStructure;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.ide.util.treeView.PresentableNodeDescriptor;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.ui.speedSearch.ElementFilter;
import com.intellij.ui.treeStructure.SimpleNode;
import org.jetbrains.annotations.NotNull;
@@ -154,6 +155,12 @@ public class FilteringTreeStructure extends AbstractTreeStructure {
return myBaseStructure.hasSomethingToCommit();
}
@NotNull
@Override
public ActionCallback asyncCommit() {
return myBaseStructure.asyncCommit();
}
public class FilteringNode extends SimpleNode {
private Object myDelegate;
private State state = State.VISIBLE;
@@ -153,15 +153,6 @@ public abstract class AbstractTreeBuilderCrashTest extends BaseTreeTestCase {
public NodeDescriptor doCreateDescriptor(final Object element, final NodeDescriptor parentDescriptor) {
return (NodeDescriptor)element;
}
@Override
public void commit() {
}
@Override
public boolean hasSomethingToCommit() {
return false;
}
};
@@ -22,6 +22,7 @@ import com.intellij.lang.ant.config.*;
import com.intellij.lang.ant.config.impl.MetaTarget;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
@@ -37,6 +38,7 @@ final class AntExplorerTreeStructure extends AbstractTreeStructure {
private final Object myRoot = new Object();
private boolean myFilteredTargets = false;
private static final Comparator<AntBuildTarget> ourTargetComparator = new Comparator<AntBuildTarget>() {
@Override
public int compare(final AntBuildTarget target1, final AntBuildTarget target2) {
final String name1 = target1.getDisplayName();
if (name1 == null) return Integer.MIN_VALUE;
@@ -55,6 +57,7 @@ final class AntExplorerTreeStructure extends AbstractTreeStructure {
return true;
}
@Override
@NotNull
public AntNodeDescriptor createDescriptor(Object element, NodeDescriptor parentDescriptor) {
if (element == myRoot) {
@@ -77,6 +80,7 @@ final class AntExplorerTreeStructure extends AbstractTreeStructure {
return null;
}
@Override
public Object[] getChildElements(Object element) {
final AntConfiguration configuration = AntConfiguration.getInstance(myProject);
if (element == myRoot) {
@@ -84,7 +88,7 @@ final class AntExplorerTreeStructure extends AbstractTreeStructure {
return new Object[] {AntBundle.message("loading.ant.config.progress")};
}
final AntBuildFile[] buildFiles = configuration.getBuildFiles();
return (buildFiles.length != 0) ? buildFiles : new Object[]{AntBundle.message("ant.tree.structure.no.build.files.message")};
return buildFiles.length != 0 ? buildFiles : new Object[]{AntBundle.message("ant.tree.structure.no.build.files.message")};
}
if (element instanceof AntBuildFile) {
@@ -102,13 +106,10 @@ final class AntExplorerTreeStructure extends AbstractTreeStructure {
return targets.toArray(new AntBuildTarget[targets.size()]);
}
if (element instanceof AntBuildTarget) {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
@Override
@Nullable
public Object getParentElement(Object element) {
if (element instanceof AntBuildTarget) {
@@ -125,14 +126,23 @@ final class AntExplorerTreeStructure extends AbstractTreeStructure {
return null;
}
@Override
public void commit() {
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
}
@Override
public boolean hasSomethingToCommit() {
return PsiDocumentManager.getInstance(myProject).hasUncommitedDocuments();
}
@NotNull
@Override
public ActionCallback asyncCommit() {
return asyncCommitDocuments(myProject);
}
@Override
public Object getRootElement() {
return myRoot;
}
@@ -146,14 +156,17 @@ final class AntExplorerTreeStructure extends AbstractTreeStructure {
super(project, parentDescriptor);
}
@Override
public boolean isAutoExpand() {
return true;
}
@Override
public Object getElement() {
return myRoot;
}
@Override
public boolean update() {
myName = "";
return false;
@@ -167,14 +180,17 @@ final class AntExplorerTreeStructure extends AbstractTreeStructure {
myColor = Color.blue;
}
@Override
public Object getElement() {
return myName;
}
@Override
public boolean update() {
return true;
}
@Override
public boolean isAutoExpand() {
return true;
}