IFileNode.FindNextNode

Hi,

I use IFileNode.FindNextNode to find nodes in a PSI tree that satisfy a
specific predicate. The tooltip for the method tells "Returns first tree
node satisfying the predicate and located after the current node".

My question: which node is "the current node"? How can I set it?

For example I would like to do the following:

while (node = fileNode.FindNextNode(new TreeNodePredicate(MyPredicate))) {
// do something with node
}

private TreeNodeActionType MyPredicate(ITreeNode treeNode) {
if (treeNode is MyNodeType) {
return TreeNodeActionType.ACCEPT;
}
return TreeNodeActionType.CONTINUE;
}



Sincerely,
Stefan Lieser

5 comments
Comment actions Permalink

Hello Stefan,

current node here means the node which you call FindNextNode on (i.e., 'this').
I'm not sure
that using this function is a good idea - why not simply traverse the tree
(using ITreeNode.FirstChild,
NextSibling) and check each node? Also, you can use IElement interfaces and
IRecursiveElementProcessor
for traversing tree as IElement hierarchy.


Regards,
Dmitry Shaporenkov
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"

Hi,

I use IFileNode.FindNextNode to find nodes in a PSI tree that satisfy
a specific predicate. The tooltip for the method tells "Returns first
tree node satisfying the predicate and located after the current
node".

My question: which node is "the current node"? How can I set it?

For example I would like to do the following:

while (node = fileNode.FindNextNode(new
TreeNodePredicate(MyPredicate))) {
// do something with node
}
private TreeNodeActionType MyPredicate(ITreeNode treeNode) {
if (treeNode is MyNodeType) {
return TreeNodeActionType.ACCEPT;
}
return TreeNodeActionType.CONTINUE;
}
Sincerely,
Stefan Lieser



0
Comment actions Permalink

Hello Dmitry,

Ok, I will tell you a bit more what I'm doing, maybe you can give me
some concrete tips. I'm writing a parser for NHibernate mapping files.
These are XML of course, so I use your XmlLexerGenerated as the ILexer.

To do unit testing I pass strings to the parser and verify that GetText
equals the string. So far everything works (if I would have some
examples or a manual it would be a lot simpler of course... without
Reflector it would be impossible...).

Now I would like to verify that the parser builds a correct tree, so I'm
looking for a method which gives me a list of nodes of a specified type,
and thats where IFileNode.FindNextNode came into play.

Some more questions: if I copy my plugin to the plugins directory it is
loaded by R#. If I open a NHibernate mapping file (*.hbm.xml) the
vertical bar on the right of the editor window is displayed, the file is
analyzed, and then the vertical bar disappears. What conditions must be
met so that the vertical bar stays there?

The NHibernate mapping files contain references to C# properties in
strings. I would like to get a rename support: if I rename the C#
property, the string in the mapping file should be renamed too. What is
to be done to "glue" the C# and mapping file PSI-trees together?


Sincerely,
Stefan Lieser



Dmitry Shaporenkov (JetBrains) wrote:

Hello Stefan,

current node here means the node which you call FindNextNode on (i.e.,
'this'). I'm not sure that using this function is a good idea - why not
simply traverse the tree (using ITreeNode.FirstChild,
NextSibling) and check each node? Also, you can use IElement interfaces
and IRecursiveElementProcessor
for traversing tree as IElement hierarchy.


Regards,
Dmitry Shaporenkov
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"

>> Hi,
>>
>> I use IFileNode.FindNextNode to find nodes in a PSI tree that satisfy
>> a specific predicate. The tooltip for the method tells "Returns first
>> tree node satisfying the predicate and located after the current
>> node".
>>
>> My question: which node is "the current node"? How can I set it?
>>
>> For example I would like to do the following:
>>
>> while (node = fileNode.FindNextNode(new
>> TreeNodePredicate(MyPredicate))) {
>> // do something with node
>> }
>> private TreeNodeActionType MyPredicate(ITreeNode treeNode) {
>> if (treeNode is MyNodeType) {
>> return TreeNodeActionType.ACCEPT;
>> }
>> return TreeNodeActionType.CONTINUE;
>> }
>> Sincerely,
>> Stefan Lieser


0
Comment actions Permalink

Some more questions: if I copy my plugin to the plugins directory it is
loaded by R#. If I open a NHibernate mapping file (*.hbm.xml) the vertical
bar on the right of the editor window is displayed, the file is analyzed,
and then the vertical bar disappears. What conditions must be met so that
the vertical bar stays there?


The vertical error stripe is initially visible because the PSI tree exists
for given file

But then it disapperas because none of the error highlighting stages
rocognizes this file as the processing object.
To make the error stripe visible for your file you have to create your own
error highlighting stage.

Do not hesitate to ask details how to create it

--
Eugene Pasynkov
Developer
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


0
Comment actions Permalink

Hello Eugene,

Eugene Pasynkov (JetBrains) wrote:
>> What conditions must be met so that
>> the vertical bar stays there?


The vertical error stripe is initially visible because the PSI tree exists
for given file

But then it disapperas because none of the error highlighting stages
rocognizes this file as the processing object.
To make the error stripe visible for your file you have to create your own
error highlighting stage.

Do not hesitate to ask details how to create it


What do I have to do for a error highlighting stage? Can you point me to
an example?

But the bigger question is, how do I glue my psi tree to the C# psi so
that renaming a property is propagated to my plugin?


Sincerely,
Stefan Lieser

0
Comment actions Permalink


>> Do not hesitate to ask details how to create it

What do I have to do for a error highlighting stage? Can you point me to
an example?


As a good example, please refer to the NERPA plugin sources by Ilya
Ryzhenkov
You have to implement daemon stage and daemon stage process
To start with, refer to the class marked by attribute

But the bigger question is, how do I glue my psi tree to the C# psi so
that renaming a property is propagated to my plugin?


When the rename refacoring works, it find ALL references across the solution
to the element being renamed, and the bind that reference to the new
element.

In your case, you should do the following:

1) Implement the IReference interface and return the pointer to it in the
"IElement.GetReferences()" method. Usually, the PSI tree element itself
implements that interface.
2) In "IReference.Resolve()" method you should correctly resolve it to some
element. If you have the fully qualified name of the entity you are
resolving to, then the resolve method is rather trivial. But if the resolve
will involve building of symbol tables (as in C#), then the resolve process
becomes a tricky one.
3) In "IReference.BindTo()" method you have to modifu your file so that the
reference will resolve to the new given element

--
Eugene Pasynkov
Developer
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


0

Please sign in to leave a comment.