如何在用Kotlin编写的Intellij IDEA Gradle插件项目中包括Kotlin PSI类(例如KtClass)? [英] How to include Kotlin PSI classes (e.g. KtClass) in Intellij IDEA Gradle plugin project written in Kotlin?

查看:581
本文介绍了如何在用Kotlin编写的Intellij IDEA Gradle插件项目中包括Kotlin PSI类(例如KtClass)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个插件,以将模拟数据添加到Kotlin项目中.第一部分涉及在当前项目中查找从特定基类继承的所有Kotlin类.我希望能够解析这些类以读取注释的值并获取构造函数的结构.然后,该信息将用于将代码添加到项目中,从而将选定类的实例添加到模拟数据库实例中.

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.

我一直在使用PsiViewer插件检查Kotlin类文件中的PSI树.为了访问KtFile,KtClass等,我在我的build-gradle文件中为"org.jetbrains.kotlin:kotlin-compiler-embeddable"添加了一个依赖项.在我尝试运行插件之前,这似乎还可以.当我使用例如psiFile is KtFile.我仍然可以通过对text字段的简单解析来掌握正确的PsiFile实例,但是当我尝试强制转换PsiFile实例时,出现以下异常:

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)

我目前正在使用IntelliJ IDEA 2019.2.3.尝试使用不同版本的kotlin插件(1.3.31和1.3.41).在Windows 10上运行.

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)
    }
}

我认为我没有正确设置gradle.我已经在广泛地寻找合适的设置,但是找不到可行的解决方案.谁能指导我进行正确的Gradle设置?

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?

推荐答案

您是否通过向IntelliJ任务添加插件来进行检查

Did you check by adding plugins to IntelliJ task

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

请检查并更新

这篇关于如何在用Kotlin编写的Intellij IDEA Gradle插件项目中包括Kotlin PSI类(例如KtClass)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