国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

IntelliJ IDE 插件開發(fā) | (七)PSI 入門及實(shí)戰(zhàn)(實(shí)現(xiàn) MyBatis 插件的跳轉(zhuǎn)功能)

這篇具有很好參考價(jià)值的文章主要介紹了IntelliJ IDE 插件開發(fā) | (七)PSI 入門及實(shí)戰(zhàn)(實(shí)現(xiàn) MyBatis 插件的跳轉(zhuǎn)功能)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

系列文章

本系列文章已收錄到專欄,交流群號(hào):689220994,也可點(diǎn)擊鏈接加入。

前言

所謂 PSI(Program Structure Interface),直譯過(guò)來(lái)是程序結(jié)構(gòu)接口,其實(shí)就是 IntelliJ 平臺(tái)給我們提供用來(lái)解析代碼文件,簡(jiǎn)化對(duì)各類編程語(yǔ)言(Java、Kotlin、XML)操作的接口。大部分針對(duì)編程語(yǔ)言或者框架的便利插件其實(shí)就與此相關(guān),本文則會(huì)先介紹關(guān)于 PSI 的一些基礎(chǔ)知識(shí),然后再以一些 Mybatis 插件提供的 Java 方法 和 Mapper XML 文件互相跳轉(zhuǎn)的例子來(lái)說(shuō)明 PSI 的實(shí)際應(yīng)用,最終實(shí)現(xiàn)效果如下圖,本文涉及的到的完整代碼文件也已上傳到GitHub。

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

PSI file(PSI 文件)

在本系列的第五篇文章中介紹了Virtual Files 和 Documents 用于處理文件的 API,而 PSI file 也是用于處理文件的 API,不過(guò)也有一些不同,具體如下:

類別 層面 范圍
VF、Document 文本文件 應(yīng)用級(jí)
PSI 編程語(yǔ)言語(yǔ)法樹 項(xiàng)目級(jí)

獲取文件的 PSI file 對(duì)象的方式主要有以下幾種(來(lái)自官網(wǎng)):

Context API
Action AnActionEvent.getData(CommonDataKeys.PSI_FILE)
Document PsiDocumentManager.getPsiFile()
PSI Element PsiElement.getContainingFile()
Virtual File PsiManager.findFile(), PsiUtilCore.toPsiFiles()
File Name FilenameIndex.getVirtualFilesByName()

最后一種方式FilenameIndex.getVirtualFilesByName()得到的結(jié)果是Virtual File 對(duì)象,需要再通過(guò)倒數(shù)第二行的方式再獲取到對(duì)應(yīng)的 PIS file 對(duì)象。

不過(guò)通過(guò)以上方式獲取到的 PsiFile 只是頂層的接口,針對(duì)不同的編程語(yǔ)言,我們會(huì)使用相應(yīng)的實(shí)現(xiàn)類。例如 Java 是 PsiJavaFile,XML 是 XMLFile。

下面通過(guò)實(shí)際使用來(lái)進(jìn)行介紹,首先是 PsiJavaFile,當(dāng)然在使用之前需要確保build.gradle文件中將 Java 添加到插件配置中(XML 內(nèi)置無(wú)需添加):

intellij {
    // 用到的插件
    plugins.set(listOf("com.intellij.java"))
}

然后在plugin.xml中加入以下配置:

<depends>com.intellij.modules.java</depends>

如果是 XML 則需要添加如下配置:

<depends>com.intellij.modules.xml</depends>

經(jīng)過(guò)以上配置后,我們就可以使用 PsiJavaFile 和 XMLFile 的相關(guān) API 了。

例如以下代碼可以得到 java 文件的所屬表名和類中 所有的方法名,然后展示出來(lái):

class PsiJavaAction: AnAction() {

    override fun actionPerformed(e: AnActionEvent) {
        // 獲取 PsiFile 對(duì)象
        val psiFile = e.getData(CommonDataKeys.PSI_FILE)
        // 轉(zhuǎn)換為 PsiJavaFile
        val psiJavaFile = psiFile as PsiJavaFile
        // 獲取類所屬包
        Utils.info("當(dāng)前類所屬包:${psiJavaFile.packageName}")
        // 遍歷獲取所有的方法名
        psiJavaFile.accept(object: JavaRecursiveElementVisitor() {
            override fun visitMethod(method: PsiMethod) {
                Utils.info("查找到方法:${method.name}")
            }
        })
    }

}

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

