Skip to content

Conversation

@ptziegler
Copy link
Contributor

@ptziegler ptziegler commented Nov 10, 2025

Due to the fix for Bug 210747, a dummy tree-item is added to the viewer if the same element is removed twice. The intend of the original fix is to remove the "expand" icon from a tree item, when its still collapsed children are removed from the viewer (but not the model).

The problem with this approach is that it doesn't take the situation into consideration, where the children of the item have already been removed.

Given a tree item with at least one child in the data model but where all child-widgets have been removed in the viewer. When removing the children again, this internally calls updatePlus(Item,Object).

But because the number of child-widgets doesn't match the number of children, this method now creates a dummy item, to correct this inconsistency. This problem doesn't occur when calling internalRemove(Object,Object[]), because here the call to
updatePlus(Item,Object) is guarded by a check to make sure the tree item has at least one child-widget.

To reproduce:

  1. Make sure the ".* resources" filter is enabled
  2. Create a new project "Project A" and "Project B"
  3. Create a new text file "test" in "Project A"
  4. Move "test" to "Project B"

Closes #3525

@ptziegler ptziegler marked this pull request as draft November 10, 2025 13:09
@ptziegler
Copy link
Contributor Author

@laeubi This fixes the issue with the project explorer. Though I'd still like to add a proper test case.

@laeubi
Copy link
Contributor

laeubi commented Nov 10, 2025

@ptziegler good finding! I can guess its hard to come of with a simple testcase here given JDT is involved and we likely do not want to include it as a dependency.

@iloveeclipse
Copy link
Member

Considering M3 is this week, I would prefer to postpone this change to 4.39 (assuming it works() in general and not only for specific use case).

