1. 程式人生 > 程式設計 >詳解基於IDEA2020.1的JAVA程式碼提示外掛開發例子

詳解基於IDEA2020.1的JAVA程式碼提示外掛開發例子

之前因為專案組有自己的程式碼規範,為了約束平時的開發規範,於是基於2019.1.3版本開發了一個程式碼提示的外掛。但是在把IDEA切換到2020.1版本的時候,卻發現瘋狂報錯,但是網上關於IDEA外掛開發的相關文章還是不夠多,只能自己解決。於是根據官方的SDK文件,使用Gradle重新構建了一下專案,把程式碼拉了過來。下文會根據2020.1版本簡單開發一個程式碼異常的提示外掛,把容易踩坑的地方提示一下。

1、首先先根據IDEA外掛開發官方文件,用Gradle新建一個project

選中file -> new -> Project...,在彈出的視窗左側選擇Gradle,彈出以下介面:

詳解基於IDEA2020.1的JAVA程式碼提示外掛開發例子

預設勾選了Java,需要額外勾選IntelliJ Platform Plugin

來表示這是一個IDEA外掛專案,還需要勾選Kotlin/JVM這一項,為什麼要勾選這一項呢,官網是這麼介紹的:

To include support for the Kotlin language in the plugin,check the Kotlin/JVM box (circled in green below.) This option can be selected with or without the Java language.

也就是說,如果我們開發的外掛需要對JAVA程式碼做支援的話,是要勾選這一項的。所有如果外掛是基於JAVA程式碼檢查的話,需要勾選這一個選項。

勾選完之後,點選next,之後的資訊根據自己實際需要填寫即可,然後點選finish,然後默默等待Gradle構建專案,如果可以的話掛個梯子,下載包什麼的還是挺慢的。

構建完後的專案的目錄結構以及每一個目錄的作用,可以直接去看官方文件,裡面有介紹。

https://www.jetbrains.org/intellij/sdk/docs/tutorials/build_system/prerequisites.html

2、 構建完專案後,需要修改build.gradle部分配製

構建完後,預設會開啟build.gradle檔案,內容如下:

plugins {
  id 'java'
  id 'org.jetbrains.intellij' version '0.4.19'
  id 'org.jetbrains.kotlin.jvm' version '1.3.71'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
  mavenCentral()
}

dependencies {
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
  testCompile group: 'junit',name: 'junit',version: '4.12'
}