在以上代碼中需要注意psiJavaFile.accept()方法,其中 accept 方法是 PsiFile 所提供的方法,方法簽名為void accept(@NotNull PsiElementVisitor visitor),用于遍歷 PSI 文件中的各類元素,可以看到上面我們?cè)趥鲄r(shí)傳遞的是JavaRecursiveElementVisitor,這是用于遍歷 Java 中各類元素(字段、方法、注解等)的一個(gè)實(shí)現(xiàn)類,只需要重寫對(duì)應(yīng)的方法即可,在上面我們重寫了visitMethod方法,其實(shí)內(nèi)部提供了很多方法,大家可以自行嘗試,通過(guò)方法名也可以看到這里還支持遍歷 break 語(yǔ)句,斷言語(yǔ)句等等:

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

下面再說(shuō)明如何遍歷 XML 文件中的元素:

class PsiXMLAction: AnAction() {

    override fun actionPerformed(e: AnActionEvent) {
        // 獲取 PsiFile 對(duì)象
        val psiFile = e.getData(CommonDataKeys.PSI_FILE)
        // 轉(zhuǎn)換為 XmlFile
        val xmlFile = psiFile as XmlFile
        // 獲取根標(biāo)簽名稱
        Utils.info("根標(biāo)簽名稱:${xmlFile.rootTag?.name}")
        // 遍歷獲取所有的元素信息
        xmlFile.accept(object: XmlRecursiveElementVisitor() {
            override fun visitXmlAttribute(attribute: XmlAttribute) {
                Utils.info("屬性名稱:${attribute.name}, 屬性值:${attribute.value}")
            }
        })
    }

}

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

可以看到這里遍歷使用的是XmlRecursiveElementVisitor,是 XML 對(duì)于PsiElementVisitor 的一個(gè)實(shí)現(xiàn)類,用于遍歷 XML 文件中的各種元素:

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

PSI Element(PSI 元素)

在上面介紹 PSI 文件的時(shí)候多次提到元素的概念,PSI 文件則正是由一系列的 PSI Element 所組成。和 PSI file 類似,PSI Element 也屬于一個(gè)頂層接口,針對(duì)不同的編程語(yǔ)言,會(huì)有多種 PSI 元素。以 Java 為例,有 PsiClass、PSIMethod、PsiField 等對(duì)應(yīng) Java 語(yǔ)法的各類元素。而 XML 中也有 XmlTag、XmlAttribute 等概念。那我們?nèi)绾慰焖僦酪粋€(gè)文件中有哪些 PSI 元素?如何快速知道一個(gè)我們不熟悉的編程語(yǔ)言中的 PSI 元素?別慌,IntelliJ平臺(tái)給我提供了工具:

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

通過(guò) IntelliJ 平臺(tái)的工具,我們可以很方便地查看當(dāng)前或者任意一種文件的 PSI 結(jié)構(gòu),下面分別以 Java 和 XML 文件為例,首先是 Java 文件:

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

同時(shí)點(diǎn)擊左下的元素節(jié)點(diǎn),上方還會(huì)自動(dòng)對(duì)應(yīng)到元素位置:

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

然后是 XML 文件:

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

當(dāng)然,除了 Java 和 XML,IntelliJ 支持的編程語(yǔ)言遠(yuǎn)不止這些,這里展示一部分,剩下的大家可以自行探索:

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

上面介紹了如何快速查看 PSI 文件中的元素,下面再介紹如何去獲取 PSI 元素,以下來(lái)自官網(wǎng):

Context API
Action AnActionEvent.getData(CommonDataKeys.PSI_ELEMENT)Note: If an editor is currently open and the element under caret is a reference, this will return the result of resolving the reference.
PSI File PsiFile.findElementAt(offset)
Reference PsiReference.resolve()

可以看到總共有三種方式:第一種是直接獲取當(dāng)前光標(biāo)位置的 PSI 元素;第二種是可以自己指定偏移量(如果不熟悉偏移量的概念,可以看本系列第五篇文章中講解 CaretModel 的部分),獲取指定文件指定位置的 PSI 元素;最后一種引用則使用的較少,這里不再展開介紹,大家可以查看官方文檔進(jìn)行了解。

除了獲取某個(gè)位置的 PSI 元素,我們還可以獲取其所屬父元素或者子元素,下面以 Java 文件為例講解如何使用:

class PsiJavaAction: AnAction() {

