idea插件开发(2)-插件详细配置

一、工程结构

        本章详细讲解下插件工程的配置,官方在github上提供了一个idea插件开发的模板工程,可在​​https://github.com/JetBrains/intellij-platform-plugin-template​​下载,此工程模板与idea中创建的工程最大不同之处就是配置了github的ci-action流程以及junit-test,其它方面没有区别,本文会详细讲解下在进行编码进行要掌握的必要的插件配置相关的知识。

1、工程结构示例

        涉及到一些Gradle的知识可参考笔者写的另一篇关于Gradle工程构建的文章。典型的Idea-plugin工程完整的目录大体如下所示:

├── build.gradle # gradle构建脚本文件,相当于maven的pom.xml文件,****重要****
├── gradle.properties # 可定义一些属性值在build.gradle中使用,****重要****
├── gradle # Gradle包装器,有了包装器就不需要在系统中安装gradle了
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties # 包装器配置文件,****重要****
├── gradlew # 适用于mac和linux系统的shell脚本,不需要改动
├── gradlew.bat # 适用于windows系统的批处理脚本,不需要改动
├── settings.gradle # 多模块管理时的模块依赖配置文件,对于单个项目此文件可选
└── src
    └── main
        ├── java #插件源码
        └── resources #存放语言文件以及插件需要的图片等文件
        │   └── messages
        │   │    └── Bundle_zh_CN.properties #国际化Bundle,需要在plugin.xml文件中配置
	    |   │
        |   └─── META-INF
        |        └─── plugin.xml # 插件配置文件,****重要****
        └────────└─── pluginIcon.svg #插件在IDEA/Plugins中的展示图标

其中有5个配置文件非常重要:

  • settings.gradle:管理工程结构,如果是单模块的工程可忽略;
  • gradlew-wrapper.properties:定义Gradle构建工具的版本等信息;
  • gradle.properties:有两个功能:1、可以自定义多个key-value值,供构建脚本引用;2、定义构建的默认行为;
  • build.gradle:Gradle构建脚本,相当于maven的pom.xml文件;
  • plugin.xml:插件配置,配置插件的依赖、扩展点等插件行为;

注意事项】:构建脚本和工程管理配置文件是可编程的,高版本的idea工程中文件以.gradle.kts结尾的,区别是.kts需要用kotlin语言,.gradle需要用groovy语言来扩展这两个脚本。

2、工程管理配置settings.gradle

        此文件主要是用于多模块配置用的,比如父子工程结构,在父模块中可以配置一些公共的依赖以及依赖的版本等信息,方便实现整个工程统一的管理。

pluginManagement {
    repositories {
        mavenCentral()
        gradlePluginPortal()
    }
}

rootProject.name = "firstplugin"

        如果是多个模块可按如下配置配置,工程名称为b2bdemo,包含两个子模块api和server:

rootProject.name = 'b2bdemo'
include 'api'
include 'server'

二、构建工具配置gradle-wrapper.properties

        此配置文件主要是配置Gradle构建工具的版本等信息。常用的就是如下5个属性,其中distributionUrl默认为-bin,建议配置成-all,原因是包含源代码,这样在构建过程出现问题可以分析源代码。

#Gradle 解包后存储的父目录,默认在userName/.gradle下面;
distributionBase=GRADLE_USER_HOME

#distributionBase指定目录的子目录, distributionBase+distributionPath就是 Gradle 解包后的存放的具体目录
distributionPath=wrapper/dists

#Gradle 指定版本的压缩包下载地址,如果你使用IDEA的话,它会推荐下载all版,包含源代码,这样IDEA就可以分析源代码,提供更加精确的gradle脚本支持,可用于全组统一,而不需要在本地安装各自的版本
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip

#Gradle 压缩包下载后存储父目录
zipStoreBase=GRADLE_USER_HOME

#zipStoreBase指定目录的子目录。zipStoreBase+zipStorePath就是 Gradle 压缩包的存放位置
zipStorePath=wrapper/dists

三、构建脚本配置gradle.properties

        有两个功能:1、可以自定义多个key-value值,供构建脚本引用;2、定义构建的默认行为;多数配置都很清晰,看注释即可。在开发初始也可以把此文件置空,后续需要时再进行配置。

#性能配置
kotlin.incremental.useClasspathSnapshot = false
kotlin.stdlib.default.dependency = false
org.gradle.configuration-cache = true
org.gradle.caching = true
systemProp.org.gradle.unsafe.kotlin.assignment = true

#供build.gradle.kts构建脚本使用的属性
pluginSinceBuild = 221
pluginUntilBuild = 231.*