// See https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
  version '2020.1'
}
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>"""
}

這裡有個坑,構建完後,我把以前的程式碼複製過來,提醒我有部分類沒有找到,也就是說沒有引入對應的jar包。後來我在官網例子裡面發現,它的build.gradle檔案,和我的build檔案有點不一樣,具體不一樣的地方如下:

// See https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
 version = '2020.1'
 plugins = ['java']
 sameSinceUntilBuild = true
}

它在intellij裡面,多了一個plugins = ['java']的選項,如果缺少這個選項的話,會缺少java-api.jar等jar等JAVA程式碼支援的jar包,導致一些類或者方法不可用。所以如果是JAVA程式碼支援的話,build.gradle檔案需要加上plugins = ['java']這一行。

3、修改plugin.xml檔案

plugin.xml檔案是對於本外掛的作用的一些描述,以及一些依賴關係配製,構建完後的plugin.xml檔案內容如下:

<idea-plugin>
  <id>org.example.new-plugin-for-java</id>
  <name>Plugin display name here</name>
  <vendor email="[email protected]" url="http://www.yourcompany.com">YourCompany</vendor>

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

  <!-- please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
     on how to target different products -->
  <depends>com.intellij.java</depends>

  <extensions defaultExtensionNs="com.intellij">
    <!-- Add your extensions here -->
    <localInspection
        language="JAVA"
        displayName="test displayer"
        groupPath="Java"
        groupBundle="messages.InspectionsBundle"
        groupKey="group.names.probable.bugs"
        enabledByDefault="true"
        level="ERROR"
        implementationClass="com.nw.TestInsepction"/>
  </extensions>

  <actions>
    <!-- Add your actions here -->
  </actions>
</idea-plugin>

這裡有個坑,如果是IDEA2019.2以前的版本的話,這個檔案不用其他東西,直接參考網上的外掛開發教程,寫好程式碼,就可以正常運行了。但是如果是IDEA2019.2的版本的話,執行的時候會瘋狂報錯,一開始不知道為什麼,只能又去翻官方的例子,玩大家一起來找不同,結果發現官網的例子,下面的配置資訊和預設構建的不一樣:

 <!-- Evaluates java PSI -->
 <depends>com.intellij.modules.java</depends>

原來這裡的依賴還要改一下,改成上面這樣,那為什麼要改成這個依賴呢,這個時候,我才發現預設構建的plugin.xml裡面,在depends上面有一段註釋,大概意思就是,請前往註釋裡面的網站去找到如何根據產品去選擇對應的depends,那就很簡單了,直接上網頁看,裡面很多的介紹,以及各種不同的depends是幹嘛的。網頁裡面有這麼一段話:

(2) The Java language functionality was extracted as a plugin in version 2019.2 of the IntelliJ Platform. This refactoring separated the Java implementation from the other,non-language portions of the platform. Consequently,Java dependencies are expressed differently in plugin.xml depending on the version of the IntelliJ Platform being targeted:

Syntax required for releases prior to 2019.2,allowable in all releases:

  • plugin.xml include com.intellij.modules.java

Syntax for 2019.2 and later releases:

  • plugin.xml allowable alternative include com.intellij.java
  • build.gradle required to include intellij.plugins 'java'

大概意思是,從2019.2版本開始後,java程式碼相關的支援抽成了一個外掛,不包含在預設構建的包裡面了,所以從2019.2版本開始後,plugin.xmlbuild.gradle需要修改成相關的配置。這也是為什麼我們第二步要改build.gradle的原因。

4、參考網上的例子,編寫第一個程式碼提示外掛

新建一個java類,內容如下,這是一個測試用的提示外掛,在所有變數上面提示"this is error"

package com;

import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiField;
import org.jetbrains.annotations.NotNull;

/**
 * 這是一個測試用的提示外掛,在所有變數上面提示"this is an error"
 * @author LiuYeFeng
 * @date 2020/5/5
 * @e-mail [email protected]
 */
public class TestInspectionTool extends AbstractBaseJavaLocalInspectionTool {

  @NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,boolean isOnTheFly) {
    // 返回一個java元素的訪問器,重寫當訪問變數的時候,需要做的操作
    return new JavaElementVisitor() {
      @Override
      public void visitField(PsiField field) {
        super.visitField(field);
        // 註冊問題,也就是在變數上面顯示異常紅色下劃線,並提示"this is an error"
     		// 如果可以的話,這裡也可以附帶上快速修復問題的方法
        holder.registerProblem(field,"this is an error");
      }
    };
  }
}

然後在plugin.xml裡面的extensions新增上面編寫的外掛,如下;

 <extensions defaultExtensionNs="com.intellij">
    <!-- Add your extensions here -->
    <localInspection
        language="JAVA"
        displayName="Test field error"
        groupPath="Java"
        groupBundle="messages.InspectionsBundle"
        groupKey="group.names.probable.bugs"
        enabledByDefault="true"
        level="ERROR"
        implementationClass="com.TestInspectionTool"/>
  </extensions>

以上配置大致是註冊一個程式碼提示元件,裡面的引數會決定你的提示配置在IDEA的哪個分類裡面,以及提示的等級,例子裡面用ERROR級別,可以檢視的簡單一點。

5、開始看程式碼提示外掛的效果

點選右上角的debug,等待編譯執行。執行後會彈出一個新的IDEA,這個IDEA會載入了我們編寫的外掛,同時在我們原來編寫外掛的IDEA可以看到日誌輸出等東西,也可以斷點。可以簡單理解為新的IDEA是一個瀏覽器,我們在用網頁除錯後端介面。

因為我們編寫的外掛是新寫一個變數,不管三七二十一就會報錯,提示this is an error,效果如下;

詳解基於IDEA2020.1的JAVA程式碼提示外掛開發例子

到此,一個完成的程式碼異常提示外掛,就簡單完成了。

6、程式碼提示外掛還可以做到的

我們編寫的這個外掛,其實是比較簡單的,並沒有做邏輯分析。我們是可以根據實際需要,去編寫一些專案組本身特有的功能的,例如某些繼承自特殊類的所有欄位,必須要有註釋。在Service裡面的方法,異常返回之前必須要記錄日誌或者一些其他操作等,都是可以做到的,還可以做一些快速修復(quick fix),例如欄位沒有註釋可以快速生成註釋。

這就需要對IDEA語法樹相關有了解,IDEA把程式碼抽象成了Psi語法樹,根據不同的程式碼功能劃分為不同的PsiElement,例如註釋是PsiComment,欄位是PsiField,方法是PsiMethod,類是PsiClass。IDEA本身也提供了相當多的工具類,例如ReferencesSearch可以尋找類或者方法的引用點,PsiTreeUtil可以處理程式碼語法樹上面的一些操作,例如獲取變數所在的方法,ControlFlowUtil可以對程式碼進行解析等,還有PsiClassUtilPsiFieldUtil等各種相關性的工具類可以提供各種便捷的操作,這就需要外掛開發者自己去摸索。遇到問題可以去IDEA官方問答論壇去找一下,說不定別人已經幫你解決了這個問題了。

附加:

IntelliJ Platform SDK官網

https://www.jetbrains.org/intellij/sdk/docs/intro/welcome.html

IntelliJ 外掛開發交流社群

https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development

到此這篇關於詳解基於IDEA2020.1的JAVA程式碼提示外掛開發例子的文章就介紹到這了,更多相關IDEA2020.1 JAVA程式碼提示外掛內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!