This change (which affects org.eclipse.jface.viewers.AbstractTreeViewer.remove(Object...)` behavior must be tested for a longer time before release.

@ptziegler
Copy link
Contributor Author

Aaah, now everything makes sense. The dummy tree item is created in updatePlus(...), in response to Bug [210747]

image

I can guess its hard to come of with a simple testcase here given JDT is involved and we likely do not want to include it as a dependency.

The remove() method might be called from anywhere. It just happens to be JDT for the Project Explorer. The difficult part is finding a good test case that can be adapted. 😄

@github-actions
Copy link
Contributor

github-actions bot commented Nov 10, 2025

Test Results

 3 018 files  +121   3 018 suites  +121   2h 15m 45s ⏱️ - 9m 32s
 8 242 tests +  6   7 994 ✅ +  6  248 💤 ±0  0 ❌ ±0 
23 646 runs  +794  22 855 ✅ +792  791 💤 +2  0 ❌ ±0 

Results for commit 806fd4b. ± Comparison against base commit 02fc196.

♻️ This comment has been updated with latest results.

@ptziegler
Copy link
Contributor Author

ptziegler commented Nov 10, 2025

I had a closer look at Bug 210747 and whatever was done with f1899ad doesn't work, regardless of my change.

Steps To Reproduce:

  1. The content provider returns three elements (a), (b) and (c), while (b) is a child of (a) and (c) is a child of (b)

  2. programatically expand item (a)
    observe: item (b) is rendered with a plus sign

  3. Call AbstractTreeViewer.remove() to remove item (c)
    observe: the plus sign is not removed

As it is, item (b) continues to have a dummy tree-item as its child and would therefore show a plus sign. This is because the element is only removed from the UI and the call to isExpandable(...) queries the content provider (i.e. the model). So needsPlus returns true, even if its only child has just been removed.

boolean hasPlus = getItemCount(item) > 0;
boolean needsPlus = isExpandable(item, null, element);
boolean removeAll = false;

What a mess...

@ptziegler ptziegler force-pushed the issue3525 branch 2 times, most recently from 652520a to 657b1b7 Compare November 11, 2025 09:40
@ptziegler ptziegler marked this pull request as ready for review November 11, 2025 09:43
@ptziegler
Copy link
Contributor Author

I've adapted the check so that for the use-case described in Bug 210747, where an element was removed from the tree that hasn't been realized yet, the updatePlus() method is still called. In my use-case, where an element is removed twice, nothing happens the second time.

I'm still not sure what the reasoning behind the initial change was, but I'm fairly confident that what was described in the bug was never fixed and probably can't be reasonbly fixed.

I've added a test case for this bug, which will obviously fail. Perhaps someone who is more familiar with the TreeViewer can have a look, otherwise I'll remove it again for the next M1.

Considering M3 is this week, I would prefer to postpone this change to 4.39 (assuming it works() in general and not only for specific use case).

This change (which affects org.eclipse.jface.viewers.AbstractTreeViewer.remove(Object...)` behavior must be tested for a longer time before release.

That's fine by me. This problem has existed for almost two decades, so three more months won't make much of a difference.

@ptziegler ptziegler changed the title Don't try to remove elements that are not in the tree #3525 Don't create dummy item when removing invalid element from tree #3525 Nov 11, 2025
@ptziegler
Copy link
Contributor Author

ptziegler commented Nov 12, 2025

I'm a little bit concerned about this code block here, which is also responsible for the test failure and which was added with #810

boolean continueOuter = false;
if (getItemsLimit() > 0) {
Widget[] itemsOfElement = internalFindItems(element);
for (Widget item : itemsOfElement) {
if (item instanceof TreeItem ti) {
TreeItem parentItem = ti.getParentItem();
if (parentItem == null) {
internalRefreshStruct(ti.getParent(), getInput(), false);
continueOuter = true;
break;
}
// refresh parent item with the latest model.
internalRefreshStruct(parentItem, parentItem.getData(), false);
continueOuter = true;
}
}
}
if (continueOuter) {
continue;
}

In short, if setDisplayIncrementally() is called, you are no longer able to remove elements from the viewer without first removing them from the model.

@ptziegler ptziegler force-pushed the issue3525 branch 3 times, most recently from ad4c5c7 to 562ad67 Compare November 12, 2025 13:22
@eclipse-platform-bot
Copy link
Contributor

eclipse-platform-bot commented Dec 1, 2025

This pull request changes some projects for the first time in this development cycle.
Therefore the following files need a version increment:

bundles/org.eclipse.jface/META-INF/MANIFEST.MF
tests/org.eclipse.jface.tests/META-INF/MANIFEST.MF

An additional commit containing all the necessary changes was pushed to the top of this PR's branch. To obtain these changes (for example if you want to push more changes) either fetch from your fork or apply the git patch.

Git patch
From eeb93ec168a1ceae99cc3198d03fd9d50661a1fb Mon Sep 17 00:00:00 2001
From: Eclipse Platform Bot <platform-bot@eclipse.org>
Date: Fri, 5 Dec 2025 15:04:33 +0000
Subject: [PATCH] Version bump(s) for 4.39 stream


diff --git a/bundles/org.eclipse.jface/META-INF/MANIFEST.MF b/bundles/org.eclipse.jface/META-INF/MANIFEST.MF
index b2c427bf1a..81de89277b 100644
--- a/bundles/org.eclipse.jface/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.jface/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jface;singleton:=true
-Bundle-Version: 3.38.100.qualifier
+Bundle-Version: 3.38.200.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Export-Package: org.eclipse.jface,
diff --git a/tests/org.eclipse.jface.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.jface.tests/META-INF/MANIFEST.MF
index b8dc172d3e..8cadbfa2c6 100644
--- a/tests/org.eclipse.jface.tests/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.jface.tests/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: org.eclipse.jface.tests
-Bundle-Version: 1.4.1100.qualifier
+Bundle-Version: 1.4.1200.qualifier
 Automatic-Module-Name: org.eclipse.jface.tests
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Require-Bundle: org.junit;bundle-version="4.12.0",
-- 
2.52.0

Further information are available in Common Build Issues - Missing version increments.

@ptziegler
Copy link
Contributor Author

If there are no objections (and if the remaining checks succeed), I'll plan on merging this within the next few days.

@iloveeclipse
Copy link
Member

@ptziegler : not sure if the commit title & message, PR title & message are reflecting the actual fix?
It would be good to update everything to the latest change state.

@iloveeclipse
Copy link
Member

To reproduce:

  • Create a new project "Project A" and "Project B"
  • Create a new text file "test" in "Project A"
  • Move "test" to "Project B"

I can't reproduce on master, tried with Package and Project Explorers. Anything missing, like projects should be expanded / collapsed etc? Or is this only Windows specific (I'm on RHEL Linux/X11).

@iloveeclipse
Copy link
Member

iloveeclipse commented Dec 1, 2025

I can't reproduce on master, tried with Package and Project Explorers. Anything missing, like projects should be expanded / collapsed etc?

OK, following is needed:

  1. Create a new project "X" and "Y".
  2. Make sure in view preferences there is no other files or directories (like .settings, .project etc) are shown, so both projects are shown as "empty".
  3. Create a new text file "hello.txt" in "X". It should be the only visible file in the project.
  4. Move "hello.txt" to "Y".
  5. kaboom: the Package Explorer doesn't show "hello.txt", and Project Explorer shows strange empty node
image

@iloveeclipse
Copy link
Member

