IDEA 插件开发入门教程
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
IntelliJ IDEA 是目前最好用的 JAVA 開(kāi)發(fā) IDE,它本身的功能已經(jīng)非常強(qiáng)大了,但是每個(gè)人的需求不一樣,有些需求 IDEA 本身無(wú)法滿足,于是我們就需要自己開(kāi)發(fā)插件來(lái)解決。工欲善其事,必先利其器,想要提高開(kāi)發(fā)效率,我們可以借助 IDEA 提供的插件功能來(lái)滿足我們的需求。如果沒(méi)有我需要的功能怎么辦?很簡(jiǎn)單,我們自己造一個(gè)!
插件能做什么?
IDEA 的插件幾乎可以做任何事情,因?yàn)樗?IDE 本身的能力都封裝好開(kāi)放出來(lái)了。主要的插件功能包含以下四種:
- 自定義語(yǔ)言支持:如果有 IDEA 暫時(shí)不支持的語(yǔ)言,你可以自己寫(xiě)一個(gè)插件來(lái)支持,例如 Go 語(yǔ)言原來(lái)的支持就是通過(guò)插件做的,后來(lái)單獨(dú)做了一個(gè) Goland。官方有自定義語(yǔ)言插件支持的教程。
- 框架支持:例如Struts 2?的框架支持
- 工具集成:可以給 IDEA 的自帶功能進(jìn)行增強(qiáng),例如對(duì) Git 的操作增加 CodeReview 的功能。參考Gerrit
- 用戶界面:自定義的插件改變用戶界面。參考BackgroundImage
我為了減少重復(fù)代碼的編寫(xiě),寫(xiě)了一個(gè)代碼生成的插件IDEA代碼生成插件CodeMaker,支持自定義代碼生成的模板。
Hello world 插件
依照慣例,我們從 Hello world 開(kāi)始。
新建一個(gè) Gradle 的插件工程
有些教程推薦用 IDEA 默認(rèn)的插件工程來(lái)開(kāi)始,但是我比較推薦用 Gradle 來(lái)管理整個(gè)插件工程,后面的依賴管理會(huì)很方便,否則都得靠手動(dòng)管理。
點(diǎn)擊新建工程,選擇 Gradle
接下來(lái)填寫(xiě)項(xiàng)目屬性
配置 Gradle,用默認(rèn)配置就行
新建完工程之后,IDEA 會(huì)自動(dòng)開(kāi)始解析項(xiàng)目依賴,因?yàn)樗螺d一個(gè)幾百兆的 SDK 依賴包,所以會(huì)比較久,打開(kāi)科學(xué)上網(wǎng)能快一點(diǎn)。
Gradle 依賴解析完成之后,項(xiàng)目結(jié)構(gòu)如下圖,其中 plugin.xml 是插件的配置,build.gradle 是項(xiàng)目依賴的配置(類比 pom.xml)。
下面就是默認(rèn)生成的 plugin.xml
<idea-plugin><!--插件id--><id>com.xiaokai.test.demo</id><!--插件名稱--><name>Demo</name><!--開(kāi)發(fā)者信息--><vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor><!--插件說(shuō)明--><description><![CDATA[Enter short description for your plugin here.<br><em>most HTML tags may be used</em>]]></description><!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.htmlon how to target different products --><!-- uncomment to enable plugin in all products<depends>com.intellij.modules.lang</depends>--><!--依賴的其他插件能力--><extensions defaultExtensionNs="com.intellij"><!-- Add your extensions here --></extensions><!--插件動(dòng)作--><actions><!-- Add your actions here --></actions> </idea-plugin>創(chuàng)建一個(gè) Action
Action 是 IDEA 中對(duì)事件響應(yīng)的處理器,它的 actionPerformed 就像是 JS 中的 onClick 方法。可以看出來(lái),插件的開(kāi)發(fā)本質(zhì)上跟 web、Android 的開(kāi)發(fā)沒(méi)有什么不同,因?yàn)槎际鞘录?qū)動(dòng)的編程。
我們可以直接使用 IDEA 提供的 Action 生成器
點(diǎn)擊 OK 之后會(huì)在 src 生成類文件:
package com.xiaokai.test;import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent;public class HelloWorldAction extends AnAction {@Overridepublic void actionPerformed(AnActionEvent e) {// TODO: insert action logic here} }同時(shí),動(dòng)作的信息也會(huì)注冊(cè)到 plugin.xml 中
<!--插件動(dòng)作--><actions><!-- Add your actions here --><action id="demo.hello.world" class="com.xiaokai.test.HelloWorldAction" text="HelloWorld"description="Say Hello World"><add-to-group group-id="GenerateGroup" anchor="last"/></action></actions>彈出對(duì)話框
創(chuàng)建完 Action 之后我們就要開(kāi)始往里面寫(xiě)邏輯了,既然是 Hello World 教學(xué),那我們就來(lái)試一下最簡(jiǎn)單的彈出對(duì)話框。
@Overridepublic void actionPerformed(AnActionEvent e) {//獲取當(dāng)前在操作的工程上下文Project project = e.getData(PlatformDataKeys.PROJECT);//獲取當(dāng)前操作的類文件PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);//獲取當(dāng)前類文件的路徑String classPath = psiFile.getVirtualFile().getPath();String title = "Hello World!";//顯示對(duì)話框Messages.showMessageDialog(project, classPath, title, Messages.getInformationIcon());}代碼寫(xiě)完之后,打開(kāi) Gradle 的界面,點(diǎn)擊 runIde 就會(huì)啟動(dòng)一個(gè)安裝了插件的 IDEA,然后就可以進(jìn)行測(cè)試。你還可以右鍵啟動(dòng) Debug 模式,這樣還能進(jìn)行斷點(diǎn)。
運(yùn)行的效果如下圖:
可以看到,我們右鍵打開(kāi) Generate 菜單之后,里面最后一項(xiàng)就是我們添加的 Action,
進(jìn)階的教程
如果想學(xué)習(xí)更多的原理和設(shè)計(jì)理念可以看IntelliJ Platform SDK的官方文檔。不過(guò)老實(shí)說(shuō),它的文檔寫(xiě)的挺差的,基本上就是簡(jiǎn)單講了一下概念和原理,沒(méi)有深入的分析。所以如果要深入研究還得靠自己。最靠譜的學(xué)習(xí)方式就是看別人寫(xiě)的插件,舉個(gè)例子,你想知道怎么樣實(shí)現(xiàn)自動(dòng)生成代碼,你就去找支持這個(gè)功能的插件,看他的源碼是怎么寫(xiě)的。
我當(dāng)時(shí)寫(xiě)CodeMaker的時(shí)候也是靠自己啃源碼之后寫(xiě)出來(lái)的。下面我簡(jiǎn)單介紹一下我用過(guò)的一些 API,這些 API 基本都沒(méi)有文檔說(shuō)明,全靠代碼相傳。
判斷當(dāng)前光標(biāo)選擇的元素是什么
//獲取當(dāng)前事件觸發(fā)時(shí),光標(biāo)所在的元素PsiElement psiElement = anActionEvent.getData(LangDataKeys.PSI_ELEMENT);//如果光標(biāo)選擇的不是類,彈出對(duì)話框提醒if (psiElement == null || !(psiElement instanceof PsiClass)) {Messages.showMessageDialog(project, "Please focus on a class", "Generate Failed", null);return;}獲取當(dāng)前類文件的所有類對(duì)象
一個(gè)類文件中可能會(huì)有內(nèi)部類,所以讀取的時(shí)候返回的是一個(gè)列表
public static List<PsiClass> getClasses(PsiElement element) {List<PsiClass> elements = Lists.newArrayList();List<PsiClass> classElements = PsiTreeUtil.getChildrenOfTypeAsList(element, PsiClass.class);elements.addAll(classElements);for (PsiClass classElement : classElements) {//這里用了遞歸的方式獲取內(nèi)部類elements.addAll(getClasses(classElement));}return elements;}格式化代碼
public static void reformatJavaFile(PsiElement theElement) {CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(theElement.getProject());try {codeStyleManager.reformat(theElement);} catch (Exception e) {LOGGER.error("reformat code failed", e);}}使用粘貼板
CopyPasteManager.getInstance().setContents(new SimpleTransferable(table.toString(), DataFlavor.allHtmlFlavor));原文鏈接
轉(zhuǎn)載于:https://my.oschina.net/u/1464083/blog/3014373
總結(jié)
以上是生活随笔為你收集整理的IDEA 插件开发入门教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 做梦梦到老太太拉屎啥意思
- 下一篇: 你认为已经过时的C语言,是如何影响500