Search code examples
javaunit-testingintellij-ideajunitintellij-plugin

Custom reference contributor is not being called while running tests for Intellij Platform plugin


I'm developing a plugin for Intellij Platform (actually for PhpStorm).

My plugin is providing references within string literal expressions in PHP language. I created a reference contributor and a few reference provider classes. My plugin works perfectly when I run it within PhpStorm.

My plugin becomes bigger, so I decided to write a few tests for it. I created an unit test using IntelliJ IDEA "Create test" action and choosed JUnit 3. When I run test (see code below), the class MyPsiReferenceContributor is not being accessed at all, and test expectedly fails ("Test failed"). parent.getReferences() returns an empty array (parent is an instance of StringLiteralExpressionImpl).

Is seems that MyPsiReferenceContributor is not being registered in test environment.

What should I do to make my reference contributor available within tests?

I used this project https://github.com/Haehnchen/idea-php-symfony2-plugin as example, but my plugin is not using Gradle as theirs does.

This is how I registered my reference contributor in plugin.xml:

<extensions defaultExtensionNs="com.intellij">
    <psi.referenceContributor implementation="com.zenden2k.MyFrameworkIntegration.MyPsiReferenceContributor"/>
</extensions>

This is my reference contributor:

public class MyPsiReferenceContributor extends PsiReferenceContributor {
    // This is not being called while running tests! :(
    @Override
    public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
        MyPsiReferenceProvider provider = new MyPsiReferenceProvider();
        registrar.registerReferenceProvider(StandardPatterns.instanceOf(StringLiteralExpression.class), provider);
    }
}

This is my test case:

package com.zenden2k.MyFrameworkIntegration.tests;

import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.testFramework.fixtures.BasePlatformTestCase;

public class MyPsiReferenceContributorTest extends BasePlatformTestCase {
    public void setUp() throws Exception {
        super.setUp();

        myFixture.copyFileToProject("GetStaticDatasourceFixture.php");
        myFixture.copyFileToProject("user.xml");
    }

    protected String getTestDataPath() {
        return "src/test/com/zenden2k/MyFrameworkIntegration/tests/fixtures";
    }


    public void testThatStaticDatasourceReferenceIsProvided() {
        final ElementPattern<?> pattern = PlatformPatterns.psiElement().withName("test");
        myFixture.configureByText("user.php",
                        "<?php \n" +
                        "class MyClass extends CXMLObject {\n" +
                        "  public function test() {\n" +
                        "     $this->getStaticDatasource('t<caret>est');\n" +
                        "  }\n" +
                        "}\n"
        );

        PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
        if (psiElement == null) {
            fail("Fail to find element in caret");
        }

        PsiElement parent = psiElement.getParent();
        final PsiReference[] ref = parent.getReferences();
        for (PsiReference reference : ref) {
            PsiElement element = reference.resolve();
            if (pattern.accepts(element)) {
                return;
            }
        }
        fail("Test failed");
    }
}

Solution

  • First of all - using Gradle is a recommended way for the development of the plugin. You may check the Building Plugins with Gradle docs section for more details.

    There is a Simple Language Sample project available in the IntelliJ Platform SDK Code Samples repository that covers testing of the PSI References.