platformType = IC
platformVersion = 2022.1.4

其它几个常用的配置如下:

  • org.gradle.unsafe.configuration-cache = true:开启gradle缓存,加快构建速度
  • org.jetbrains.intellij.buildFeature.selfUpdateCheck=false:设置插件是否自动更新检查
  • org.jetbrains.intellij.buildFeature.buildSearchableOptions=false:禁止为插件生成索引信息
  • org.jetbrains.intellij.buildFeature.paidPluginSearchableOptionsWarning=false:如果插件为付费的,设置是否可搜索;
  • kotlin.incremental.useClasspathSnapshot=false:Kotlin 编译器抛出内存不足时的解决方法
  • kotlin.stdlib.default.dependency = false:如果Kotlin版本大于1.4设置成false,否则设置成true
  • runIde.autoReloadPlugins = true:修改插件后可重新运行build插件,这样就会自动更新了

四、构建脚本build.gradle

        这是Gradle的核心文件,可用groovy和kotlin语言编写。一般专门做运维时会编写一些程序代码,在idea插件开发时采用纯配置即可。本例中提供了两种配置带脚本语言和不带脚本语言的。

1、脚本类型

采用Kotlin脚本语言定义的构建脚本

import org.jetbrains.changelog.Changelog
import org.jetbrains.changelog.markdownToHTML

fun properties(key: String) = providers.gradleProperty(key)
fun environment(key: String) = providers.environmentVariable(key)

plugins {
    id("java") // Java support
    alias(libs.plugins.kotlin) // Kotlin support
    alias(libs.plugins.gradleIntelliJPlugin) // Gradle IntelliJ Plugin
    alias(libs.plugins.changelog) // Gradle Changelog Plugin
    alias(libs.plugins.qodana) // Gradle Qodana Plugin
    alias(libs.plugins.kover) // Gradle Kover Plugin
}

group = properties("pluginGroup").get()
version = properties("pluginVersion").get()

// Configure project's dependencies
repositories {
    mavenCentral()
}

// Dependencies are managed with Gradle version catalog - read more: https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog
dependencies {
//    implementation(libs.annotations)
}

// Set the JVM language level used to build the project. Use Java 11 for 2020.3+, and Java 17 for 2022.2+.
kotlin {
    jvmToolchain(11)
}

// Configure Gradle IntelliJ Plugin - read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html
intellij {
    pluginName = properties("pluginName")
    version = properties("platformVersion")
    type = properties("platformType")

    // Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file.
    plugins = properties("platformPlugins").map { it.split(',').map(String::trim).filter(String::isNotEmpty) }
}

// Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin
changelog {
    groups.empty()
    repositoryUrl = properties("pluginRepositoryUrl")
}

// Configure Gradle Qodana Plugin - read more: https://github.com/JetBrains/gradle-qodana-plugin
qodana {
    cachePath = provider { file(".qodana").canonicalPath }
    reportPath = provider { file("build/reports/inspections").canonicalPath }
    saveReport = true
    showReport = environment("QODANA_SHOW_REPORT").map { it.toBoolean() }.getOrElse(false)
}

// Configure Gradle Kover Plugin - read more: https://github.com/Kotlin/kotlinx-kover#configuration
kover.xmlReport {
    onCheck = true
}

tasks {
    wrapper {
        gradleVersion = properties("gradleVersion").get()
    }

    patchPluginXml {
        version = properties("pluginVersion")
        sinceBuild = properties("pluginSinceBuild")
        untilBuild = properties("pluginUntilBuild")

        // Extract the  section from README.md and provide for the plugin's manifest
        pluginDescription = providers.fileContents(layout.projectDirectory.file("README.md")).asText.map {
            val start = ""
            val end = ""

            with (it.lines()) {
                if (!containsAll(listOf(start, end))) {
                    throw GradleException("Plugin description section not found in README.md:\n$start ... $end")
                }
                subList(indexOf(start) + 1, indexOf(end)).joinToString("\n").let(::markdownToHTML)
            }
        }

        val changelog = project.changelog // local variable for configuration cache compatibility
        // Get the latest available change notes from the changelog file
        changeNotes = properties("pluginVersion").map { pluginVersion ->
            with(changelog) {
                renderItem(
                    (getOrNull(pluginVersion) ?: getUnreleased())
                        .withHeader(false)
                        .withEmptySections(false),
                    Changelog.OutputType.HTML,
                )
            }
        }
    }

    // Configure UI tests plugin
    // Read more: https://github.com/JetBrains/intellij-ui-test-robot
    runIdeForUiTests {
        systemProperty("robot-server.port", "8082")
        systemProperty("ide.mac.message.dialogs.as.sheets", "false")
        systemProperty("jb.privacy.policy.text", "")
        systemProperty("jb.consents.confirmation.enabled", "false")
    }

    signPlugin {
        certificateChain = environment("CERTIFICATE_CHAIN")
        privateKey = environment("PRIVATE_KEY")
        password = environment("PRIVATE_KEY_PASSWORD")
    }

    publishPlugin {
        dependsOn("patchChangelog")
        token = environment("PUBLISH_TOKEN")
        // The pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3
        // Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more:
        // https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel
        channels = properties("pluginVersion").map { listOf(it.split('-').getOrElse(1) { "default" }.split('.').first()) }
    }
}

