IntelliJ Platform Plugin SDK Help

Bundling Plugin API Sources

If a plugin exposes its own API that is meant to be used by other plugins, it is worth considering bundling the plugin's API sources in the ZIP distribution.

If a third-party plugin uses Gradle IntelliJ Plugin and adds a dependency to the plugin which bundles sources in the ZIP distribution, sources will be automatically attached to the plugin library and visible in IDE when developers navigate to the API classes. Being able to see API sources drastically improves the development experience, and it is highly recommended to bundle them.

API sources location

The API source JARs must be located in the example-plugin.zip!/plugin/lib/src directory in the plugin ZIP distribution, e.g.:

example-plugin.zip └── example-plugin └── lib ├── example-plugin.jar └── src └── example-plugin-api-src.jar

The plugin ZIP can contain multiple source JARs, and there are no strict rules for the source JAR names.

Defining Plugin API

Usually, the following classes are considered as plugin API:

Keep in mind that API should be stable and change very rarely as every incompatible change will break the client plugins. It is also recommended to organize the plugin code in multiple modules with clear responsibilities, e.g.:

  • example-plugin-api - a module containing API

  • example-plugin-impl - a module containing plugin features code that are not meant to be extended or used by client plugins

General rule to define API is to include classes that are likely to be consumed by the client plugins code.

Of course, more complex plugins may require more fine-grained structure. See Gradle IntelliJ Plugin - Usage Examples.

Bundling API Sources in Gradle Build Script

In the simplest case, if a project consists of a single module and plugin API is clearly isolated in a package, e.g. com.example.plugin.openapi, including the source JAR can be achieved by adding the following snippet to the tasks section of the Gradle build script:

tasks { val createOpenApiSourceJar by registering(Jar::class) { // Java sources from(sourceSets.main.get().java) { include("**/com/example/plugin/openapi/**/*.java") } // Kotlin sources from(kotlin.sourceSets.main.get().kotlin) { include("**/com/example/plugin/openapi/**/*.kt") } destinationDirectory.set(layout.buildDirectory.dir("libs")) archiveClassifier.set("src") } buildPlugin { dependsOn(createOpenApiSourceJar) from(createOpenApiSourceJar) { into("lib/src") } } }
task createOpenApiSourceJar(type: Jar) { // Java sources from(sourceSets.main.java) { include '**/com/example/plugin/openapi/**/*.java' } // Kotlin sources from(sourceSets.main.kotlin) { include '**/com/example/plugin/openapi/**/*.kt' } destinationDirectory = layout.buildDirectory.dir('libs') archiveClassifier = 'src' } buildPlugin { dependsOn(createOpenApiSourceJar) from(createOpenApiSourceJar) { into 'lib/src' } }

The above configuration will create a source JAR containing Java and Kotlin source files from the com.example.plugin.openapi package and add it to the final plugin ZIP distribution in the required example-plugin.zip!/example-plugin/lib/src directory.

If your plugin is a Gradle project and there is no clear open API package separation, it is recommended to restructure the plugin project to a Gradle multi-project variant and create a dedicated open API subproject that contains all API sources to be included in the final distribution created by the main plugin Gradle project.

Last modified: 24 November 2022