Cannot use com.intellij.psi.jsp.el.ELLiteralExpression in ReferenceContributor

Hi everyone,

I'm trying to provide references for literal strings placed in JSF EL-Statements like: <div>#{myBean.doSomething('LITERALEXPRESSION')}</div>. Using the PSI View I figured out that I'd need to provide a reference provider like:


       registrar.registerReferenceProvider(PlatformPatterns.psiElement(com.intellij.psi.jsp.el.ELLiteralExpression),
                new PsiReferenceProvider() {
                    @NotNull
                    @Override
                    public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
                        //Do somethign smarter here....
                        return new PsiReference[0];
                    }
                });


However, the class can be found (autocompleted) but as soon as it is in the code, the el package is marked red:

el.ELLiteralExpression


I'm using IntelliJ Ultimate - is there anything I need to add to the SDK classpath or do I need to add an dependency to the plugin.xml?

regards Andy

11 comments

Hello Andreas,

exactly, you'll need to add $IDEA_HOM$/plugins/jsp/lib/jsp-impl.jar to your IntelliJ SDK. The Plugin ID for <dependency> is com.intellij.jsp

0

Thanks Yann,

now it compiles but does not work :-(

The registration is called, but the inner class is never invoked:

public class JSPXPropertyReferenceProvider extends PsiReferenceContributor {

    @Override
    public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
        registrar.registerReferenceProvider(PlatformPatterns.psiElement(ELLiteralExpression.class),
                new PsiReferenceProvider() {
                    @NotNull
                    @Override
                    public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
                        return new PsiReference[0];
                    }
                });

    }
}


Plugin.xml:
  <depends>com.intellij.java-i18n</depends>
  <depends>com.intellij.jsp</depends>

    <extensions defaultExtensionNs="com.intellij">
        <properties.implicitPropertyUsageProvider implementation="com.scireum.intellij.extendedproperties.QualifiedNameUsageProvider"/>
        <psi.referenceContributor implementation="com.scireum.intellij.extendedproperties.XMLPropertyReferenceProvider" />
        <psi.referenceContributor implementation="com.scireum.intellij.extendedproperties.JSPXPropertyReferenceProvider" />
    </extensions>

I also tries adding language="jsp" but that didn't help either. A breakpoint on the line "return new PsIReference[0]" is never hit :-(

Thanks in advance for your excellent support.

regards Andy

0

Oops, actually there's a much easier way to solve this - simply extend com.intellij.psi.jsp.el.ElLiteralCustomReferenceProvider (you can filter out non-relevant places in #accept()).

0

Thanks Yann,

I implemented it the following way:
@NotNull
    @Override
    public PsiReference[] createReferences(@NotNull ELLiteralExpression element) {
        String val = element.getText().substring(1, element.getText().length() - 1);
        List<PsiReference> result = new ArrayList<PsiReference>();
        for (IProperty prop : PropertiesUtil.findPropertiesByKey(element.getProject(), val)) {
            result.add(new PropertyReference(prop.getKey(), element, prop.getPropertiesFile().getResourceBundle().getBaseName(), true));
        }
        return result.toArray(new PsiReference[result.size()]);
    }

This works perfect when scanning XML files. However, in this case, I can click on the literal and it jumps to the properties file. However, the property itself is marked as unused and "Find Usages" on it doesn't list the JSPX occurence. Is there anything more I need to add?

thanks,
Andy

0

My guess is the TextRange of the PropertyReference you're creating doesn't match the actual TextRange of the actual text (=key value) in ELLiteralExpression.

Try passing TextRange.from(1, val.length())

0

Dear Yann,

doesn't seem to help. When I click on the link the complete text (withouth the ') are underlined, so the value should match...

0

Try returning only one reference (break after first match) to see if it works then. If not, could you share your whole plugin's sources?

0

Dear Yann,

please find attached the zip of the whole plugin-project. Thanks a again for your help...

My Test-Project contains 2 Files:

/tes.jspx:

<div>#{myBea1n.doSomething('test.hello.word17', 'Hallo')}</div>


/src/test.properties:

test.hello.word=Test
test.hello.word17=Test


I've attached those too - and let's not care about all those typos in them ;-)

regards
Andy



Attachment(s):
test.properties.zip
tes.jspx.zip
intellij-extended-properties.zip
0

For me "Find Usages" and usage highlighting in .properties file works properly with a very simple blank Web application test project.
Could you check if it works when you reference it from a simple literal expression like

  <div>#{'test.hello.word17'}</div>

0

I attached a newly created project...

I can jump (cmd+click) from the jspx to the properties file. However "test" is marked as unused and Find Usages on it is empty.

Thanks again for your patience.



Attachment(s):
untitled.zip
0

So far I could nail down the problem to JSP vs JSPX (it works in JSP, but not in JSPX), I'll update when I found out more..

A few remarks on your existing code:

Please disable (testing code?)  XMLPropertyReferenceProvider, it might interfere with the actual references you want to insert.

com.scireum.intellij.extendedproperties.JSPXPropertyReferenceProvider#accept  should not try to resolve text against existing property keys, but only  return whether this place is an acceptable place where you want to  insert your custom references (e.g. by checking if the literal  expression is used as a parameter of a certain method, ...).

0

Please sign in to leave a comment.