Kotlin简化版的构建脚本(推荐)

plugins {
  id("java")
  id("org.jetbrains.intellij") version "1.13.3"
}

group = "com.example"
version = "1.0-SNAPSHOT"

repositories {
  mavenLocal()
  maven("https://maven.aliyun.com/nexus/content/repositories/central/")
  mavenCentral()
}

// Configure Gradle IntelliJ Plugin
// Read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html
intellij {
  version.set("2022.2.5")
  type.set("IC") // Target IDE Platform, IU旗舰版, IC社区版
  plugins.set(listOf(/* Plugin Dependencies */))
}

dependencies {
}

tasks {
  // Set the JVM compatibility versions
  withType {
    sourceCompatibility = "17"
    targetCompatibility = "17"
  }

  patchPluginXml {
    version.set("${project.version}")
    sinceBuild.set("222")
    untilBuild.set("232.*")
  }

  signPlugin {
    certificateChain.set(System.getenv("CERTIFICATE_CHAIN"))
    privateKey.set(System.getenv("PRIVATE_KEY"))
    password.set(System.getenv("PRIVATE_KEY_PASSWORD"))
  }

  publishPlugin {
    token.set(System.getenv("PUBLISH_TOKEN"))
  }

  // 将依赖打进jar包中
  jar.configure {
    duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.INCLUDE
    from(configurations.runtimeClasspath.get().filter { it.name.endsWith("jar")}.map { zipTree(it) })
  }
}

2、构建脚本特殊配置说明

添加Kotlin支持(可选)

plugins {
  id("java")
  id("org.jetbrains.kotlin.jvm") version "1.8.21"
}
java {
  sourceCompatibility = JavaVersion.VERSION_17
}
tasks {
  compileKotlin {
    kotlinOptions.jvmTarget = "17"
  }
  compileTestKotlin {
    kotlinOptions.jvmTarget = "17"
  }
}

intellijGradle插件配置

        Gradle IntelliJ 插件是 Jetllij官方开发的一个插件,可帮助配置您的环境方便开发idea插件包含基于 IntelliJ 的 IDE 构建、测试、验证和发布插件。

        需要配置plugins标签中,pulgins中声明的内容是为了开发插件而依赖的其它框架,比如我们要开发微服务一般要引入springboot框架一个道理。

        详细配置可参考https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html

plugins {
  id("java")
  id("org.jetbrains.intellij") version "1.13.3"
}

【注意事项】:如果插件适用的idea版本是2022.3+,需要在Settings | Build, Execution, Deployment | Build Tools | Gradle,设置JDK不低于Java 17。

插件适用范围

        配置要发布的插件适配的jetllij家族产品的种类和版本。其中 version和type是必填项。如果此插件不依赖其它插件,则plugins.set()设置为空即可。

intellij {
  version.set("2022.1.1")
  type.set("IU")
  plugins.set(listOf("com.jetbrains.php:221.5787.21"))
}

/*plugins.set(listOf("com.jetbrains.php:221.5787.21"))这段代码等价于
om.jetbrains.php*/
  • version:​​ide版本
  • type:适用平台类型,IC​​​ - ​​IntelliJ IDEA Community Edition​​;​​IU​​​ - ​​IntelliJ IDEA Ultimate Edition​​;​​CL​​​ - ​​CLion​​;​​PY​​​ - ​​PyCharm Professional Edition​​;​​PC​​​ - ​​PyCharm Community Edition​​;​​PS​​​ - ​​PhpStorm​​;​​RD​​​ - ​​Rider​​;​​GO​​​ - ​​GoLand​​;​​AI​​​ - ​​Android Studio​​;​​JPS​​ - JPS-only;​​GW​​ - Gateway
  • plugins.set():设置与此插件捆绑的依赖插件,替代的写法是直接在根配置中以代替一般有以下几种情况;
    1. 依赖来自JetBrains Marketplace的插件:使用pluginId:version格式,例如org.intellij.plugins.markdown:231.8109.126. 您选择的版本必须与您正在构建的 IDE 版本兼容
    2. 依赖idea捆绑插件:可以省略版本部分的插件 ID,例如:org.intellij.groovy
    3. 依赖自己的子项目:使用project(':subproject', 'instrumentedJar')格式
    4. 依赖外部的jar包:例如从 JetBrains Marketplace 手动下载或在另一个项目中单独构建的插件更新,将File实例添指向lib.jar文件的任何其他父目录。