This patch doesn't fix for me the problem with the steps above.

@ptziegler
Copy link
Contributor Author

Make sure in view preferences there is no other files or directories (like .settings, .project etc) are shown, so both projects are shown as "empty".

Yes, the resource filter for files starting with a '.' needs to be enabled. Apologies for the inaccuracy.

This patch doesn't fix for me the problem with the #3527 (comment).

On Linux, this block is entered, which then causes the creation of an additional tree item. But not on Windows. Commenting this block out makes the viewer behave as expected, but that shouldn't be the solution.

if (!getExpanded(ti)) {
boolean needDummy = isExpandable(ti, path, parent);
boolean haveDummy = false;
// remove all children
Item[] items = getItems(ti);
for (Item item : items) {
if (item.getData() != null) {
disassociate(item);
item.dispose();
} else if (needDummy && !haveDummy) {
haveDummy = true;
} else {
item.dispose();
}
}
// append a dummy if necessary
if (needDummy && !haveDummy) {
newItem(ti, SWT.NULL, -1);
}
return;
}

The call to getExpanded() is simply delegated to the TreeItem widget. This looks like in inconsistency in SWT? Both on Linux and Windows, this method should return true.

@Override
protected boolean getExpanded(Item item) {
return ((TreeItem) item).getExpanded();
}

@iloveeclipse
Copy link
Member

This looks like in inconsistency in SWT?

So it looks like the patch works on Windows only? Have you Mac access, any idea how it looks there?

Could you please investigate that Windows/Linux inconsistency before merging the patch?

@ptziegler
Copy link
Contributor Author

The TreeItem has a local variable that keeps track of the "expanded" state. However, this variable is not used inside getExpanded(), which instead calls the GTK API directly. The result is two conflicting values: true from the local variable and false from GTK. This doesn't look right...

image

@ptziegler
Copy link
Contributor Author

ptziegler commented Dec 1, 2025

So it looks like the patch works on Windows only?

That seems to be the cases, yes.

Have you Mac access, any idea how it looks there?

No, only Windows and Linux.

Could you please investigate that Windows/Linux inconsistency before merging the patch?

That's my current plan. If this really is an SWT issue, it should be possible to derive a small snippet with the same, inconsistent "expanded" state.

@iloveeclipse
Copy link
Member

iloveeclipse commented Dec 5, 2025

@ptziegler : not sure if the commit title & message, PR title & message are reflecting the actual fix? It would be good to update everything to the latest change state.

Can you please update commit message & rebase?

@ptziegler ptziegler changed the title Don't create dummy item when removing invalid element from tree #3525 Skip dummy item creation when removing invalid element from tree #3525 Dec 5, 2025
…pse-platform#3525

Due to the fix for Bug 210747, a dummy tree-item is added to the viewer
if the same element is removed twice. The intend of the original fix is
to remove the "expand" icon from a tree item, when its still collapsed
children are removed from the viewer (but not the model).

The problem with this approach is that it doesn't take the situation
into consideration, where the children of the item have already been
removed.

Given a tree item with at least one child in the data model but where
all child-widgets have been removed in the viewer. When removing the
children again, this internally calls `updatePlus(Item,Object)`.

But because the number of child-widgets doesn't match the number of
children, this method now creates a dummy item, to correct this
inconsistency. This problem doesn't occur when calling
`internalRemove(Object,Object[])`, because here the call to
`updatePlus(Item,Object)` is guarded by a check to make sure the tree
item has at least one child-widget.

To reproduce:

1) Make sure the ".* resources" filter is enabled
2) Create a new project "Project A" and "Project B"
3) Create a new text file "test" in "Project A"
4) Move "test" to "Project B"

Closes eclipse-platform#3525
@ptziegler ptziegler changed the title Skip dummy item creation when removing invalid element from tree #3525 Skip dummy item creation when removing element from viewer twice #3525 Dec 5, 2025
@ptziegler
Copy link
Contributor Author

@iloveeclipse I've updated the commit/pr message and elaborated a little bit on what exactly is going wrong and why.

@iloveeclipse iloveeclipse merged commit 2a814c8 into eclipse-platform:master Dec 9, 2025
18 checks passed
@iloveeclipse
Copy link
Member

Thanks @ptziegler. Sorry for delay, as usually totally overloaded...

@ptziegler
Copy link
Contributor Author

No worries. Thanks for also taking a look at this change. Otherwise I completely would've missed the weird behavior on Linux.

@ptziegler ptziegler deleted the issue3525 branch December 9, 2025 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Project explorer doesn't refresh correctly after moving files

4 participants