IDEA Plug-Ins

Purpose

Plug-ins are the only possible way for third-parties to extend IDEA functionality. Every plug-in uses API exposed by IDEA or other plug-ins to implement its functionality. This document is focused on plug-in system architecture and plug-in lifecycle. It doesn’t specify any of the other APIs which may be used by plug-ins.

Plug-In Content

There are 3 ways how to organize plug-in content:

1. Plug-in consists of one .jar file placed in IDEA_HOME/plugins/. The archive should contain configuration file (META-INF/plugin.xml) and classes which implement the plug-in functionality. Configuration file specifies plug-in name, description, version, vendor, IDEA version plug-in is supposed to be used with, plug-in components, actions and action groups, action user interface placement.

IDEA_HOME
Plugins Sample.jar/ com/foo/..... ... ... META-INF plugin.xml


2. Plug-in files are located in a folder:

IDEA_HOME
Plugins Sample lib libfoo.jar libbar.jar classes com/foo/..... ... ... META-INF plugin.xml

The 'classes' folder and all jars located in the 'lib' folder are automatically added to the classpath.

3. Plug-in files are located in a jar-file which is placed to the lib folder:

IDEA_HOME
Plugins Sample lib libfoo.jar libbar.jar Sample.jar/ com/foo/..... ... ... META-INF plugin.xml

All the jars from 'lib' folder are automatically added to the classpath.

Plug-In Components

Components are the fundamental concept of plug-ins integration. There are 2 kinds of components: application-level and project-level. Application-level components are created and initialised on IDEA start-up. Project-level components are created for each Project instance present in IDEA (please note that components might be created for even unopened projects). Application-level component can be acquired from Application instance with getComponent(Class) method. Project-level component can be acquired from Project instance with getComponent(Class) method.

Every component should have interface and implementation classes specified in the configuration file. The interface class will be used for retrieving the component from other components and the implementation class will be used for component instantiation. Note that two components of the same level (Application or Project) cannot have the same interface class. Interface and implementation classes can be the same.

Each component has the unique name which is used for its externalization and other internal needs. The name of component is returned by its getComponentName() method.

Components Naming Notation

It's recommended to name components in plugin_name.component_name form.

Application Level Components

Application-level component's implementation class should implement the ApplicationComponent interface. It should have constructor with no parameters which will be used for its instantiation.

Project Level Components

Project-level component's implementation class should implement the ProjectComponent interface. It should have constructor with a single parameter of Project type or with no parameters. If a component needs Project instance it should provide constructor of the first form and store its parameter into a field for later use.

Plug-In Components Configuration

Every component’s state will be automatically saved & loaded if component implements JDOMExternalizable interface.
Application-level component's state is saved in the xml file with plug-in’s name in IDEA_HOME/config/plugins folder.
Project-level component saves its state to the project (.ipr) file. If workspace option in the plugin.xml is set to true component will save its configuration to the workspace (.iws) file instead of project (.ipr) file.
Note that component should always be ready to save its state.

Defaults

Defaults (components' predefined settings) should be placed in the component_name.xml file. Put this file in the plug-in's classpath in the folder corresponding to the default package. readExternal() method will be called on the <component> root tag. If component has defaults readExternal method is called twice: the first time for defaults and the second time for saved configuration.

Plug-In Components Lifecycle

Component lifecycle:

Note that you should not request any other components in the constructor of your component, otherwise you'll get an assertion. If you need access to other components when initializing your component you can access them in the initComponent method.

Plug-In Actions

Each plug-in can contribute a number of actions to the IDEA user interface. Normally all actions are specified in the configuration file. The configuration file also specifies action placement in UI. Plug-in vendor can place actions into the main menu, pop-up menus or the toolbar. See actions.html for the detailed description.

Plug-In Configuration (plugin.xml)

Here is a sample plugin.xml:

<idea-plugin>
    
    <!-- Plug-in name -->
    <name>VssIntegration</name>
    
    <!-- Description -->
    <description>Vss integration plug-in</description>
    
    <!-- Plug-in version -->
    <version>1.0</version>
    
    <!-- Plug-in's vendor -->
    <vendor>Foo Inc.</vendor>
    
    <!-- Minimum and maximum IDEA version plug-in is supposed to work with -->
    <idea-version min=”3.0” max=”3.1”/>    
    
    <!-- Plug-in's application components -->
    <application-components>
        <component>
            <!-- Component's interface  class -->
            <interface-class>com.foo.Component1Interface</interface-class>
            <!-- Component's implementation class -->
            <implementation-class>com.foo.impl.Component1Impl</implementation-class>
        </component>
    </application-components>
    
    <!-- Plug-in's project components -->
    <project-components>
        <component>
            <!-- Interface and implementation classes are the same -->
            <interface-class>com.foo.Component2</interface-class>
            <!-- Save state to the .iws instead of .ipr -->
            <option name="workspace" value="true" />            
        </component>
    </project-components>
    
    <!-- Actions -->
    <actions>    
        <action id="VssIntegration.GarbageCollection" class="com.foo.impl.CoolectGarbage" text="Collect _Garbage" description="Run garbage collector">
            <keyboard-shortcut first-keystroke="control alt G" second-keystroke="C" keymap="$default"/>
        </action>
    </actions>
    
</idea-plugin>