intellij {
    plugins.set(listOf(file("/path/to/plugin/lib/")))
}

可依赖的平台模块

        详细可参考Plugin Compatibility with IntelliJ Platform Products | IntelliJ Platform Plugin SDK

或开发自己的idea产品一文。

task属性配置

        详细的配置在​​https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#tasks​​ 中查看说明,task中的一些配置可替换plugin.xml和grablew.properties中的一些默认行为配置。下面列出几个重的经常用到的一些子配置,示例如下:

tasks {
  withType {
    sourceCompatibility = "17"
    targetCompatibility = "17"
  }

  patchPluginXml {
    sinceBuild.set("222")
    untilBuild.set("232.*")
  }
}
  • buildSearchableOptions:是否为插件创建索引,默认为true;
  • ​patchPluginXml:用于设置支持的版本范围,替换plugin.xml中的配置,是一个非常重要的配置;小版本
  • ​listProductsReleases:支持的idea版本,是从远程下载的,可用printProductsReleases和printBundledPlugins输出相关信息
  • publishPlugin:将插件发布到市场,最主要的是设置token和channels值,热门频道可选值有alpha、eap、beta三个
  • signPlugin:与发布相关的插件签名,包含证书、密钥和密码等验证功能,包含三个主要属性
    1. verifyPlugin:验证​​plugin.xml​​描述符的完整性和内容以及插件存档结构,主要是设置某些警告信息是否需要打破构建流程,一般不需要修改;
    2. verifyPluginConfiguration:验证patchPluginXml中相关的配置是否正确,验证插件项目中配置的 SDK、目标平台、API 等的版本
    3. verifyPluginSignature:验证signPlugin配置是否正确,运行IntelliJ Plugin Verifier工具来检查与指定 IntelliJ IDE 构建的二进制兼容性

runIde运行时配置

        改变插件测试运行时的一些设置,并不影响插件发布后的设置,一般用于开发时使用。比如下列几个配置:

tasks {
  runIde {
    jvmArgs("-DmyProperty=value") #启动 IDE 时添加一些 JVM 参数
    systemProperty("name", "value") #修改runIde任务的系统属性
    autoReloadPlugins.set(false) #设置启动自动加载
    buildSearchableOptions { #禁用构建可搜索选项
        enabled = false
    }
  }
}

ui调试

        如果插件涉及到ui界面,则可以在 IntelliJ IDEA 中启用内部模式时打开相应的调试工具,idea默认是关闭的,可以在【菜单】选择修改属性,然后修改idea.properties文件,添加以下语句然后重启,就可以在【工具】-【内部操作】菜单中看到了。

idea.is.internal=true

        使用时,将光标置于 UI 元素的中心单击鼠标左键可显示 Swing 组件的属性,也可以打开工具】-【内部操作】-【UI】-【Laf 默认值】窗口进行UI组件的设置。

五、插件配置plugin.xml

        与插件相关的唯一配置文件,也就是说插件行为样式等所有功能都是在这个文件中配置的,配置项也比较多,详细配置可参考​​plugin.xml​​官方文档。必要的描述示例如下:


 
   
   MyPrluginName
   
   
   YourCompany
 
   
   io.org.example.plugin
 
   
   Integrates Volume Snapshot Service W10
 
    
   Initial release of the plugin.
 
   
   1.1.1
   
    
   com.intellij.java
   com.MySecondPlugin
 
   
   
 
   
   messages.Bundle
 
   
   
   
   
   
   
   
     ...
   
   
   
   
   
   
     
   
     
   
   
   
 ...... 
 

1、基础配置

product-descriptor付费描述符

​        可选,仅适用于付费或免费增值插件;在免费软件中不要设置此值。它有三个必要属性code、release-date、release-version。其中code需要按照官方要求来设置,详细可参考​​code规范​​

idea-version适用版本

        必填项,配置插件适用范围,一般可以用build.grale的patchPluginXml属性来代替。

depends依赖

        可选,如果当前插件依赖另一个插件的话,需要用此值,比如扩展点依赖等。值为另一个插件的id值。config-file相当于一个子的配置文件,可把依赖的插件的配置专让放在另一个文件中,这样可以分别管理。