    override fun actionPerformed(e: AnActionEvent) {
        val psiFile = e.getData(CommonDataKeys.PSI_FILE)
        // 獲取光標(biāo)處 PSI 元素,假定該元素在方法內(nèi)部
        val psiElement = e.getData(PlatformDataKeys.EDITOR)
        	?.caretModel?.let { psiFile?.findElementAt(it.offset) }
        // 獲取該元素所屬的方法名
        val psiMethod = PsiTreeUtil.getParentOfType(psiElement, PsiMethod::class.java)
        // 獲取該元素所屬的類名
        val psiClass = PsiTreeUtil.getParentOfType(psiElement, PsiClass::class.java)
        Utils.info("所屬方法名:${psiMethod?.name}")
        Utils.info("所屬類名:${psiClass?.name}")
    }

}

可以看到上面我們使用PsiTreeUtil::getParentOfType可以獲取到一個(gè)元素的父元素,同時(shí)支持跨層級(jí)獲取,既可以獲取元素所屬的方法,也可以獲取元素所屬的類。

效果如下:

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

相應(yīng)地我們也可以通過(guò)PsiTreeUtil::getChildrenOfTypeAsList去獲取某個(gè)元素的所有子元素:

class PsiJavaAction: AnAction() {

    override fun actionPerformed(e: AnActionEvent) {
        val psiFile = e.getData(CommonDataKeys.PSI_FILE)
        // 先獲取光標(biāo)所在處元素所屬的類
        val psiElement = e.getData(PlatformDataKeys.EDITOR)
        	?.caretModel?.let { psiFile?.findElementAt(it.offset) }
        val psiClass = PsiTreeUtil.getParentOfType(psiElement, PsiClass::class.java)
        // 獲取類中所有的方法
        val psiMethods = PsiTreeUtil.getChildrenOfTypeAsList(psiClass, PsiMethod::class.java)
        Utils.info("包含的方法:${psiMethods.joinToString(",") { it.name }}")
    }

}

intellij psi,Kotlin,ide,mybatis,kotlin,intellij-idea

實(shí)戰(zhàn)

在正式實(shí)現(xiàn)前,先介紹一下整體的實(shí)現(xiàn)思路,這里只說(shuō)明如何從 Java 方法跳轉(zhuǎn)到 Mapper XML 文件中的節(jié)點(diǎn),反向參考代碼也很好理解,思路如下:

  1. 左側(cè)圖標(biāo)行標(biāo)記符通過(guò)實(shí)現(xiàn)RelatedItemLineMarkerProvider并重寫collectNavigationMarkers方法設(shè)置。
  2. 判斷代碼行的元素類型為 PsiMethod 才進(jìn)行設(shè)置,同時(shí)文件類名以 Mapper 結(jié)尾。
  3. 根據(jù)類名在項(xiàng)目查找同名的 Mapper XML 文件。
  4. 通過(guò) accept 方法遍歷 XML 文件所有的屬性,將 id 值為對(duì)應(yīng)方法名的標(biāo)簽所對(duì)應(yīng)的元素保存到可跳轉(zhuǎn)的目標(biāo)。

設(shè)置行標(biāo)記符號(hào),平臺(tái)給我們提供了 RelatedItemLineMarkerProvider 類進(jìn)行設(shè)置,只需要自定義了自己的行標(biāo)記類,然后在 plugin.xml 中添加 如下配置即可:

<codeInsight.lineMarkerProvider language="JAVA"
	implementationClass="cn.butterfly.psi.provider.JavaMapperLineMarkerProvider"/>

代碼實(shí)現(xiàn)如下:

class JavaMapperLineMarkerProvider: RelatedItemLineMarkerProvider() {

    override fun collectNavigationMarkers(
        element: PsiElement,
        result: MutableCollection<in RelatedItemLineMarkerInfo<*>>
    ) {
        // 查找類名后綴為 Mapper 內(nèi)的所有方法
        if (element !is PsiMethod) {
            return
        }
        val psiClass = PsiTreeUtil.getParentOfType(element, PsiClass::class.java) ?: return
        val className = psiClass.name ?: return
        if (!className.endsWith("Mapper")) {
            return
        }

        // 查找同名 XML 文件對(duì)應(yīng)的 PSI 文件對(duì)象
        val virtualFile = FileTypeIndex.getFiles(XmlFileType.INSTANCE, GlobalSearchScope.allScope(element.project))
            .first { it.name.startsWith(className) }
        val psiFile = PsiManager.getInstance(element.project).findFile(virtualFile)

        // 遍歷 XML 文件中標(biāo)簽 id 節(jié)點(diǎn)值等于 Java 方法名的元素, 然后添加可跳轉(zhuǎn)的行標(biāo)記符
        psiFile?.accept(object : XmlRecursiveElementVisitor() {
            override fun visitXmlAttribute(attribute: XmlAttribute) {
                if (attribute.name == "id" && attribute.value == element.name) {
                    // NavigationGutterIconBuilder 用于創(chuàng)建標(biāo)識(shí)符
                    result.add(
                        NavigationGutterIconBuilder.create(PluginIcons.MAPPER_ICON)
                            .setTargets(setOf(attribute.navigationElement))
                            .setTooltipText("Navigation to target in mapper xml").createLineMarkerInfo(element)
                    )
                }
            }
        })
    }

}

