Community
Participate
Working Groups
The Java content provider for the Project Explorer overrides the Resources content provider. What it does is remove all resources from the children of IWorkspaceRoot and then adds back either Java projects or Resource projects. The problem is that there may be other content extensions that have replaced resource projects with model projects and these projects will get added back resulting in what appears like duplicate entries in the Project Explorer. The algorithm in the getPipelinedElements should be: 1) Remove all projects that have the Java nature 2) Add all Java projects to the result
Is this a change you need for 3.2? Or 3.2.1? I think the change is safe to make.
I don't need it at all. I just noticed the behavior when working on an model example that uses the Project Explorer. Given that most of the current clients are built on top of the Java content provider anyway, it's probably not a stop-ship for 3.2. I'll leave it up to you (and JDT/UI) to decide whether the fix should be in 3.2.1 or wait until 3.3.
In that case, I'd recommend a fix for 3.2.1.
Created attachment 46827 [details] Patches JavaNavigatorContentProvider to filter only Java Projects
Martin -- would you review for release to M20060802?
I don't think that the patch works for Michael's example. You should only add back Java projects, but children (=getElements(input)) contains resource and Java projects. The correct implementation to iterate through all elements and one by one replace IProjects that have a Java nature. It could also be that a content extensions replaced a IProject with Java nature. So this project shouldn't show up again.
If this isn't a serious problem, I'm inclined to defer it to 3.3; I know of no extension that is affected by this behavior. Michael V and Martin -- are you okay with this?
I wouldn't mind seeing this fixed as it seems to me that getPipelinedChildren is fundamentally broken.
Originally, JDT/UI wanted their extension to return Java and Resource content. In the WTP version, there was a split; one extension returned resources, and one extension returned only Java elements. To change getChildren() to only return Java elements is a pretty big change for this timeframe; if I misunderstood your original comments, could you rephrase?
I'm only concerned about the method 'getPipelinedElements'. I'm not sure where and if it is used. But if I understand right, its implementation should iterate through all 'currentChildren' and test each if it is of type IProject and if it's nature is a Java nature. If that's the case, it should be replaced it by the corresponding Java element. That leaves all non-java projects and other projects of unknown type as they are.
I am seeing a problem with the JavaNavigatorContentProvider that I think is related to this one, so I'll just post a comment here first - please let me know if this should be a new bug. I am adding a model content provider to the project explorer for projects of a given nature. I am overriding the resource content provider, replacing projects with my Foo nature and their resources with my model elements. The pb I see has to do with resource changes: the java navigator content provider is posting adds (postAdd, see stack traces below) for resources, instead of relying on intercept add to intercept the changes posted by the resource content provider. It does so not only for java resources (which I suspect it shouldn't), but also for non-java resources (e.g. folder in a project that doesn't have a java nature). The result is that the viewer.add method (and thus the interceptAdd methods of overriding extensions) is called twice for each add. Note that the same is probably true of most other resource change event types. Here are 3 stack traces that demonstrate the pb. They have been obtained by opening both the (legacy) Navigator view and the project explorer view, and creating a new folder under a Foo (non-java) project using the Navigator popup menu: trace1: JavaNavigatorContentProvider posts an add: ------------------------------------------------------ JavaNavigatorContentProvider(PackageExplorerContentProvider).postAdd(Object, Object) line: 623 JavaNavigatorContentProvider.postAdd(Object, Object) line: 221 JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDelta(IResourceDelta, Object) line: 549 JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDeltas(IResourceDelta[], Object) line: 579 JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDelta(IResourceDelta, Object) line: 556 JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDeltas(IResourceDelta[], Object) line: 579 JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDelta(IResourceDelta, Object) line: 556 JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDeltas(IResourceDelta[], Object) line: 579 JavaNavigatorContentProvider(PackageExplorerContentProvider).processDelta(IJavaElementDelta) line: 422 JavaNavigatorContentProvider(PackageExplorerContentProvider).elementChanged(ElementChangedEvent) line: 105 DeltaProcessor$3.run() line: 1448 SafeRunner.run(ISafeRunnable) line: 37 DeltaProcessor.notifyListeners(IJavaElementDelta, int, IElementChangedListener[], int[], int) line: 1438 DeltaProcessor.firePostChangeDelta(IJavaElementDelta, IElementChangedListener[], int[], int) line: 1286 DeltaProcessor.fire(IJavaElementDelta, int) line: 1265 DeltaProcessor.resourceChanged(IResourceChangeEvent) line: 1824 DeltaProcessingState.resourceChanged(IResourceChangeEvent) line: 444 NotificationManager$2.run() line: 280 SafeRunner.run(ISafeRunnable) line: 37 NotificationManager.notify(ResourceChangeListenerList$ListenerEntry[], IResourceChangeEvent, boolean) line: 274 NotificationManager.broadcastChanges(ElementTree, ResourceChangeEvent, boolean) line: 148 Workspace.broadcastPostChange() line: 256 --------------------------------- trace 2: JavaNavigatorContentProvider interceptAdd is called as a result of #1: ---------------------------------- JavaNavigatorContentProvider.interceptAdd(PipelinedShapeModification) line: 146 SafeDelegateTreeContentProvider.interceptAdd(PipelinedShapeModification) line: 224 NavigatorPipelineService.pipelineInterceptAdd(PipelinedShapeModification, ContributorTrackingSet, INavigatorContentDescriptor) line: 95 NavigatorPipelineService.interceptAdd(PipelinedShapeModification) line: 79 CommonViewer.add(Object, Object[]) line: 260 CommonViewer(AbstractTreeViewer).add(Object, Object) line: 593 PackageExplorerContentProvider$4.run() line: 629 PackageExplorerContentProvider$7.run() line: 666 ------------------------------------ trace 3: JavaNavigatorContentProvider is called again as a result of the add posted by the resource content provider: ------------------------------------ JavaNavigatorContentProvider.interceptAdd(PipelinedShapeModification) line: 146 SafeDelegateTreeContentProvider.interceptAdd(PipelinedShapeModification) line: 224 NavigatorPipelineService.pipelineInterceptAdd(PipelinedShapeModification, ContributorTrackingSet, INavigatorContentDescriptor) line: 95 NavigatorPipelineService.interceptAdd(PipelinedShapeModification) line: 79 CommonViewer.add(Object, Object[]) line: 260 ResourceExtensionContentProvider$2.run() line: 256 ResourceExtensionContentProvider.runUpdates(Collection) line: 295 ResourceExtensionContentProvider.access$1(ResourceExtensionContentProvider, Collection) line: 292 ResourceExtensionContentProvider$1.run() line: 118
not for 3.2.2
I've just noticed that in the Project Explorer when running with CDT you get duplicate entries for CDT Projects. The CDT Navigator Content Provider adds its own ICProject objects in place of the platforms IProject objects, but the IProject objects still appear. Stepping through whats going on in the debugger, the sequence is (1) the resources plugin adds its content (2) the two overriding extensions (CDT, JDT) are processed in that respective order (3) CDT adds ICProject objects, and remove their corresponding IProject objects (4) JDT adds both Java and Non-Java projects the line where non-Java projects are added is: ===== public Object[] getChildren(Object parentElement) { try { if (parentElement instanceof IJavaModel) return concatenate(getJavaProjects((IJavaModel)parentElement), getNonJavaProjects((IJavaModel)parentElement)); ===== in ===== Thread [main] (Suspended) JavaNavigatorContentProvider(PackageExplorerContentProvider).getChildren(Object) line: 202 JavaNavigatorContentProvider(StandardJavaElementContentProvider).getElements(Object) line: 151 JavaNavigatorContentProvider.getElements(Object) line: 102 JavaNavigatorContentProvider.getPipelinedElements(Object, Set) line: 131 NavigatorContentServiceContentProvider.pipelineElements(Object, NavigatorContentExtension[], ContributorTrackingSet) line: 355 NavigatorContentServiceContentProvider.getElements(Object) line: 162 CommonViewer(StructuredViewer).getRawChildren(Object) line: 936 ===== I'm new to the CNF framework, but reading through this bugzilla - it does sound like the Java content provider should not return content it does not own, and this is consistent with the problem I'm seeing? thanks, Andrew
This was fixed with the patch for bug 150404.