com.example.dependencypluginid

com.example.dependencypluginid

com.intellij.modules.java

对本地文件依赖

intellij {
    plugins.set(listOf(file("/path/to/plugin/lib/")))
}

2、Actions

action

        ide插件定义的任何一个点击事件称为Action,需要继承AnAction类。所以定义action后需要在配置文件中进行配置,这样idea才能识别此动作。它有以下5个属性。


  

它有6个子元素:

  • ​​:把当前动作添到菜单或工具栏的位置
  • ​​​​:键盘快捷键设置
  • ​​​​:鼠标快捷键设置
  • ​​:覆盖现有特定菜单的显示文本
  • ​​:起一个短点的搜索快捷键,相当于动作的索引​​:
  • :起一个缩写的名字,同synonym功能差不多。

add-to-group

override-text

group

        布局元素,它包含action、group、add-to-group子元素,上述这3个元素可以相互嵌套循环,最终可设计成一个复杂的菜单。特有的子元素主要有:

  • ​​:引用另一个group或action
  • ​​​​​:分隔符,显示为一个水平线

  

reference

        将现有操作元素添加到组中。可以在元素中声明使用。它有一个子元素add-to-group。


  



  
    
  

separator

        定义组中action之间的分隔符。该元素可以在元素下使用,也可以在元素中使用,它有一个子元素add-to-group,示例如下:


  
  
  



  
    
  



3、扩展和扩展点配置

extensions扩展声明

        用于扩展另一个插件声明使用,它可以包含子元素,有两种配置方式:

#使用完全限定扩展名称的扩展声明:

  



  

extensionPoints扩展点

        插件详细的扩展点配置,现在已公布的扩展点有1000多个,需要查看官方文档。有以下几个重要属性;

  • name和qualifiedName:必选,二选一,一般配置name
  • beanClass和interface:二选一,看代码实现哪个都可以
  • dynamic:是否设置为动态插件,默认为false,动态插件涉及的限制比较多不建议使用
  • area:实例化范围,默认为IDEA_APPLICATION,可选值还有IDEA_PROJECT

with

        为扩展点指定所需的父类型。单个元素可以包含多个元素,类似于with中的元素是自定义扩展点的一个成员变量有点类似于依赖注入的方式,两个必选属性,需要结合代码,后续会在扩展点实现时详细讲解:

  • tag和attribute:二选一
  • implements:类名

        
            
        
    

        上述代码的含义是自定的MyExtensionBean.java的扩展点类中有一个属性,这个属性要用@Attribute注解声明为PsiElement类型。注意属性名称的对应。

public class MyExtensionBean{
    @Attribute("psiElementClass")
    private PsiElement psiElementClass;

}

4、发布配置

        如果发布插件到平台上需要必要的签名和认证,这些信息会涉及到安全性问题。所以最好不要打包到插件的发布包中或是源码中,有三种配置方式:

采用环境变量

        在【run/debug】时配置,设置为jvm参数的模式。

idea插件开发(2)-插件详细配置_第1张图片

采用系统变量

#系统环境变量
signPlugin {
   certificateChain = environment("CERTIFICATE_CHAIN")
   privateKey = environment("PRIVATE_KEY")
   password = environment("PRIVATE_KEY_PASSWORD")
}

publishPlugin {
  token.set(System.getenv("ORG_GRADLE_PROJECT_intellijPublishToken"))
}

或
signPlugin {
  certificateChain.set(providers.environmentVariable("CERTIFICATE_CHAIN"))
  privateKey.set(providers.environmentVariable("PRIVATE_KEY"))
  password.set(providers.environmentVariable("PRIVATE_KEY_PASSWORD"))
}

采用本地文件

#本地文件方式
signPlugin {
  certificateChainFile.set(file("certificate/chain.crt"))
  privateKeyFile.set(file("certificate/private.pem"))
  password.set("8awS22%#3(4wVDDBMlTREX")
}

publishPlugin {
  token.set("perm:a961riC....l17oW8t+Qw==")
}

六、plugin.xml中推荐使用的配置元素

 Plugin Configuration File | IntelliJ Platform Plugin SDK

#idea-plugin基本配置









 国际化资源

  声明与提供的模块不兼容

    
    
    
    
    
    
    
    
        
        
        
        
        
        
        
        
            
            
            
                
            
                
    
        
    
        

    
         为扩展点标记或属性中提供的类名指定所需的父类型


    

    

你可能感兴趣的:(Idea插件开发,intellij-idea,java,ide)