IDEA插件开发

目录

readme

API

获取插件version

获取IDEA版本

常用功能

读取Json文件关键字

获取用户的本地某个路径

kt协程

回调函数

通知板块(重启)

从本地安装插件

反射函数


readme

本篇IDEA插件开发中使用的是kotlin语言

API

获取插件version

import com.intellij.openapi.extensions.PluginId
import com.intellij.ide.plugins.PluginManagerCore
val pluginId = PluginId.getId("idString")
val pluginVersion = PluginManagerCore.getPlugin(pluginId)?.version.toString()

获取IDEA版本

if (ApplicationInfo.getInstance().build.baselineVersion <= 211) { }

常用功能

读取Json文件关键字

fun getVersionAndUrlFromJson(url: String): Pair<String, String> {
    val connection = URL(url).openConnection() as HttpURLConnection
    connection.requestMethod = "GET"
    connection.connectTimeout = 10000//设置读取超时
    connection.readTimeout = 10000
    val jsonString = connection.inputStream.bufferedReader().use { it.readText() }
    val json = Json { ignoreUnknownKeys = true }
    val jsonElement = json.parseToJsonElement(jsonString).jsonObject
    val jetbrains = jsonElement["jetbrains"]?.jsonObject
    //读取二级关键字
    val version = jetbrains?.get("jetbrains_version")?.jsonPrimitive?.content ?: ""
    val pluginUrl = jetbrains?.get("jetbrains_url")?.jsonPrimitive?.content ?: ""
    return Pair(version, pluginUrl)
}

获取用户的本地某个路径

val userHome = System.getProperty("user.home")//用户目录
var pluginZipPath = Paths.get(userHome, "fittencode.zip").toString()//拼接

kt协程

runBlocking {
    //会阻塞主线程
}

GlobalScope.launch {
    //使用的是DefaultDispatcher,会自动切换到后台线程
    //子线程中此处不可以做UI操作,不绑定生命周期
}

GlobalScope.launch(Dispatchers.Main) {
    //使协程依托于主线程中,此时可以更新UI等操作
}

GlobalScope.launch(Dispatchers.IO) {
    //效果与CoroutineScope一样
}

CoroutineScope(Dispatchers.IO).launch {
    //比较推荐
}

回调函数

import java.util.function.Consumer
val callback: Consumer<PluginInstallCallbackData> = Consumer {
    //执行后之后的回调操作
}

通知板块(重启)

fun notify(project: Project) {  
    val title = "title"
    val notificationType = NotificationType.INFORMATION // 通知类型,可以选择不同的类型
    val content = "通知内容。点击 <a href='doSomething'>这里</a> 来执行操作。"
    val listener = object : NotificationListener {
        override fun hyperlinkUpdate(notification: Notification, event: HyperlinkEvent) {
            if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
                if (event.eventType == HyperlinkEvent.EventType.ACTIVATED && event.description == "name") {
                    val application = ApplicationManager.getApplication() as ApplicationImpl
                    application.invokeLater {
                        application.restart(6, ArrayUtil.EMPTY_STRING_ARRAY)
                    }
                }
            }
        }
    }

    val notification = Notification("plugin_id", title, content, notificationType, listener)
    Notifications.Bus.notify(notification, project)
}

从本地安装插件

//版本在211之前
fun installFromDiskOldVersion(project: Project, file: Path, callback:                         Consumer<PluginInstallCallbackData>) : Boolean{
    val installFromDiskMethod = ReflectUtil.getMethod(
        PluginInstaller::class.java,
        "installFromDisk",
        *arrayOf(InstalledPluginsTableModel::class.java, Path::class.java,  Consumer::class.java, Component::class.java))
    if (installFromDiskMethod == null) {
        println("Method not found: installFromDisk")
        return false
    } else {
        installFromDiskMethod.isAccessible = true
        val tableModel = InstalledPluginsTableModel(project)
        val ret = installFromDiskMethod.invoke(null as Any?, tableModel, file, callback, null)
        return true
        }
}
//211之后
fun installFromDiskNewVersion(project: Project, file: File, callback: Consumer<PluginInstallCallbackData>) : Boolean{
    try {
        val pluginEnablerClass = ReflectUtil.classForName("com.intellij.ide.plugins.PluginEnabler") as Class<*>
        val pluginEnabler = ReflectUtil.getStaticField<Any>(pluginEnablerClass, "HEADLESS")
        val tableModel = InstalledPluginsTableModel(project)
        var installFromDiskMethod = ReflectUtil.getMethod(
            PluginInstaller::class.java, "installFromDisk", *arrayOf(
            InstalledPluginsTableModel::class.java, pluginEnablerClass, File::class.java, JComponent::class.java, Consumer::class.java))
        if (installFromDiskMethod != null) {
            installFromDiskMethod.isAccessible = true
            val ret = installFromDiskMethod.invoke(null, tableModel, pluginEnabler, file, null, callback)
            println("ret: $ret")
            return true
        }

        installFromDiskMethod = ReflectUtil.getMethod(
            PluginInstaller::class.java, "installFromDisk", *arrayOf(
            InstalledPluginsTableModel::class.java, pluginEnablerClass, File::class.java, Project::class.java, JComponent::class.java, Consumer::class.java))
        if (installFromDiskMethod != null) {
            installFromDiskMethod.isAccessible = true
            val ret = installFromDiskMethod.invoke(null, tableModel, pluginEnabler, file, project, null, callback)
            return true
        }
    } catch (e: Exception) {
        println("2.Error.cause: ${e.cause?.message}")
    }
    println("Method not found: installFromDisk")
    return false
}

反射函数

object ReflectUtil {
    private val classMap = ConcurrentHashMap<String, Class<*>>()
    
    fun getMethod(clazz: Class<*>, methodName: String?, vararg parameterTypes: Class<*>?): Method? {
        var targetClass: Class<*>? = clazz

        do {
            var method: Method? = null

            try {
                method = clazz.getDeclaredMethod(methodName, *parameterTypes)
            } catch (var6: NoSuchMethodException) {
            }

            if (method != null) {
                return method
            }

            targetClass = targetClass!!.superclass
        } while (targetClass != null && targetClass != Any::class.java)

        return null
    }

    @Throws(ClassNotFoundException::class)
    fun classForName(className: String): Class<*>? {
        var target = classMap[className]
        if (target == null) {
            target = Class.forName(className)
            classMap[className] = target
        }
        return target
    }

    @Throws(NoSuchFieldException::class, IllegalAccessException::class)
    fun <T> getStaticField(targetClass: Class<*>, fieldName: String): T {
        val field: Field = targetClass.getDeclaredField(fieldName)
        field.isAccessible = true
        return field.get(null) as T
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值