Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse Platform » Common Navigator setup question
Common Navigator setup question [message #440666] Fri, 31 July 2009 04:59 Go to next message
Franck Mising name is currently offline Franck Mising name
Messages: 91
Registered: July 2009
Location: France
Member
I am really struggling with the incompatible changes introduced in the CNF
with the Galileo release... still working through issues and trying to
create reproducible test cases, but before spending any more hours in the
debugger I would really appreciate it if someone could help me confirm
that my overall setup is correct.

In the Project Explorer, I want to replace IProjects with a certain nature
and all their descendants with my model nodes M1Project, M1Folder and
M1File.
Furthermore another plugin supports higher level abstractions and needs to
replace certain M1File nodes with M2Files.

To achieve this I have declared two overriding content extensions
(M1Resource is a common base class of all M1 nodes, same for M2):

M1:
contentProvider="cnf_test.M1ContentProvider"
labelProvider="cnf_test.ResourceWrapperLabelProvider"
override:
suppressedExtensionId="org.eclipse.ui.navigator.resourceContent "
triggerPoints: instanceof org.eclipse.core.resources.IWorkspaceRoot
possibleChildren: instanceof cnf_test.M1Resource

M2:
contentProvider="cnf_test.M2ContentProvider"
labelProvider="cnf_test.ResourceWrapperLabelProvider"
override: suppressedExtensionId="CNF_Test.M1"
triggerPoints: instanceof cnf_test.M1Folder
possibleChildren: instanceof cnf_test.M2Resource

M1ContentProvider implements getPipelinedElements and getPipelinedParent
to replace IProjects with M1Projects and conversely,
and implements getChildren and getParent for M1 nodes.

M2ContentProvider does the same for M2 nodes but implements
getPipelinedChildren rather than getPipelinedElements.

Both content providers listen to resource changes and translate resource
deltas into calls to the appropriate viewer.update(<model node>) or
viewer.refresh(model node).

Is this setup basically correct or did I miss anything fundamental? The
issues I am seeing are multiple, often triggered by external resource
changes (e.g. new folder under created M1Project) not being properly
reflected in the project explorer.

Any help would be greatly appreciated, I have stopped counting the time I
have spent debugging this and I am getting really frustrated :(

Thanks!
Franck
Re: Common Navigator setup question [message #440972 is a reply to message #440666] Fri, 31 July 2009 05:25 Go to previous messageGo to next message
Franck Mising name is currently offline Franck Mising name
Messages: 91
Registered: July 2009
Location: France
Member
Forgot to mention that both providers implement all the interceptXxx
methods as expected, replacing IResources with M1 nodes (M1 provider) or
M1Files with M2Files (M2 provider)...

Franck
Re: Common Navigator setup question [message #441259 is a reply to message #440666] Fri, 31 July 2009 06:08 Go to previous messageGo to next message
Franck Mising name is currently offline Franck Mising name
Messages: 91
Registered: July 2009
Location: France
Member
Here is a first specific use case where I am seeing strange CNF behavior.

Based on discussions I saw on bugzilla on label providers being searched
by trigger points I have updated augmented my triggerPoints with the
possibleChildren condition (i.e. M1 trigger points are now [IWorkspaceRoot
or any M1Resource], M2 are [M1Project or M1Folder or any M2Resource]).

If I use File->New->Folder... to create a new folder directly under an
M1Project, my M1 resource listener issues a call to
viewer.refresh(M1Project).

The image for newM1Folder should be provided by the M1LabelProvider.
The refresh call goes down to
NavigatorContentServiceLabelProvider.getImage(newM1Folder)
which in turns looks for possible contributing extensions by calling
findDescriptorsByTriggerPoint(newM1Folder, considerOverrides=false).

That method only considers firstClassDescriptorsSet members as candidate
extensions, which my M1 content extension is not (it overrides resources).
It would also consider getSourceOfContribution(newM1Folder) but that
returns null (more on this below), and in the end the image returned is
null.

Should I declare two navigator content extensions for M1, one overriding
the core resources provider and another not overriding anything (to
account for providing M1 children or M1 containers)??

Regarding contributions sources, I am tracing and seeing very strange
things, in particular M1Folders being marked as contributed by the
M2Provider, due to this line in NavigatorContentServiceContentProvider:

// Update contributor even if not pipelining as this is where it is
recorded by
viewer pipelinedChildren.setContributor((NavigatorContentDescriptor )
theOverridingExtensions[i].getDescriptor());

I don't quite understand the comment, but this code will mark an M1Folder
and all its M1 children as having been contributed my M2, simply because
M2 wanted a chance to maybe replace a few specific M1 children... this
looks wrong?
This trace demonstrates the pb:
rememberContribution: Content[CNF_Test.M2, "M2 model provider"]:
cnf_test.M1Folder@2c073c61
rememberContribution: Content[CNF_Test.M2, "M2 model provider"]:
cnf_test.M1Folder@2c073c71
rememberContribution: Content[CNF_Test.M2, "M2 model provider"]:
cnf_test.M1Folder@2c073c79
rememberContribution: Content[CNF_Test.M2, "M2 model provider"]:
cnf_test.M2Resource@58cfeb49
rememberContribution: Content[CNF_Test.M2, "M2 model provider"]:
cnf_test.M1File@89d4cd29

Should I just disregard those erroneous contribution assignments??

Thanks!
Franck
Re: Common Navigator setup question [message #441978 is a reply to message #440666] Fri, 31 July 2009 07:52 Go to previous messageGo to next message
Franck Mising name is currently offline Franck Mising name
Messages: 91
Registered: July 2009
Location: France
Member
Another suspicious behavior in NavigatorContentService.internalGetChildren:

enabledExtensions = findContentExtensionsByTriggerPoint(M1Folder)

will include both M1 and M2 providers (M2 may want to replace M1Folder
children).

The loop over enabledExtensions processes M1 first which correctly return
M1 an M2 children.
It then gets to M2, which presumable should be skipped due to this test:

if (!isOverridingExtensionInSet(foundExtension.getDescriptor(),
enabledExtensions))

but isOverridingExtensionInSet(M2, [M1,M2]) returns false because M2 is
set to InvokeOnlyIfSuppressedExtAlsoVisibleAndActive... in other terms,
because of that setting M2 is invoked both as a pipelined extension of M1
and as a first class extension, which is the opposite of what I would
expect.

Franck
Processing of viewer.remove [message #443662 is a reply to message #440666] Fri, 31 July 2009 11:27 Go to previous messageGo to next message
Franck Mising name is currently offline Franck Mising name
Messages: 91
Registered: July 2009
Location: France
Member
Still digging, and trying to figure out whether CommonViewer.remove(IFile)
which is invoked by the resource listener in the ResourceContent provider
could be made to invoke my M1Provider.interceptRemove.

At this point it doesn't because starting from CommonViewer.remove(IFile),
NavigatorPipelineService.interceptRemove first correctly identifies the
ResourceContent provider as an interested provider because it has IFile as
a possible child.
However it proceeds with pipelineInterceptRemove which looks for
overriding extensions of ResourceContent that also have IFile as a
possible child.

My M1 provider doesn't have resources as possible children, since its
purpose is to replace resources with M1Resources.

Should I add IResources to the possible children of M1 (doesn't look
right)? Or do I need to keep my resource listener in the M1 provider that
issues viewer.remove(M1File)?
Interestingly enough interceptAdd(IFile) does call my
M1Provider.interceptAdd (and recursively calls M2.interceptAdd())... so
really confused as to which resource events my providers need to react to
and which viewer calls they should issue.

Keeping the listeners I end up with many useless calls to viewer.add,
remove and refresh coming from each provider in the stack of overriding
providers.
Filed bug #285344 [message #446979 is a reply to message #440666] Fri, 31 July 2009 19:35 Go to previous message
Franck Mising name is currently offline Franck Mising name
Messages: 91
Registered: July 2009
Location: France
Member
... please comment and vote. I have identified the change from Ganymede in
NavigatorContentServiceContentProvider.pipelineChildren that is breaking
existing CNF contributors.

Thanks,
Franck
Previous Topic:CompareUI Dialog and "exact" differences
Next Topic:What Restrictions Does Eclipse Impose On Plugin Development
Goto Forum:
  


Current Time: Fri Aug 01 03:57:28 EDT 2014

Powered by FUDForum. Page generated in 0.01676 seconds