總結(jié)

本文簡(jiǎn)單介紹了關(guān)于 PSI 文件和元素的基礎(chǔ)知識(shí),最后以一個(gè) Mybatis 文件跳轉(zhuǎn)的例子去演示了如何去實(shí)際運(yùn)用 PSI,在下一篇文章則會(huì)介紹關(guān)于 PSI 的進(jìn)階知識(shí),敬請(qǐng)期待~~文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-861625.html

到了這里,關(guān)于IntelliJ IDE 插件開發(fā) | (七)PSI 入門及實(shí)戰(zhàn)(實(shí)現(xiàn) MyBatis 插件的跳轉(zhuǎn)功能)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • IntelliJ IDEA 2021版本可用的IDE Eval Reset插件

    IntelliJ IDEA 2021版本可用的IDE Eval Reset插件

    IDEA版本說(shuō)明: 如果你是最新版本或者比 2021.2.2 版本高的話,就可能存在失效或者不可用的情況,可以嘗試降低版本使用。 在 idea- settings- plugins 里搜索 IDE Eval Reset (注意:是在Marketplace欄目下搜索,Installedl欄目下是你已經(jīng)安裝好的插件),然后點(diǎn)擊 Install 進(jìn)行安裝,安裝完

    2024年02月14日
    瀏覽(37)
  • IntelliJ IDEA安裝Mybatis 插件Free Mybatis plugin

    IntelliJ IDEA安裝Mybatis 插件Free Mybatis plugin

    需求描述 在開發(fā)一些Mybatis的項(xiàng)目,經(jīng)常需要寫一個(gè)Mapper接口,在找代碼過(guò)程,經(jīng)常需要去找對(duì)應(yīng)的xml文件,所以非常的不方便。自從有了免費(fèi)的free-mybatis-plugin插件之后 ,在可以實(shí)現(xiàn)在idea里一鍵跳轉(zhuǎn)到對(duì)應(yīng)的xml文件,反之,在xml文件也可以一鍵跳轉(zhuǎn)到對(duì)應(yīng)mapper接口。 也有其

    2024年02月15日
    瀏覽(28)
  • 【Java】IDE集成開發(fā)環(huán)境工具IntelliJ安裝和使用

    【Java】IDE集成開發(fā)環(huán)境工具IntelliJ安裝和使用

    歡迎來(lái)到《小5講堂》 大家好,我是全棧小5。 這是《Java》序列文章,每篇文章將以博主理解的角度展開講解, 特別是針對(duì)知識(shí)點(diǎn)的概念進(jìn)行敘說(shuō),大部分文章將會(huì)對(duì)這些概念進(jìn)行實(shí)際例子驗(yàn)證,以此達(dá)到加深對(duì)知識(shí)點(diǎn)的理解和掌握。 溫馨提示:博主能力有限,理解水平有限

    2024年01月18日
    瀏覽(30)
  • Intellij IDEA 插件開發(fā)

    Intellij IDEA 插件開發(fā)

    很多idea插件文檔更多的是介紹如何創(chuàng)建一個(gè)簡(jiǎn)單的idea插件,本篇文章從開發(fā)環(huán)境、demo、生態(tài)組件、添加依賴包、源碼解讀、網(wǎng)絡(luò)請(qǐng)求、渲染數(shù)據(jù)、頁(yè)面交互等方面介紹,是一篇能夠滿足基本的插件開發(fā)工程要求的文章。 如有疏漏歡迎指正,如想深入了解歡迎探討。 Intelli

    2024年02月11日
    瀏覽(23)
  • Delphi Professional Crack,IDE插件開發(fā)和擴(kuò)展IDE

    Delphi Professional Crack,IDE插件開發(fā)和擴(kuò)展IDE

    構(gòu)建具有強(qiáng)大視覺(jué)設(shè)計(jì)功能的單源多平臺(tái)本機(jī)應(yīng)用程序。 Delphi幫助您使用Object Pascal為Windows、Mac、Mobile、IoT和Linux構(gòu)建和更新數(shù)據(jù)豐富、超連接、可視化的應(yīng)用程序。Delphi Professional適合個(gè)人開發(fā)人員和小型團(tuán)隊(duì)構(gòu)建桌面和移動(dòng)應(yīng)用程序。 Delphi功能 單一代碼庫(kù)-用更少的編碼工

    2024年02月14日
    瀏覽(26)
  • IDE(集成開發(fā)環(huán)境)插件是安全開發(fā)的便捷方式之一

    IDE(集成開發(fā)環(huán)境)插件是安全開發(fā)的便捷方式之一

    開發(fā)人員每天都使用插件,插件的功能在于簡(jiǎn)化開發(fā)流程,例如自動(dòng)檢測(cè)所有特殊字符(如“;”、“:”)或語(yǔ)法合規(guī)性。創(chuàng)建插件的目的本身就是為了讓開發(fā)人員能夠在編寫代碼時(shí)檢測(cè)漏洞,并在無(wú)需離開 IDE 環(huán)境的情況下立即修復(fù)漏洞。我們來(lái)了解一下,什么是插件以及如

    2024年03月23日
    瀏覽(22)
  • MyBatis第八講:MyBatis插件機(jī)制詳解與實(shí)戰(zhàn)

    MyBatis提供了一種插件(plugin)的功能,雖然叫做插件,但其實(shí)這是攔截器功能。那么攔截器攔截MyBatis中的哪些內(nèi)容呢?本文是MyBatis第8講,對(duì)MyBatis插件機(jī)制詳解。

    2024年02月13日
    瀏覽(31)
  • AIGC:IntelliJ IDEA 神級(jí)插件( ChatGPT 團(tuán)隊(duì)開發(fā))

    AIGC:IntelliJ IDEA 神級(jí)插件( ChatGPT 團(tuán)隊(duì)開發(fā))

    Bito是一款在IntelliJ IDEA編輯器中的插件,Bito插件是由ChatGPT團(tuán)隊(duì)開發(fā)的,它是ChatGPT團(tuán)隊(duì)為了提高開發(fā)效率而開發(fā)的一款工具。Bito插件的強(qiáng)大之處在于它可以幫助開發(fā)人員更快地提交代碼,同時(shí)還提供了一些有用的功能,如自動(dòng)補(bǔ)全提交信息、快速查看歷史記錄等。 用他自己的

    2024年02月12日
    瀏覽(20)
  • 十個(gè)超級(jí)實(shí)用的 IntelliJ IDEA 插件,開發(fā)更高效

    十個(gè)超級(jí)實(shí)用的 IntelliJ IDEA 插件,開發(fā)更高效

    Intellij IDEA廣受歡迎,被認(rèn)為是最佳的IDE之一,同時(shí)加上一些優(yōu)秀的插件,會(huì)讓開發(fā)人員的工作更加輕松愉快。本文推薦十個(gè)Intellij IDEA優(yōu)秀插件。 IDE是開發(fā)人員的必備武器,擁有一個(gè)好的IDE不僅能提高工作效率,還能讓開發(fā)人員更加享受編碼的樂(lè)趣。Intellij IDEA廣受歡迎,被認(rèn)

    2024年04月09日
    瀏覽(27)
  • flutter開發(fā)實(shí)戰(zhàn)-指紋、面容ID驗(yàn)證插件實(shí)現(xiàn)

    flutter開發(fā)實(shí)戰(zhàn)-指紋、面容ID驗(yàn)證插件實(shí)現(xiàn)

    flutter開發(fā)實(shí)戰(zhàn)-指紋、面容ID驗(yàn)證插件實(shí)現(xiàn) 在iOS開發(fā)中,經(jīng)常出現(xiàn)需要指紋、面容ID驗(yàn)證的功能。 指紋、面容ID是一種基于用生物識(shí)別技術(shù),通過(guò)掃描用戶的面部特征來(lái)驗(yàn)證用戶身份。 在iOS中實(shí)現(xiàn)指紋、面容ID驗(yàn)證功能,步驟如下 2.1 info.plist配置 在info.plist中配置允許訪問(wèn)FAC

    2024年02月13日
    瀏覽(28)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包