Bug 376890 - ProjectExplorer - Duplicate Items
Summary: ProjectExplorer - Duplicate Items
Status: NEW
Alias: None
Product: CDT
Classification: Tools
Component: cdt-core (show other bugs)
Version: Next   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact: Jonah Graham CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-04-16 12:04 EDT by Heiko Böttger CLA
Modified: 2020-09-04 15:21 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Heiko Böttger CLA 2012-04-16 12:04:30 EDT
Build Identifier: 20120216-1857

The CDT CNavigatorContentProvider adds items independend of the resources contained in the Set passed to the getPipelinedChildren-Method. This results in duplicate items if another ContentProvider replaces a folder by its own element. This can be simply reproduced by adding the javanature and cdtnature to the same project. 

The documentation of the getPipelinedChildren says nothing about adding unrelated items, but it says "Intercept the children that would be contributed". If I have understood the CNF corretly, that means only the children contained in the set should be handled and replaced by zero, one or multiple elements. 

Currently I have no idea how to workaround this without overwriting the CNavigatorContentProvider, which is likely to happend for other CNF-Contributions like as well. May be some one working on the CNF-Framework could make an improved to the framework inorder to reduce things like this.
 


Reproducible: Always

Steps to Reproduce:
1. Create a CDT-Project
2. Add the Java-Nature
3. Open ProjectExplorer and search for the src-Folder (it appears twice)
Comment 1 Anton Leherbauer CLA 2012-05-11 08:00:47 EDT
Both, the JDT and the CDT CNF content provider apply exactly the same algorithm:
1) override any upstream resource with their custom element (if any)
2) don't add resources for already customized resources (elements adaptable to IResource)
They don't try to replace any customized element from upstream or suppress their own customized element if there is already an upstream custom element for the same resource.
And this makes sense, because e.g. a source folder could be both a Java source folder and a C/C++ source folder. This can only be represented with two distinct nodes.

In case of Java and C nature, the JDT content provider is even called after the CDT one, so it would be the JDT content provider to add duplicate items.

I'm inclined to mark this as invalid.  Feel free to move this to the CNF realm (Platfom/UI).
Comment 2 Heiko Böttger CLA 2012-05-14 02:51:17 EDT
Thanks for looking at this bug and sorry for answering so late.

In my org.eclipse.cdt bundle with version 5.3.2.201202111925 the CNavigatorContentProvider contains the following code:

private void customizeCElements(Object[] cChildren, Set<Object> proposedChildren) {
		List<Object> elementList= Arrays.asList(cChildren);
		for (Object element : proposedChildren) {
			IResource resource= null;
			if (element instanceof IResource) {
				resource= (IResource)element;
			} else if (element instanceof IAdaptable) {
				resource= (IResource)((IAdaptable)element).getAdapter(IResource.class);
			}
			if (resource != null) {
				int i= elementList.indexOf(resource);
				if (i >= 0) {
					cChildren[i]= null;
				}
			}
		}
		for (Object element : cChildren) {
			if (element instanceof ICElement) {
				ICElement cElement= (ICElement)element;
				IResource resource= cElement.getResource();
				if (resource != null) {
					proposedChildren.remove(resource);
				}
				proposedChildren.add(element);
			} else if (element != null) {
				proposedChildren.add(element);
			}
		}
	}

However I cannot see how this makes sure, that if an object was removed from proposedChildren, is not added by the second for-loop. One problem is that there must be an element adaptable to IResource inorder to avoid duplicates. 
The second problem seems to be the elementList.indexOf, i cannot see how that works. When I remember right, there is no IResource in the elementList, it is a CContainer and this will always result in -1.

But you are right it seems to be the JavaNavigatorContentProvider in this case, because it uses nearly the same code. 

For me it would be good enough if there would be a possibility to just tell CDT to not replace containers by CContainers. Is this some how possible, by specifying a folder in project to be the src-Folder?
Comment 3 Anton Leherbauer CLA 2012-05-14 03:55:43 EDT
(In reply to comment #2)
> The second problem seems to be the elementList.indexOf, i cannot see how that
> works. When I remember right, there is no IResource in the elementList, it is a
> CContainer and this will always result in -1.

As I mentioned before, the algorithm does not try to avoid "duplicates". The same resource adapted to different custom element types (e.g. Java source folder and C/C++ source folder) are not considered duplicates.
I understand that you would like to apply a more aggressive filtering on already customized resources, but that's hard to accomplish given that any change in this area can break other clients very easily.

> For me it would be good enough if there would be a possibility to just tell CDT
> to not replace containers by CContainers. Is this some how possible, by
> specifying a folder in project to be the src-Folder?

CDT adapts an IFolder to a CContainer if it is either a source folder or an output folder (or a member thereof).
The default source folder and output folder is the project root (if no explicit source or output folder is defined).
So, in theory, you can define source folder and output folder such that all resources appear as plain resources, but on the other hand you will loose most of the functionality CDT would provide for that resources.