Plugin development: getClasses for JetFile


#1

Hi everyone!

I want to add Kotlin support to one my favorite plugins. In the plugin code I see that PsiClass instance is resolved by ((PsiClassOwner) psiFile).getClasses() method call.
Kotlin file is represented by org.jetbrains.kotlin.psi.JetFile instance that always returns empty array as a result of getClasses method call.

Is there any way to get Java classes from JetFile?

ps. Actually what I need is to check if any class from the Kotlin file extends one of the the Java classes from some predefined set.


#2

You can use org.jetbrains.kotlin.asJava.LightClassUtil.INSTANCE.getPsiClass(jetClass) to obtain a PsiClass corresponding to a JetClass.

Please note that we do not provide stable plugin API as of now (your code may break in future versions). In fact we have a plan to rename all our PSI classes very soon.

Also note that JetObjectDeclaration generates a java class as well. So what you should probably do is traverse JetFile.getDeclarations() and filter those that are JetClassOrObject.


#3

Pavel, thank you. The way you suggested it works with reflection. For some reason it does not work using direct field access:

LightClassUtil.INSTANCE$ triggers NullPointerException
LightClassUtil.class.getField(‚ÄúINSTANCE$‚ÄĚ).get(LightClassUtil.class) works fine.

The classloader for LightClassUtil.class is PluginClassLoader[org.jetbrains.kotlin, 0.14.449.Idea142.11]

BTW, do you have any plans adding Kotlin Psi classes to the ‚Äúproperties‚ÄĚ plugin?


#4

What do you mean by your last question? Since the Kotlin plugin is not part of the IntelliJ IDEA codebase, the properties plugin cannot have any dependencies on the Kotlin PSI.


#5

Kotlin is designed to be  very "compatible" with Java, so some plugins (may be many of them) can work both for Kotlin and Java with almost no additional code. But to enable this support there must be some simple layer to access to Java representation for Kotlin structures.

For example: in my case this plugin is ‚Äėwicketforge‚Äô that automatically generates HTML templates for Java classes using superclass as a semantic marker. What more important it enables fast navigation between these HTML files and Java classes and this operation is used very often during development (similar to switch between C++ header and source files). To make this plugin to work with Kotlin too all I need is to get superclass for my Kotlin object.

But when I install ‚Äėwicketforge‚Äô plugin it depends on ‚Äėproperties‚Äô plugin only. I believe a lot of¬†¬†plugin owners will be reluctant to add new dependencies for small patches.

So if there is a chance to move some minimal Kotlin PSI support to the general purpose ‚Äėproperties‚Äô plugin it will make very simple to persuade plugin developers to accept patches for Kotlin.


#6

Kotlin classes, methods and properties are already exposed as Java PSI (PsiClass, PsiMethod and PsiField), and can be discovered through Java APIs such as JavaPsiFacade.findClass(). You can also use methods such as PsiClass.getExtendsListTypes() to get the list of superclasses for a Kotlin class.

It may be possible to provide some additional entry points allowing to discover Kotlin classes through the existing API (for example, Kotlin files do not currently implement PsiClassOwner.getClasses()). However, all of this support needs to be provided by the Kotlin plugin, and if any additional platform APIs are needed, they would be provided by the platform. The properties plugin has absolutely nothing to do with it.


#7

Ok. Sorry for the misunderstanding with properties plugin. Trying to make a fast fix and continue my target development I found that some of Psi classes being used are defined in 'properties' and expected (blindly) that other Psi classes comes from the same source.

I will try to use the methods you suggested to find Java classes in Kotlin file. Thank you!