Skip to content

Instantly share code, notes, and snippets.

@develar
Created November 13, 2020 11:24
Show Gist options
  • Save develar/219f0cd3edab49fb96ba532053f04ec9 to your computer and use it in GitHub Desktop.
Save develar/219f0cd3edab49fb96ba532053f04ec9 to your computer and use it in GitHub Desktop.
plugins.md

InternalIgnoreDependencyViolation

Annotation InternalIgnoreDependencyViolation allows class to be used among various plugins. By default, classloader of extension class must be equal to classloader of plugin where extension is defined. It means that class of extension must be located in a module where corresponding plugin descriptor is located.

Generally, IJ Platform prohibits referencing extension class belonging to plugin1 from the plugin.xml in plugin2. However, sometimes this kind of dependency violation is necessary, in which case the corresponding extension must be annotated with this annotation.

For example:

plugin.xml
  <findUsageHandler implementation="com.plugin1.MyHandler"/>
MyHandler.java
  @InternalIgnoreDependencyViolation
  final class MyHandler {
  }

"Plugin" vs "Module"

Currently, plugin it is entity that consists of one or more IJ IDEA modules. Currently, IJ IDEA module is not reflected in any way in a plugin — only as part of build script, where plugin layout is described. It is going to be changed — IJ Module will be integral part of plugin subsystem. Plugin descriptor will reference all modules that forms its content, and plugin descriptor itself it is a specific form of module descriptor.

So, in the docs below term "plugin" or "module" is used by intention, and it is not sort of error but intended usage.

Every plugin it is a module, but not every module it is a plugin.

The package attribute

The package attribute determines JVM package where all module classes are located. Recursively — com.example implies com.example.sub also.

If package is specified:

  • All plugin optional descriptors must also specify package, and it must be different. For example, if com.example is set for main plugin descriptor, com.example cannot be used for any optional descriptor. Classes referenced by optional descriptors, must be in a different package.
  • Icon class generator uses specified package for icon class but not icons. If you already have icon class, recommended moving existing icon class before running icon class generator to ensure that all references to icon class are updated by IntelliJ IDEA refactoring. Also, icon class generator uses the same icon class name as before if old one is detected in place.
  • Plugin module cannot have module-level libraries. It is technical limitation for time being.

The content element

The content element determines content of the plugin. Plugin consists of modules. Module, where plugin.xml is located, is implicitly added, and you don't have to specify it.

<content>
  <module name="intellij.platform.commercial.verifier" package="com.intellij.ultimate"/>
</content>
Element Minimum Maximum Description
module 0 unbounded A module which should be included.

The only package may be exported by the module, but what if you cannot perform a move refactoring for some reasons? The temporary solution to specify additional package for the current module:

<idea-plugin package="org.jetbrains.plugins.ruby.java">
  <content>
    <!-- a way to specify multiple packages for plugin -->
    <module name="intellij.ruby.java" package="org.jetbrains.plugins.ruby.jruby"/>
  </content>
</idea-plugin>

The content.module element

Attribute Type Use Description
name string required The name of the module.
package string required The package of the module. Duplicates the package specified in the referenced module, but for now it is required for technical reasons.

The module is not added to classpath but just forms plugin content. Still, if some another plugin depends on this plugin,

The dependencies element

The dependencies element determines dependencies of the module.

<dependencies>
  <plugin id="org.jetbrains.plugins.yaml"/>
</dependencies>
Element Minimum Maximum Description
plugin 0 unbounded A plugin upon which a dependency should be added.
module 0 unbounded A module upon which a dependency should be added.

The dependencies.plugin element

Attribute Type Use Description
id string required The id of the plugin.

The dependencies.module element

Attribute Type Use Description
name string required The name of the module.

The module must have descriptor file with the same name as module, e.g. for module intellij.clouds.docker.compose must be a descriptor file intellij.clouds.docker.compose.xml in a module root.

Module dependency is always optional. If module depends on an unavailable plugin, it will be not loaded. In this meaning for now module dependency makes sense only for plugins, but not for modules. It will be changed in the future, when all plugins will act as a module.

The module added to classpath of dependent module but dependency itself is not able to access the dependent module (as it was earlier). Currently, it is packaged into the same JAR, but packaging it is implementation details that are hidden and maybe changed in any moment or maybe different in a different execution environment. The same classloader configuration is guaranteed, but not packaging, and independence from packaging it is a one of the goal of a new descriptor format.

In the old plugin descriptor format:

  • tag depends without config-file it is dependency.module.
  • tag depends with optional it is content.module.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment