diff --git a/platform/util/src/com/intellij/openapi/util/objectTree/ObjectNode.java b/platform/util/src/com/intellij/openapi/util/objectTree/ObjectNode.java index bd3843b2f926..af7660bd80f4 100644 --- a/platform/util/src/com/intellij/openapi/util/objectTree/ObjectNode.java +++ b/platform/util/src/com/intellij/openapi/util/objectTree/ObjectNode.java @@ -107,6 +107,7 @@ final class ObjectNode { ObjectTree.executeActionWithRecursiveGuard(this, myTree.getNodesInExecution(), new ObjectTreeAction>() { @Override public void execute(@NotNull ObjectNode each) { + if (myTree.getDisposalInfo(myObject) != null) return; // already disposed. may happen when someone does `register(obj, ()->Disposer.dispose(t));` abomination try { action.beforeTreeExecution(myObject); } @@ -167,7 +168,7 @@ final class ObjectNode { } } - private void removeFromObjectTree() { + void removeFromObjectTree() { synchronized (myTree.treeLock) { myTree.putNode(myObject, null); if (myParent == null) { diff --git a/platform/util/testSrc/com/intellij/openapi/util/objectTree/DisposerTest.java b/platform/util/testSrc/com/intellij/openapi/util/objectTree/DisposerTest.java index 129c0112d64e..caf35b02d32c 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/objectTree/DisposerTest.java +++ b/platform/util/testSrc/com/intellij/openapi/util/objectTree/DisposerTest.java @@ -94,6 +94,16 @@ public class DisposerTest extends TestCase { assertEquals(Arrays.asList(myFolder2, myLeaf1, myFolder1, myRoot), myDisposedObjects); } + public void testDisposalOrderNestedDispose() { + Disposer.register(myRoot, myFolder2); + //noinspection SSBasedInspection + Disposer.register(myRoot, () -> Disposer.dispose(myFolder2)); + + Disposer.dispose(myRoot); + + assertEquals(Arrays.asList(myFolder2, myRoot), myDisposedObjects); + } + public void testDirectCallOfDisposable() { SelDisposable selfDisposable = new SelDisposable("selfDisposable"); Disposer.register(myRoot, selfDisposable);