How to include Kotlin PSI classes (e.g. KtClass) in Intellij IDEA Gradle plugin project written in Kotlin?

杀马特。学长 韩版系。学妹 提交于 2020-08-09 04:43:56

问题


I am trying to write a plugin to add mock data to a Kotlin project. The first part involves finding all the Kotlin classes in the current project that inherits from a specific base class. I want to be able to parse these classes to read the value of an annotation and to get the structure of the constructor. This information will then be used to add code to the project adding instances of selected classes to a mock database instance.

I have been using the PsiViewer plugin to inspect the PSI tree in the Kotlin class files. To get access to KtFile, KtClass etc I added a dependency to "org.jetbrains.kotlin:kotlin-compiler-embeddable" in my build-gradle file. This seems to be OK until I try to run the plugin. I never get a match when using e.g. psiFile is KtFile. I still manage to get hold of the correct PsiFile instances by simple parsing of the text field, but when I try to cast a PsiFile instance I get the following exception:

java.lang.ClassCastException: class org.jetbrains.kotlin.psi.KtFile cannot be cast to class org.jetbrains.kotlin.psi.KtFile (org.jetbrains.kotlin.psi.KtFile is in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @2ed18f3d; org.jetbrains.kotlin.psi.KtFile is in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @4308c14c)

I am using IntelliJ IDEA 2019.2.3 at the moment. Tried to use different versions of the kotlin plugins (1.3.31 and 1.3.41). Running on Windows 10.

build.gradle

plugins {
    id 'java'
    id 'org.jetbrains.intellij' version '0.4.11'
    id 'org.jetbrains.kotlin.jvm' version '1.3.31'
}

group 'se.winassist'
version '1.0'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    implementation "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.31"
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

// See https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
    version '2019.2.3'
}
compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
patchPluginXml {
    changeNotes """
      Add change notes here.<br>
      <em>most HTML tags may be used</em>"""
}

CreateMockdataFromPostgreSQLClass.kt:

import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.ui.Messages
import org.jetbrains.kotlin.psi.KtFile

class CreateMockdataFromPostgreSQLClass: AnAction() {
    override fun actionPerformed(e: AnActionEvent) {
        val project = e.getRequiredData(CommonDataKeys.PROJECT)
        val kotlinFileHandler = KotlinFileHandler(project)
        val dbClasses = kotlinFileHandler.getAllKotlinDbClasses()
        val classNames = dbClasses.map {
            val ktFile = it as KtFile
            ktFile.name
        }.joinToString(separator = "\n")
        Messages.showInfoMessage(classNames, "Test")
    }
}

KotlinFileHandler.kt:

import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager

data class KotlinFileHandler(val aProject: Project) {

    fun getAllKotlinDbClasses(): List<PsiFile> {
        val roots = ProjectRootManager.getInstance(aProject).contentSourceRoots
        val dirs = roots.map { PsiManager.getInstance(aProject).findDirectory(it) }
        val result = mutableListOf<PsiFile>()
        getKotlinDbClassesInPsiDir(result, dirs)
        return result.toList()
    }

    private tailrec fun getKotlinDbClassesInPsiDir(aResult: MutableList<PsiFile>, aPsiDirectoryList: List<PsiDirectory?>) {
        if (aPsiDirectoryList.isEmpty()) return

        val subDirectories = mutableListOf<PsiDirectory>()
        aPsiDirectoryList.filter { it != null }.forEach {
            val children = it!!.children
            val files = children.filter {
                it is PsiFile && it.language.toString().toLowerCase() == "language: kotlin"
            }.map { it as PsiFile }
            subDirectories += children.filter { it is PsiDirectory }.map { it as PsiDirectory }
            aResult += files.filter {
                hasBasePersistenceSuperclass(it) && hasTableNameAnnotation(it)
            }.toList()
        }
        getKotlinDbClassesInPsiDir(aResult, subDirectories)
    }
}

I assume I set up gradle incorrectly. I have looked for a proper setup extensively, but failed to find a working solution. Can anyone guide me to the proper gradle setup?


回答1:


Did you check by adding plugins to IntelliJ task

intellij {
  version '2020.1'
  plugins = ['java','Kotlin']
  intellij.type = 'IC'
}

Please check and update



来源:https://stackoverflow.com/questions/58803103/how-to-include-kotlin-psi-classes-e-g-ktclass-in-intellij-idea-gradle-plugin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!