Community
Participate
Working Groups
Created attachment 145738 [details] Exception stack trace I don't have a test case or a sequence of events that everyone can use to reproduce this error because it occurs within our own RCP application, but I will try to explain it as best as I can. It seem that you can have an AbstractTreeViewer that contains a TreeItem that is expandable, but has a dummy node as a child (i.e. its children have not been loaded yet; see AbstractTreeViewer#updateChildren(Widget, Object, Object[], boolean) for reference). I'm not sure I understand exactly why a dummy node is needed, but I didn't dig into all of the code. The problem occurs when that dummy node (a TreeItem) was previously expanded during its last use. When getExpandedTreePaths is called, it subsequently calls internalCollectExpandedItems, which collects all expanded items, whether they are a dummy node or otherwise. When getTreePathFromItem is then called on that dummy node that was collected, it pulls out the data from that TreeItem and does an Assert.isNotNull. The data will always be null for a dummy node (I think), which causes getTreePathFromItem to fail. I am attaching the relevant part of the exception stack trace for reference. I took a quick peek at the 3.5 code and it seemed like it behaved the same way, although the flow was slightly different, but I haven't tested it out or investigated it thoroughly.
I meant to suggest a possible fix before I clicked submit. :) In AbstractTreeViewer#updateChildren: Old Code if (widget instanceof Item) { Item ti = (Item) widget; if (!getExpanded(ti)) { // need a dummy node if element is expandable; // but try to avoid recreating the dummy node boolean needDummy = isExpandable(ti, null, parent); boolean haveDummy = false; // remove all children Item[] items = getItems(ti); for (int i = 0; i < items.length; i++) { if (items[i].getData() != null) { disassociate(items[i]); items[i].dispose(); } else { if (needDummy && !haveDummy) { haveDummy = true; } else { items[i].dispose(); } } } Proposed fix (haven't tested this) if (needDummy && !haveDummy) { haveDummy = true; setExpanded(items[i], false); }
(In reply to comment #0) > I'm not sure I understand exactly why a dummy node is > needed, but I didn't dig into all of the code. The dummy node is needed because tree items without children won't show the "+" with which you can expand them. > The problem occurs when that dummy node (a TreeItem) was previously expanded > during its last use. When getExpandedTreePaths is called, it subsequently > calls internalCollectExpandedItems, which collects all expanded items, whether > they are a dummy node or otherwise. When getTreePathFromItem is then called on > that dummy node that was collected, it pulls out the data from that TreeItem > and does an Assert.isNotNull. The data will always be null for a dummy node (I > think), which causes getTreePathFromItem to fail. I am attaching the relevant > part of the exception stack trace for reference. Interesting - is this happening on multiple platforms, or just one? > I took a quick peek at the 3.5 code and it seemed like it behaved the same way, > although the flow was slightly different, but I haven't tested it out or > investigated it thoroughly. It would be good to write a test case or snippet which allows us to reproduce the problem, would you be able to do that?
I'll see if I can come up with a general test case that reproduces it.
Created attachment 145838 [details] TestCase to reproduce the error
Posted a testcase that should illustrate the error... This produces an error on Eclipse SDK Version: 3.4.2 Build id: M20090211-1700 as well as Eclipse 3.5 Build id: 20090619-0625 running on Windows Vista SP2 with the Sun 1.4.2_19 JDK. I don't have any other suitable platforms to test on. My earlier analysis wasn't completely correct. For the error to occur, the viewer must be configured to use HashLookup ( setUseHashlookup(true) ). This comes into play when items are being disassociated. Additionally, my suggested fix does not seem to be adequate. Just setting the expanded state of the dummy node is not sufficient, as that dummy node can still have child items that are expanded. These expanded items will still get pulled in by getExpandedTreePaths and cause an exception.
Created attachment 152196 [details] patch I decided to fix this in the code that collects the expanded items.
Released to HEAD.
Test released as well. Thanks for contributing the test case!
Verified using I20100425-2000 and by checking that the test case is run as part of our builds.