Resolving Types in CodeInsightFixture

Answered

We want to write unit tests for a PsiVisitor which is manipulating Java code.
We extended the LightCodeInsightFixtureTestCase and added a file into myFixture using:

PsiFile psiFile = myFixture.configureByText(fileName, clazz);

the PsiFile gets created and has no errors, at least when we check it with PsiErrorElementUtil.hasErrors. The problem is that in the visitor we often try to check the variable types and whether a variable is a subtype of a class. Indeed, we can get the PsiType of a PsiExpression. But, when we try to get the PsiClass of a PsiType with: PsiTypesUtil.getPsiClass(psiType) it always returns null, because ((PsiClassType)psiType).resolve() returns null. This is happening for types of java.lang package, too.

When we run the plugin, the PsiClass can be retrieved successfully from the PsiType. But, this is not the case when we visit the PsiFile which is added to myFixture.

Setup details:

  • We are not overriding any methods from LightCodeInsightFixtureTestCase.
  • The class we are adding to myFixture has no dependencies to external libraries. It is only using classes in java.lang and java.util packages.
  • We tried to copy a file from testData folder to myFixture with myFixture.configureByFile but the behavior is the same.

Questions:

  • Could this problem be related to the runConfiguration of the unitTest? we are using the VM Options as described in the Test Prerequisits.
    -ea -Xbootclasspath/p:../out/classes/production/boot -XX:+HeapDumpOnOutOfMemoryError -Xmx512m -XX:MaxPermSize=320m
    -Didea.system.path=../test-system -Didea.home.path=../ -Didea.config.path=../test-config -Didea.test.group=ALL_EXCLUDE_DEFINED
  • The documentation recommends to extend LightCodeInsightFixtureTestCase for tests which require Java Psi functionalities. Do we need to provide a custom ProjectDescriptor?


Please, advice!

Thanks

0
5 comments

Thank you for your help. We managed to solve the problem by using a custom ProjectDescriptor as following:

class CustomProjectDescriptor extends DefaultLightProjectDescriptor {

    @Override
    public Sdk getSdk() {
        JavaSdk javaSdk = JavaSdk.getInstance();
        return javaSdk.createJdk("JavaSDK", System.getProperty("java.home");
    }

}
0

Using local "java.home" which could be any version might not work on all machines. I'd recommend to use a known (mock) JDK that is clearly defined.

0

Do you mean to use a mock JDK from IdeaTestUtil? We did try to use that (e.g. IdeaTestUtil.getMockJdk18()) but this does not work when it comes to type resolution.
Would we be able to find the expression types, (e.g. using PsiTypesUtil.getPsiClass(psiType)) if the ProjectDescriptor was using a mock JDK?

Are we missing something?

0

If you set the parameters for running tests as described in above link, it should work - for "most" classes in JDK. Since it's mocked JDK, it doesn't contain all classes.

0

Please sign in to leave a comment.