使用Kotlin來開發IntelliJ plugin — Part 1

Freddie Wang
8 min readSep 4, 2018

--

前言

一直都很愛使用 IntelliJ IDEA 系列的 IDE,也裝了不少別人開發的 plugin 。最近為了研究 Kotlin 的一些功能,需要看看 Bytecode 反編譯成 Java 會變成什麼樣子。但 Kotlin 原生的工具似乎有些 bug,造成反編譯出來的Java檔大到無法正常開啟,所以只能使用其他的 decompiler,使用上也就不是那麼方便。於是就有了 ”不然自己寫一個 IntelliJ plugin 吧,反正也沒做過 ” 這樣的念頭。後來 google 了一下,發現相關的資料不是很豐富,中文的更少,而且還沒看到繁體中文的 (基本上都簡中),所以就有了這篇文章。

開發語言

以前 IntelliJ plugin 需要使用 Java 來開發,現在新版本的IDEA已經包含了 Kotlin 相關的 library,所以現在使用 Kotlin 來開發也沒有問題,而且更方便,本文全部就是以 Kotlin為範例。

第一步

首先當然就是要先建立一個開發專案。有兩種方式,第一種是建立一個 Intellij Platform Plugin 的專案,第二種是用 gradle。我個人是偏好使用 gradle,因為可以直接在 command line 就可以 build 了,有時候只是改一點小東西,直接在 command line 操作會方便一些。

至於如何使用 gradle,這方便的資料很多所以就直接略過。要開發 plugin的話,基本如以下的 build.gradle

buildscript {
repositories {
mavenCentral()
}
}

plugins {
id("org.jetbrains.intellij") version "0.3.7"
id("org.jetbrains.kotlin.jvm") version "1.2.51"
}

apply plugin: "org.jetbrains.intellij"
apply plugin: "kotlin"

intellij {
version "2018.1.6"
pluginName "YOUR_PLUGIN_NAME"
updateSinceUntilBuild false // This line is important
}

group "GROUP_NAME"
version "VERSION"

repositories {
mavenCentral()
}

build.gradle 的重點有兩個。

  • 使用 org.jetbrains.intellij plugin,詳細的設定和版本號碼可以參考 https://github.com/JetBrains/gradle-intellij-plugin
  • 加上 updateSinceUntilBuild = false,不然 plugin 支援的版本會跟設定裡面的不一樣,有可能無法安裝到 Release版的 IDEA (或是 Android Studio)

之後就可以使用 ./gradlew runIde 來啟動一個 有 debug 功能的Community版的Intellij了 (一開始會花一些時間下載 Community版的 Intellij)

plugin.xml

接下來就需要增加一個 plugin.xml了。plugin.xml是 IntelliJ plugin的基本設定檔案,裡面有關於 plugin的一些設定包含了名稱 、版本和支援版本之類的設定,如下所示

<idea-plugin>
<id>PLUGIN ID</id>
<name>PLUGIN NAME</name>
<version>1.0</version>
<vendor email="YOUR_EMAIL" url="YOUR_URL">YOUR NAME</vendor>

<description><![CDATA[
Enter short description for your plugin here.<br>
<em>most HTML tags may be used</em>
]]></description>

<change-notes><![CDATA[
Add change notes here.<br>
<em>most HTML tags may be used</em>
]]>
</change-notes>

<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
<idea-version since-build="162.0"/>

<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
on how to target different products -->
<!-- uncomment to enable plugin in all products
<depends>com.intellij.modules.lang</depends>
-->

<extensions defaultExtensionNs="com.intellij">
<applicationConfigurable instance="YOUR_CONFIGURABLE_CLASS"/>
</extensions>

<actions>
<action class="YOUR_CLASS" id="YOUR_ACTION_ID" text="Decompile class" description="THE_DESCRIPTION">
<add-to-group group-id="CodeMenu" relative-to-action="ConvertJavaFileToKotlin" anchor="after"/>
</action>
</actions>

</idea-plugin>

只需要把 plugin.xml 放到 resources/META-INF 底下就可以了。

Action

再來就需要實作 plugin 的 ”運作” 了。Action是 Intellij IDE 執行 plugin 的一個方式,需要在 plugin.xml 裡面宣告。Action 可以加在 menu或是 toolbar等,這樣使用者就可以使用 plugin 的功能了。宣告方式如下

<actions>
<action class="YOUR_CLASS" id="YOUR_ACTION_ID" text="Decompile class" description="THE_DESCRIPTION">
<add-to-group group-id="CodeMenu" relative-to-action="ConvertJavaFileToKotlin" anchor="after"/>
</action>
</actions>

<action>中加入 class name, id等等的資訊,在<add-to-group> 加入此 item 所在的位置,上面的範例則是把 action 加到 “Convert Java File To Kotlin,結果如下圖

the position of the menu item

接著就要處理使用者按下這個選項的動作了。只要繼承 AnAction 並且override 兩個 method 就可以了。

class SimpleAction : AnAction() {
override fun update(actionEvent: AnActionEvent) {
super.update(actionEvent)
actionEvent.presentation.isVisible = True //show the action item
}
override fun actionPerformed(actionEvent: AnActionEvent) {
//Do some action here
}
}

Configurable

在開發 plugin 的過程中,大概都會需要存取一些設定,而增加設定的方法就是透過 Configurable 這個 Interface。最基本的方式就是在 plugin.xml 加上這段

<extensions defaultExtensionNs="com.intellij">
<applicationConfigurable instance="YOUR_CONFIGURABLE_CLASS"/>
</extensions>

接著建立一個Class 實作 Configurable。

class SimpleConfigurable : Configurable {
override fun createComponent(): JComponent? {
return JComponent()
}
}

之後就可以在 Settings 裡面看到新的設定了。

Configurable

完成了 Action 跟 Configuration 之後,plugin 的基本樣子就已經有了,接著就是要實作功能了。在 part2 我會介紹如何整合外部工具到 plugin 裡面。有任何問題,不用客氣歡迎發問。

--

--

Freddie Wang

I’m a software engineer from Taiwan and living in Japan now.