Language API observations/questions

Hi,

after playing a bit more with the language API, I made the following observations that
may be worth to look at and also may be interesting for plugin developers to know about:

- Find Usages: After doing a find usages on an element, the next time it is invoked
on the same file(-type?), it will revert to a "Find Usages in File". This is probably
correct because neither the JS plugin nor my own toy language have references outside
the file, but this behavior doesn't seem right.

Also, the result view has options to toggle the listing of read/write access. There is
however no (obvious) way for a custom language to specify that. I think the FindUsages
provider should be able to provide custom filter/grouping actions for such language-
dependent purposes.

- Highlight Usages in File: This doesn't work at all. Shouldn't this use the same
mechanism as Find Usages does?

- Before build #3273 it was possible to use
AnnotationHolder.createInfoAnnotation(element, null).setTextAttributes(...)

to create special text styles/colors for certain elements. This still works, but now the
annotation shows up with a yellow mark in the right gutter with the tooltip "null".
How is this supposed to be done now without creating any gutter-mark?

- What exactly can be put into the Object[] that is returned by PsiReference.getVariants()?
PsiElements, Strings (with html formatting maybe?), ... ?
This is one of the places where 2 lines of JavaDoc would help immensely ;)

- I found this code e.g. in the JS-Function implementation:

public int getTextOffset() {
final ASTNode name = findNameIdentifier();
return name != null ? name.getStartOffset() : super.getTextOffset();
}

This will make the caret to jump to the function name on e.g. find usages or ctrl-b.
There is however also a method called getNavigationElement() that seems to be there for
exactly this purpose. But overriding this will cause ctrl-b to fail, while Find Usages
still works as expected. What's the deal with this method and why is the getTextOffset()
'hack' used here?

- What exactly is Language.mayHaveReferences() responsible for? Looking at the JS plugin
(and how the method works), shouldn't this be called "isReference"? It seems to be the
same as asking the according PsiElement if it is an instance of PsiReference, just on token
level.

Not sure if those things are any issues at all, but maybe it can help a little to improve the API.

Cheers,
Sascha

4 comments
Comment actions Permalink

- Find Usages: After doing a find usages on an element, the next time
it is invoked on the same file(-type?), it will revert to a "Find
Usages in File". This is probably correct because neither the JS
plugin nor my own toy language have references outside the file, but
this behavior doesn't seem right.

We'll dig into, thanks.

Also, the result view has options to toggle the listing of read/write
access. There is however no (obvious) way for a custom language to
specify that. I think the FindUsages provider should be able to
provide custom filter/grouping actions for such language- dependent
purposes.

Nice shot. A JIRA request please?

- Highlight Usages in File: This doesn't work at all. Shouldn't this
use the same mechanism as Find Usages does?

Sure. It's just not implemented yet.

- Before build #3273 it was possible to use
AnnotationHolder.createInfoAnnotation(element,
null).setTextAttributes(...)
to create special text styles/colors for certain elements. This still
works, but now the
annotation shows up with a yellow mark in the right gutter with the
tooltip "null".
How is this supposed to be done now without creating any gutter-mark?

Bug...

- What exactly can be put into the Object[] that is returned by
PsiReference.getVariants()?
PsiElements, Strings (with html formatting maybe?), ... ?
This is one of the places where 2 lines of JavaDoc would help
immensely ;)
- I found this code e.g. in the JS-Function implementation:

That could be both strings and PsiElements. In latter case lookup items will
have nice icons if defined for that PSI element.

public int getTextOffset() {
final ASTNode name = findNameIdentifier();
return name != null ? name.getStartOffset() :
super.getTextOffset();
}
This will make the caret to jump to the function name on e.g. find
usages or ctrl-b. There is however also a method called
getNavigationElement() that seems to be there for exactly this
purpose. But overriding this will cause ctrl-b to fail, while Find
Usages still works as expected. What's the deal with this method and
why is the getTextOffset() 'hack' used here?

