Как включить классы Kotlin PSI (например, KtClass) в проект подключаемого модуля Intellij IDEA Gradle, написанный на Kotlin? - PullRequest
1 голос
/ 11 ноября 2019

Я пытаюсь написать плагин для добавления фиктивных данных в проект Kotlin. Первая часть включает в себя поиск всех классов Kotlin в текущем проекте, которые наследуются от определенного базового класса. Я хочу иметь возможность анализировать эти классы, чтобы прочитать значение аннотации и получить структуру конструктора. Затем эта информация будет использоваться для добавления кода в проект и добавления экземпляров выбранных классов в экземпляр фиктивной базы данных.

Я использовал плагин PsiViewer для проверки дерева PSI в файлах классов Kotlin. Чтобы получить доступ к KtFile, KtClass и т. Д., Я добавил в файл build-gradle зависимость от «org.jetbrains.kotlin: kotlin-compiler-embeddable». Кажется, это нормально, пока я не попытаюсь запустить плагин. Я никогда не получаю совпадение при использовании, например, psiFile is KtFile. Мне все еще удается получить правильные PsiFile экземпляры простым анализом поля text, но когда я пытаюсь привести экземпляр PsiFile, я получаю следующее исключение:

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Я использую IntelliJ IDEA 2019.2.3 на данный момент. Пробовал использовать разные версии плагинов kotlin (1.3.31 и 1.3.41). Работает в 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?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...