NavigationElement just servse slightly different purpose. One used (in java)
to open source file attached to a library when invoked against compiled version
of the class.
Generally, getTextOffset() may return offset that is located inside some
element which wouldn't be possible if we require whole element to be returned.

- What exactly is Language.mayHaveReferences() responsible for?
Looking at the JS plugin
(and how the method works), shouldn't this be called "isReference"? It
seems to be the
same as asking the according PsiElement if it is an instance of
PsiReference, just on token level.

As the matter of fact PsiReference is not a PsiElement but rather array of
references might be returned by arbitrary PSI element. For instance, XML
attribute value element may return references to java class if there's something
in it's value that looks like qualified class name. Language.mayHaveReferences()
method serves like quite hacky possible performance problems workaround.
It is only used when searching for usages. We do process enormous number
of references at that time so this one quite helps to skip elements that
cannot ever contain references.

Not sure if those things are any issues at all, but maybe it can help
a little to improve the API.

Sure. Feedbacks like this are highly appreciated.


0
Comment actions Permalink

Maxim Shafirov wrote:
>> I think the FindUsages provider should be able to
>> provide custom filter/grouping actions for such language- dependent
>> purposes.


Nice shot. A JIRA request please?


Sure: http://www.jetbrains.net/jira/browse/IDEA-1216

Not important for me at all, but maybe useful for "serious" language
integrations :)

>> - Highlight Usages in File: This doesn't work at all. Shouldn't this
>> use the same mechanism as Find Usages does?


Sure. It's just not implemented yet.


I thought it should work automagically. Not a problem at all.

>> - What exactly can be put into the Object[] that is returned by
>> PsiReference.getVariants()?


That could be both strings and PsiElements. In latter case lookup items
will have nice icons if defined for that PSI element.


Well, the reason I'm asking is that for CSS there is the "choose color..."
completion that invokes an action, so I thought that there's maybe more than
just strings and PsiElements ;)

Generally, getTextOffset() may return offset that is located inside
some element which wouldn't be possible if we require whole element to
be returned.


Ah, ok. It just had a slightly 'hacky' smell :)

>> - What exactly is Language.mayHaveReferences() responsible for?


As the matter of fact PsiReference is not a PsiElement but rather array
of references might be returned by arbitrary PSI element. For instance,
XML attribute value element may return references to java class if
there's something in it's value that looks like qualified class name.
Language.mayHaveReferences() method serves like quite hacky possible
performance problems workaround. It is only used when searching for
usages. We do process enormous number of references at that time so this
one quite helps to skip elements that cannot ever contain references.


I'm still chewing on that one, but it's getting more clear now: PsiElement
and PsiReference are totally distinct and the connection is only done by
PsiElement.getReference[s](). In the JS plugin's case however, the reference
expression and the PsiReference are the same, thus JSReferenceExpressionImpl
returns 'this' in getReference(). Yes, considering that, mayHaveReferences()
makes sense.

Thanks for the comments,
Sascha

0
Comment actions Permalink

Well, the reason I'm asking is that for CSS there is the "choose
color..." completion that invokes an action, so I thought that there's
maybe more than just strings and PsiElements ;)


Yep, indeed there are some more. But those look quite hacky right now so
we do not open them.

-


Maxim Shafirov
http://www.jetbrains.com
"Develop with pleasure!"


0
Comment actions Permalink

- Before build #3273 it was possible to use AnnotationHolder.createInfoAnnotation(element,ull).setTextAttributes(...) to create special text styles/colors for certain elements.
This still works, but now the annotation shows up with a yellow mark in the right gutter with the tooltip "null".
How is this supposed to be done now without creating any gutter-mark?

Bug...


It still creates a gutter mark in #3281.
http://www.jetbrains.net/jira/browse/IDEA-1331

Vince.

0

Please sign in to leave a comment.