Merge branch 'master' into IJSDK-690

# Conflicts:
#	basics/action_system.md
This commit is contained in:
JohnHake 2019-12-05 19:42:23 -08:00
commit bc3b21c4b7
20 changed files with 292 additions and 371 deletions

View File

@ -33,10 +33,12 @@
* [Plugin Structure](basics/plugin_structure.md)
* [Plugin Content](basics/plugin_structure/plugin_content.md)
* [Plugin Class Loaders](basics/plugin_structure/plugin_class_loaders.md)
* [Plugin Components](basics/plugin_structure/plugin_components.md)
* [Plugin Services](basics/plugin_structure/plugin_services.md)
* [Plugin Extensions and Extension Points](basics/plugin_structure/plugin_extensions_and_extension_points.md)
* [Plugin Actions](basics/plugin_structure/plugin_actions.md)
* [Plugin Extensions](basics/plugin_structure/plugin_extensions.md)
* [Plugin Services](basics/plugin_structure/plugin_services.md)
* [Plugin Listeners](basics/plugin_structure/plugin_listeners.md)
* [Plugin Extension Points](basics/plugin_structure/plugin_extension_points.md)
* [Plugin Components](basics/plugin_structure/plugin_components.md)
* [Plugin Configuration File](basics/plugin_structure/plugin_configuration_file.md)
* [Plugin Logo (Icon)](basics/plugin_structure/plugin_icon_file.md)
* [Plugin Dependencies](basics/plugin_structure/plugin_dependencies.md)

View File

@ -145,62 +145,7 @@ To register an action from code, two steps are required.
* First, an instance of the class derived from `AnAction` must be passed to the `registerAction()` method of [`com.intellij.openapi.actionSystem.ActionManager`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionManager.java), to associate the action with an ID.
* Second, the action needs to be added to one or more groups.
To get an instance of an action group by ID, it is necessary to call `ActionManager.getAction()` and cast the returned value to [`com.intellij.openapi.actionSystem.DefaultActionGroup`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java).
You can create a plugin that registers actions on IDEA startup using the following procedure.
#### Register an Action on Idea Startup
* Create a new class that implements the [`com.intellij.openapi.components.ApplicationComponent`](upsource:///platform/core-api/src/com/intellij/openapi/components/ApplicationComponent.java) interface.
* In this class, override the `ActionComponent.getComponentName()`, `initComponent()`, and `disposeComponent()` methods.
* Register this class in the `<application-components>` section of the `plugin.xml` file.
To clarify the above procedure, consider the following sample Java class `MyPluginRegistration` that registers an action defined in a custom `TextBoxes` class and adds a new menu command to the **Window** menu group on the main menu:
```java
public class MyPluginRegistration implements ApplicationComponent {
// Returns the component name (any unique string value).
@NotNull public String getComponentName() {
return "MyPlugin";
}
// If you register the MyPluginRegistration class in the <application-components> section of
// the plugin.xml file, this method is called on IDEA start-up.
public void initComponent() {
ActionManager am = ActionManager.getInstance();
TextBoxes action = new TextBoxes();
// Passes an instance of your custom TextBoxes class to the registerAction method of the ActionManager class.
am.registerAction("MyPluginAction", action);
// Gets an instance of the WindowMenu action group.
DefaultActionGroup windowM = (DefaultActionGroup) am.getAction("WindowMenu");
// Adds a separator and a new menu command to the WindowMenu group on the main menu.
windowM.addSeparator();
windowM.add(action);
}
// Disposes system resources.
public void disposeComponent() {
}
}
```
Note, that the sample `TextBoxes` class is further described in [Creating an Action](/basics/getting_started/creating_an_action.md).
#### Declare the Action Registration Component
To ensure that your plugin is initialized on IDEA start-up, make the following changes to the `<application-components>` section of the `plugin.xml` file:
```xml
<application-components>
<!-- Add your application components here -->
<component>
<implementation-class>MypackageName.MyPluginRegistration</implementation-class>
</component>
</application-components>
```
To get an instance of an action group by ID, it is necessary to call `ActionManager.getAction()` and cast the returned value to [`com.intellij.openapi.actionSystem.DefaultActionGroup`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java).
## Building UI from Actions

View File

@ -6,9 +6,11 @@ Click the following topics to learn more about the plugin system structure and p
* [Plugin Content](plugin_structure/plugin_content.md)
* [Plugin Class Loaders](plugin_structure/plugin_class_loaders.md)
* [Plugin Components](plugin_structure/plugin_components.md)
* [Plugin Extensions and Extension Points](plugin_structure/plugin_extensions_and_extension_points.md)
* [Plugin Extensions](plugin_structure/plugin_extensions.md)
* [Plugin Listeners](plugin_structure/plugin_listeners.md)
* [Plugin Actions](plugin_structure/plugin_actions.md)
* [Plugin Services](plugin_structure/plugin_services.md)
* [Plugin Extension Points](plugin_structure/plugin_extension_points.md)
* [Plugin Components](plugin_structure/plugin_components.md)
* [Plugin Configuration File](plugin_structure/plugin_configuration_file.md)
* [Plugin Dependencies](plugin_structure/plugin_dependencies.md)

View File

@ -4,4 +4,7 @@ title: Plugin Actions
The *IntelliJ Platform* provides the concept of _actions_. An action is a class, derived from the [`AnAction`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java) class, whose `actionPerformed` method is called when the menu item or toolbar button is selected.
The system of actions allows plugins to add their own items to IDEA menus and toolbars. Actions are organized into groups, which, in turn, can contain other groups. A group of actions can form a toolbar or a menu. Subgroups of the group can form submenus of a menu. You can find detailed information on how to create and register your actions in the [IntelliJ Platform Action System](/basics/action_system.md).
Actions are the most common way for a user to invoke the functionality of your plugin. An action can be invoked from
a menu or a toolbar, using a keyboard shortcut, or from the Find Action interface.
Actions are organized into groups, which, in turn, can contain other groups. A group of actions can form a toolbar or a menu. Subgroups of the group can form submenus of a menu. You can find detailed information on how to create and register your actions in the [IntelliJ Platform Action System](/basics/action_system.md).

View File

@ -2,85 +2,26 @@
title: Plugin Components
---
> **TIP** Due to performance considerations, please consider using [Services](plugin_services.md) instead whenever possible.
> **WARNING** When writing new plugins, you should avoid creating components, and you should migrate existing components in your plugins to services, extensions or listeners (see below).
Components are the fundamental concept of plugin integration. There are three kinds of components:
Plugin components are a legacy feature supported for compatibility with plugins created for older versions of the
IntelliJ Platform. Plugins using components do not support dynamic loading (the ability to install, update and
uninstall plugins without restarting the IDE).
* **Application level components** are created and initialized when your IDE starts up. They can be acquired from the [`Application`](upsource:///platform/core-api/src/com/intellij/openapi/application/Application.java) instance by using the `getComponent(Class)` method.
* **Project level components** are created for each [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java) instance in the IDE. (Please note that components may be created even for unopened projects.) They can be acquired from the `Project` instance by using the `getComponent(Class)` method.
* **Module level components** are created for each [`Module`](upsource:///platform/core-api/src/com/intellij/openapi/module/Module.java) inside every project loaded in the IDE.
Module level components can be acquired from a `Module` instance with the `getComponent(Class)` method.
Plugin components are defined using `<application-components>`, `<project-components>` and `<module-components>`
tags in a `plugin.xml` file.
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.
To migrate your code from components to more modern APIs, please use the following guidelines:
Note that two components of the same level ([`Application`](upsource:///platform/core-api/src/com/intellij/openapi/application/Application.java), [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java) or [`Module`](upsource:///platform/core-api/src/com/intellij/openapi/module/Module.java)) cannot have the same interface class. The same class may be specified for both interface and Implementation.
Each component has a unique name which is used for its externalization and other internal needs. The name of a component is returned by its `getComponentName()` method.
## Components naming notation
It is recommended to name components in the form `<plugin_name>.<component_name>`.
## Application level components
An application component that has no dependencies should have a constructor with no parameters which will be used for its instantiation. If an application component depends on other application components, it can specify these components as constructor parameters. The *IntelliJ Platform* will ensure that the components are instantiated in the correct order to satisfy the dependencies.
Application level components must be registered in the `<application-components>` section of the plugin.xml file (see [Plugin Configuration File](plugin_configuration_file.md)).
## Project level components
Optionally, a project level component's implementation class may implement the [`ProjectComponent`](upsource:///platform/core-api/src/com/intellij/openapi/components/ProjectComponent.java) interface.
The constructor of a project level component can have a parameter of the [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java) type, if it needs the project instance. It can also specify other application-level or project-level components as parameters, if it depends on those components.
Project level components must be registered in the `<project-components>` section of the `plugin.xml` file (see [Plugin Configuration File](plugin_configuration_file.md)).
## Module level components
Optionally, a module level component's implementation class may implement the [`ModuleComponent`](upsource:///platform/projectModel-api/src/com/intellij/openapi/module/ModuleComponent.java) interface.
The constructor of a module level component can have a parameter of the Module type, if it needs the module instance. It can also specify other application level, project level or module level components as parameters, if it depends on those components.
Module level components must be registered in the `<module-components>` section of the `plugin.xml` file (see [Plugin Configuration File](plugin_configuration_file.md)).
## Persisting the state of components
The state of every component will be automatically saved and loaded if the component's class implements the [`JDOMExternalizable`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) (deprecated) or [PersistentStateComponent](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) interface.
When the component's class implements the [`PersistentStateComponent`](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) interface, the component state is saved in an XML file that you can specify using the [@State](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/State.java) and [@Storage](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/Storage.java) annotations in your Java code.
When the component's class implements the [`JDOMExternalizable`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) interface, the components save their state in the following files:
* Project level components save their state to the project (`.ipr`) file.
However, if the workspace option in the `plugin.xml` file is set to `true`, the component saves its configuration to the workspace (`.iws`) file instead.
* Module level components save their state to the module (`.iml`) file.
For more information and samples, refer to [Persisting State of Components](/basics/persisting_state_of_components.md).
## Defaults
The defaults (a component's predefined settings) should be placed in the `<component_name>.xml` file. Place this file in the plugin's classpath in the folder corresponding to the default package. The `readExternal()` method will be called on the `<component>` root tag.
If a component has defaults, the `readExternal()` method is called twice:
* The first time for defaults
* The second time for saved configuration
## Plugin components lifecycle
The components are loaded in the following order:
* Creation - constructor is invoked.
* Initialization - the `initComponent` method is invoked (if the component implements the [`BaseComponent`](upsource:///platform/extensions/src/com/intellij/openapi/components/BaseComponent.java) interface).
* Configuration - the `readExternal` method is invoked (if the component implements [`JDOMExternalizable`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) interface), or the `loadState` method is invoked (if the component implements [PersistentStateComponent](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) and has non-default persisted state).
* For module components, the `moduleAdded` method of the [`ModuleComponent`](upsource:///platform/projectModel-api/src/com/intellij/openapi/module/ModuleComponent.java) interface is invoked to notify that a module has been added to the project.
* For project components, the `projectOpened` method of the [`ProjectComponent`](upsource:///platform/core-api/src/com/intellij/openapi/components/ProjectComponent.java) interface is invoked to notify that a project has been loaded.
The components are unloaded in the following order:
* Saving configuration - the `writeExternal` method is invoked (if the component implements the [`JDOMExternalizable`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) interface), or the `getState` method is invoked (if the component implements PersistentStateComponent).
* Disposal - the `disposeComponent` method is invoked.
Note that you should not request any other components using the `getComponent()` method 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 specify them as constructor parameters or access them in the `initComponent` method.
* To manage some state or logic that is only needed when the user performs a specific operation,
use a [Service](plugin_services.md).
* To store the state of your plugin at the application or project level, use a [Service](plugin_services.md)
and implement the `PersistentStateComponent` interface. See [Persisting State of Components](/basics/persisting_state_of_components.md) for details.
* To subscribe to events, use a [listener](plugin_listeners.md) or create an [extension](plugin_extensions.md) for a dedicated extension point (for example, `com.intellij.editorFactoryListener`) if one exists for the event you need to subscribe to.
* Executing code on application startup should be avoided whenever possible because it slows down startup.
Plugin code should only be executed when projects are opened or when the user invokes an action of your plugin. If you can't avoid this, create
an [extension](plugin_extensions.md) for the `com.intellij.appLifecycleListener` extension point.
* To execute code when a project is being opened, provide [StartupActivity](upsource:///platform/core-api/src/com/intellij/openapi/startup/StartupActivity.java) implementation and register an [extension](plugin_extensions.md) for the `com.intellij.postStartupActivity` or `com.intellij.backgroundPostStartupActivity` extension point (the latter is supported starting with version 2019.3 of the platform).
* To execute code on project closing or application shutdown, implement the `Disposable` interface in a [Service](plugin_services.md)
and place the code in the `dispose()` method, or use `Disposer.register()` passing a `Project` or `Application` instance
as the `parent` argument.

View File

@ -72,7 +72,7 @@ Allowed HTML elements include text formatting, paragraphs, and lists.
`action.[pluginID].[ActionID].text` -->
<resource-bundle>messages.MyPluginBundle</resource-bundle>
<!-- Plugin's application components -->
<!-- Plugin's application components (note that components are deprecated and should not be used in new plugins) -->
<application-components>
<component>
<!-- Component's interface class -->
@ -83,7 +83,7 @@ Allowed HTML elements include text formatting, paragraphs, and lists.
</component>
</application-components>
<!-- Plugin's project components -->
<!-- Plugin's project components (note that components are deprecated and should not be used in new plugins) -->
<project-components>
<component>
<!-- Interface and implementation classes are the same -->
@ -101,7 +101,7 @@ Allowed HTML elements include text formatting, paragraphs, and lists.
</component>
</project-components>
<!-- Plugin's module components -->
<!-- Plugin's module components (note that components are deprecated and should not be used in new plugins) -->
<module-components>
<component>
<implementation-class>com.foo.Component3</implementation-class>
@ -133,8 +133,18 @@ Allowed HTML elements include text formatting, paragraphs, and lists.
tag matches the name of the extension point, and the
"implementation" class specifies the name of the class
added to the extension point. -->
<extensions xmlns="VssIntegration">
<extensions defaultExtensionNs="VssIntegration">
<testExtensionPoint implementation="com.foo.impl.MyExtensionImpl"/>
</extensions>
<!-- Application-level listeners -->
<applicationListeners>
<listener class="com.foo.impl.MyListener" topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/>
</applicationListeners>
<!-- Project-level listeners -->
<projectListeners>
<listener class="com.foo.impl.MyToolwindowListener" topic="com.intellij.openapi.wm.ex.ToolWindowManagerListener"/>
</projectListeners>
</idea-plugin>
```

View File

@ -0,0 +1,56 @@
---
title: Plugin Extension Points
---
> **NOTE** See [Plugin Extensions](plugin_extensions.md) for _using_ extension points in your plugin.
By defining _extension points_ in your plugin, you can allow other plugins to extend the functionality of your plugin.
There are two types of extension points:
* _Interface_ extension points allow other plugins to extend your plugins with _code_. When you define an interface
extension point, you specify an interface, and other plugins will provide classes implementing that interface.
You'll then be able to invoke methods on those interfaces.
* _Bean_ extension points allow other plugins to extend your plugins with _data_. You specify the fully qualified
name of an extension class, and other plugins will provide data which will be turned into instances of that class.
## How to declare extension points
You can declare extensions and extension points in the plugin configuration file `plugin.xml`, within the `<extensions>` and `<extensionPoints>` sections, respectively.
To declare extension points in your plugin, add an `<extensionPoints>` section to your `plugin.xml`. Then insert a child element `<extensionPoint>` that defines the extension point name and the name of a bean class or an interface that is allowed to extend the plugin functionality in the `name`, `beanClass` and `interface` attributes, respectively.
```xml
<extensionPoints>
<extensionPoint name="myExtensionPoint1" beanClass="com.myplugin.MyBeanClass">
<extensionPoint name="myExtensionPoint2" interface="com.myplugin.MyInterface">
</extensionPoints>
```
* The `beanClass` attribute sets a bean class that specifies one or several properties annotated with the [`@Attribute`](upsource:///platform/util/src/com/intellij/util/xmlb/annotations/Attribute.java) annotation.
* The `interface` attribute sets an interface the plugin that contributes to the extension point must implement.
The plugin that contributes to the extension point will read those properties from the `plugin.xml` file.
To clarify this, consider the following sample `MyBeanClass` bean class used in the above `plugin.xml` file:
```java
public class MyBeanClass extends AbstractExtensionPointBean {
@Attribute("key")
public String key;
@Attribute("implementationClass")
public String implementationClass;
public String getKey() {
return key;
}
public String getClass() {
return implementationClass;
}
}
```
To declare an extension designed to access the `myExtensionPoint1` extension point, your `plugin.xml` file must contain the `<myExtensionPoint1>` tag with the `key` and `implementationClass` attributes set to appropriate values.
> **TIP** See [Extension properties code insight](plugin_extensions.md#extension-properties-code-insight) on how to provide smart completion/validation.

View File

@ -0,0 +1,88 @@
---
title: Plugin Extensions
redirect_from:
/basics/plugin_structure/plugin_extensions_and_extension_points.html
---
_Extensions_ are the most common way for a plugin to extend the functionality of the IntelliJ Platform in a way
that is not as straightforward as adding an action to a menu or toolbar. The following are some of the most common
tasks accomplished using extensions:
* The `com.intellij.toolWindow` extension point allows plugins to add [tool windows](/user_interface_components/tool_windows.md)
(panels displayed at the sides of the IDE user interface);
* The `com.intellij.applicationConfigurable` and `com.intellij.projectConfigurable` extension points allow plugins to add pages to the
Settings/Preferences dialog;
* [Custom language plugins](/reference_guide/custom_language_support.md) use many extension points
to extend various language support features in the IDE.
There are [more than 1000 extension](#how-to-get-the-extension-points-list) points available in the platform and the bundled plugins, allowing to customize
different parts of the IDE behavior.
## Declaring Extensions
> **TIP** Auto-completion is available for all these steps.
1. Add an `<extensions>` element to your plugin.xml if it's not yet present there. Set the `defaultExtensionNs` attribute to one of the following values:
* `com.intellij`, if your plugin extends the IntelliJ Platform core functionality.
* `{ID of a plugin}`, if your plugin extends a functionality of another plugin.
2. Add a new child element to the `<extensions>` element. The child element name must match the name of the extension point you want the extension to access.
3. Depending on the type of the extension point, do one of the following:
* If the extension point was declared using the `interface` attribute, for newly added child element, set the `implementation` attribute to the name of the class that implements the specified interface.
* If the extension point was declared using the `beanClass` attribute, for newly added child element, set all attributes annotated with the [`@Attribute`](upsource:///platform/util/src/com/intellij/util/xmlb/annotations/Attribute.java) annotations in the specified bean class.
To clarify this procedure, consider the following sample section of the `plugin.xml` file that defines two extensions designed to access the `com.intellij.appStarter` and `com.intellij.projectTemplatesFactory` extension points in the *IntelliJ Platform* and one extension to access the `another.plugin.myExtensionPoint` extension point in another plugin `another.plugin`:
```xml
<!-- Declare extensions to access extension points in the IntelliJ Platform.
These extension points have been declared using "interface".
-->
<extensions defaultExtensionNs="com.intellij">
<appStarter implementation="com.myplugin.MyAppStarter" />
<projectTemplatesFactory implementation="com.myplugin.MyProjectTemplatesFactory" />
</extensions>
<!-- Declare extensions to access extension points in a custom plugin "another.plugin"
The "myExtensionPoint" extension point has been declared using "beanClass"
and exposes custom properties "key" and "implementationClass".
-->
<extensions defaultExtensionNs="another.plugin">
<myExtensionPoint key="keyValue" implementationClass="com.myplugin.MyExtensionPointImpl" />
</extensions>
```
### Extension default properties
The following properties are available always:
- `id` - unique ID
- `order` - allows to order all defined extensions using `first`, `last` or `before|after [id]` respectively
- `os` - allows to restrict extension to given OS, e.g., `os="windows"` registers the extension on Windows only
### Extension properties code insight
Several tooling features are available to help configuring bean class extension points in `plugin.xml`.
Property names matching the following list will resolve to FQN:
- `implementation`
- `className`
- `serviceInterface` / `serviceImplementation`
- ending with `Class` (case-sensitive)
A required parent type can be specified in the extension point declaration via nested `<with>`:
```xml
<extensionPoint name="myExtension" beanClass="MyExtensionBean">
<with attribute="psiElementClass" implements="com.intellij.psi.PsiElement"/>
</extensionPoint>
```
Property name `language` will automatically resolve to all present `Language` IDs.
Specifying `@org.jetbrains.annotations.Nls` verifies capitalization of UI text properties according to given `capitalization` value (2019.2 and later).
## How to get the extension points list?
To get a list of extension points available in the *IntelliJ Platform* core, consult the `<extensionPoints>` section of the following XML configuration files:
* [`LangExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/LangExtensionPoints.xml)
* [`PlatformExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml)
* [`VcsExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/VcsExtensionPoints.xml)

View File

@ -1,125 +0,0 @@
---
title: Plugin Extensions and Extension Points
---
The *IntelliJ Platform* provides the concept of _extensions_ and _extension points_ that allows a plugin to interact with other plugins or with the IDE itself.
## Extension points
If you want your plugin to allow other plugins to extend its functionality, in the plugin, you must declare one or several _extension points_. Each extension point defines a class or an interface that is allowed to access this point.
## Extensions
If you want your plugin to extend the functionality of other plugins or the *IntelliJ Platform*, you must declare one or several _extensions_.
## How to declare extensions and extension points
You can declare extensions and extension points in the plugin configuration file `plugin.xml`, within the `<extensions>` and `<extensionPoints>` sections, respectively.
**To declare an extension point**
In the `<extensionPoints>` section, insert a child element `<extensionPoint>` that defines the extension point name and the name of a bean class or an interface that is allowed to extend the plugin functionality in the `name`, `beanClass` and `interface` attributes, respectively.
To clarify this procedure, consider the following sample section of the plugin.xml file:
```xml
<extensionPoints>
<extensionPoint name="MyExtensionPoint1" beanClass="MyPlugin.MyBeanClass1">
<extensionPoint name="MyExtensionPoint2" interface="MyPlugin.MyInterface">
</extensionPoints>
```
* The `interface` attribute sets an interface the plugin that contributes to the extension point must implement.
* The `beanClass` attribute sets a bean class that specifies one or several properties annotated with the [`@Attribute`](upsource:///platform/util/src/com/intellij/util/xmlb/annotations/Attribute.java) annotation.
The plugin that contributes to the extension point will read those properties from the `plugin.xml` file.
To clarify this, consider the following sample `MyBeanClass1` bean class used in the above `plugin.xml` file:
```java
public class MyBeanClass1 extends AbstractExtensionPointBean {
@Attribute("key")
public String key;
@Attribute("implementationClass")
public String implementationClass;
public String getKey() {
return key;
}
public String getClass() {
return implementationClass;
}
}
```
To declare an extension designed to access the `MyExtensionPoint1` extension point, your `plugin.xml` file must contain the `<MyExtensionPoint1>` tag with the `key` and `implementationClass` attributes set to appropriate values (see sample below).
**To declare an extension**
> **TIP** Auto-completion is available for all these steps.
1. For the `<extensions>` element, set the `defaultExtensionNs` attribute to one of the following values:
* `com.intellij`, if your plugin extends the IntelliJ Platform core functionality.
* `{ID of a plugin}`, if your plugin extends a functionality of another plugin.
2. Add a new child element to the `<extensions>` element. The child element name must match the name of the extension point you want the extension to access.
3. Depending on the type of the extension point, do one of the following:
* If the extension point was declared using the `interface` attribute, for newly added child element, set the `implementation` attribute to the name of the class that implements the specified interface.
* If the extension point was declared using the `beanClass` attribute, for newly added child element, set all attributes annotated with the [`@Attribute`](upsource:///platform/util/src/com/intellij/util/xmlb/annotations/Attribute.java) annotations in the specified bean class.
To clarify this procedure, consider the following sample section of the `plugin.xml` file that defines two extensions designed to access the `appStarter` and `applicationConfigurable` extension points in the *IntelliJ Platform* and one extension to access the `MyExtensionPoint1` extension point in a test plugin:
```xml
<!-- Declare extensions to access extension points in the IntelliJ Platform.
These extension points have been declared using the "interface" attribute.
-->
<extensions defaultExtensionNs="com.intellij">
<appStarter implementation="MyTestPackage.MyTestExtension1" />
<applicationConfigurable implementation="MyTestPackage.MyTestExtension2" />
</extensions>
<!-- Declare extensions to access extension points in a custom plugin
The MyExtensionPoint1 extension point has been declared using *beanClass* attribute.
-->
<extensions defaultExtensionNs="MyPluginID">
<MyExtensionPoint1 key="keyValue" implementationClass="MyTestPackage.MyClassImpl"></MyExtensionPoint1>
</extensions>
```
### Extension default properties
The following properties are available always:
- `id` - unique ID
- `order` - allows to order all defined extensions using `first`, `last` or `before|after [id]` respectively
- `os` - allows to restrict extension to given OS, e.g., `os="windows"` registers the extension on Windows only
### Extension properties code insight
Several tooling features are available to help configuring bean class extension points in `plugin.xml`.
Property names matching the following list will resolve to FQN:
- `implementation`
- `className`
- `serviceInterface` / `serviceImplementation`
- ending with `Class` (case-sensitive)
A required parent type can be specified in the extension point declaration via nested `<with>`:
```xml
<extensionPoint name="myExtension" beanClass="MyExtensionBean">
<with attribute="psiElementClass" implements="com.intellij.psi.PsiElement"/>
</extensionPoint>
```
Property name `language` will automatically resolve to all present `Language` IDs.
Specifying `@org.jetbrains.annotations.Nls` verifies capitalization of UI text properties according to given `capitalization` value (2019.2 and later).
## How to get the extension points list?
To get a list of extension points available in the *IntelliJ Platform* core, consult the `<extensionPoints>` section of the following XML configuration files:
* [`LangExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/LangExtensionPoints.xml)
* [`PlatformExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml)
* [`VcsExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/VcsExtensionPoints.xml)

View File

@ -0,0 +1,90 @@
---
title: Plugin Listeners
---
> **NOTE** Defining listeners in `plugin.xml` is supported starting with the version 2019.3 of the platform.
_Listeners_ allow plugins to declaratively subscribe to events delivered through the
[message bus](/reference_guide/messaging_infrastructure.md). You can define both application- and project-level
listeners.
Declarative registration of listeners allows you to achieve better performance compared to registering listeners
from code, because listener instances are created lazily (the first time an event is sent to the topic), and not
during application startup or project opening.
## Defining Application-Level Listeners
To define an application-level listener, add the following section to your `plugin.xml`:
```xml
<applicationListeners>
<listener class="myPlugin.MyListenerClass" topic="BaseListenerInterface"/>
</applicationListeners>
```
The `topic` attribute specifies the listener interface corresponding to the type of events you want to receive.
Normally, this is the interface used as the type parameter of the `Topic` instance for the type of events.
The `class` attribute specifies the class in your plugin that implements the listener interface and receives
the events.
As a specific example, if you want to receive events about all changes in the virtual file system, you need
to implement the `BulkFileListener` interface, corresponding to the topic `VirtualFileManager.VFS_CHANGES`.
To subscribe to this topic from code, you could use something like the following snippet:
```java
messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
// handle the events
}
});
```
To use declarative registration, you no longer need to reference the `Topic` instance. Instead, you refer directly
to the listener interface class:
```xml
<applicationListeners>
<listener class="myPlugin.MyVfsListener" topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/>
</applicationListeners>
```
Then you provide the listener implementation as a top-level class:
```java
public class MyVfsListener implements BulkFileListener {
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
// handle the events
}
}
```
## Defining Project-level Listeners
Project-level listeners are registered in the same way, except that the top-level tag is
`<projectListeners>`. They can be used to listen to project-level events, for example, tool window operations:
```xml
<projectListeners>
<listener class="MyToolwindowListener" topic="com.intellij.openapi.wm.ex.ToolWindowManagerListener" />
</projectListeners>
```
The class implementing the listener interface can define a one-argument constructor accepting a `Project`,
and it will receive the instance of the project for which the listener is created:
```java
public class MyToolwindowListener implements ToolWindowManagerListener {
private final Project project;
public MyToolwindowListener(Project project) {
this.project = project;
}
@Override
public void stateChanged() {
// handle the state change
}
}
```

View File

@ -28,31 +28,6 @@
<!-- Resource bundle from which the text of plugin descriptions, action names and etc. will be loaded -->
<resource-bundle>org.jetbrains.tutorials.sample.PluginSampleBundle</resource-bundle>
<!-- Plugin's application components -->
<application-components>
<component>
<!-- Component's interface class -->
<interface-class>org.jetbrains.tutorials.sample.DummyApplicationComponent</interface-class>
<!-- Component's implementation class -->
<implementation-class>org.jetbrains.tutorials.sample.DummyApplicationComponentImpl</implementation-class>
</component>
</application-components>
<!-- Plugin's project components -->
<project-components>
<component>
<!-- Interface and implementation classes are the same -->
<interface-class>org.jetbrains.tutorials.sample.DummyProjectComponent</interface-class>
<implementation-class>org.jetbrains.tutorials.sample.DummyProjectComponentImpl</implementation-class>
<!-- If the "workspace" option is set "true", the component saves its state to the .iws file
instead of the .ipr file. Note that the <option> element is used only if the component implements the JDOMExternalizable interface. Otherwise, the use of the <option> element takes no effect.-->
<option name="workspace" value="true"/>
<!-- If the "loadForDefaultProject" tag is present, the project component is instantiated also for the default project. -->
<loadForDefaultProject/>
</component>
</project-components>
<!-- Actions -->
<actions>
<!-- The <action> element defines an action to register.

View File

@ -1,9 +0,0 @@
package org.jetbrains.tutorials.sample;
import com.intellij.openapi.components.BaseComponent;
/**
* @author Anna Bulenkova
*/
interface DummyApplicationComponent extends BaseComponent {
}

View File

@ -1,24 +0,0 @@
package org.jetbrains.tutorials.sample;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class DummyApplicationComponentImpl implements DummyApplicationComponent {
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
}
@NotNull
@Override
public String getComponentName() {
return "DummyApplicationComponent";
}
}

View File

@ -1,9 +0,0 @@
package org.jetbrains.tutorials.sample;
import com.intellij.openapi.components.ProjectComponent;
/**
* @author Anna Bulenkova
*/
public interface DummyProjectComponent extends ProjectComponent {
}

View File

@ -1,34 +0,0 @@
package org.jetbrains.tutorials.sample;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class DummyProjectComponentImpl implements DummyProjectComponent {
@Override
public void projectOpened() {
}
@Override
public void projectClosed() {
}
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
}
@NotNull
@Override
public String getComponentName() {
return "DummyProjectComponent";
}
}

1
faq.md
View File

@ -130,6 +130,7 @@ This FAQ is a topical index of questions that have been asked (and answered) on
* [How do I provide syntax and error highlighting in a combo box editor?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206800495-EditorTextField-in-3403-How-to-get-an-Editor-that-does-error-highlighting-)
* [How can I get notified when my tool window is activated?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206800405-How-can-i-run-some-code-when-a-ToolWindow-activates)
* [How can I provide Close and Rerun buttons in my Usage View window?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206146779-How-to-get-a-Close-button-in-an-own-Usage-View-)
* [How can I display the SDK list in a JComboBox?](https://stackoverflow.com/questions/51499884/how-to-display-the-sdk-list-in-a-jcombobox)
## General
* [How do I get the currently active project outside of an AnAction?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206763335-Getting-active-project-)

View File

@ -24,6 +24,7 @@ The following problem patterns are supported:
<class name>.<method name>(<human-readable parameters>) method visibility changed from <before> to <after>
<class name>.<method name>(<human-readable parameters>) method marked final
<class name> (class|interface) now (extends|implements) <class name> and inherits its final method <method name>(<human-readable parameters>)?
<class name> (class|interface) now (extends|implements) <class name> and inherits its abstract method <method name>(<human-readable parameters>)?
<class name>(<human-readable parameters>) constructor removed
<class name>(<human-readable parameters>) constructor parameter <type> removed

View File

@ -24,6 +24,7 @@ The following problem patterns are supported:
<class name>.<method name>(<human-readable parameters>) method visibility changed from <before> to <after>
<class name>.<method name>(<human-readable parameters>) method marked final
<class name> (class|interface) now (extends|implements) <class name> and inherits its final method <method name>(<human-readable parameters>)?
<class name> (class|interface) now (extends|implements) <class name> and inherits its abstract method <method name>(<human-readable parameters>)?
<class name>(<human-readable parameters>) constructor removed
<class name>(<human-readable parameters>) constructor parameter <type> removed
@ -72,3 +73,6 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h
`com.intellij.codeInsight.TargetElementUtilBase` class removed
: Use `com.intellij.codeInsight.TargetElementUtil` instead.
`com.intellij.psi.stubs.PrebuiltStubsProviderBase` class now extends `com.intellij.index.PrebuiltIndexProvider` and inherits its abstract method `getIndexRoot()`
: Use `com.intellij.psi.stubs.PlatformPrebuiltStubsProviderBase` instead.

View File

@ -26,6 +26,7 @@ The following problem patterns are supported:
<class name>.<method name>(<human-readable parameters>) method visibility changed from <before> to <after>
<class name>.<method name>(<human-readable parameters>) method marked final
<class name> (class|interface) now (extends|implements) <class name> and inherits its final method <method name>(<human-readable parameters>)?
<class name> (class|interface) now (extends|implements) <class name> and inherits its abstract method <method name>(<human-readable parameters>)?
<class name>(<human-readable parameters>) constructor removed
<class name>(<human-readable parameters>) constructor parameter <type> removed
@ -66,7 +67,7 @@ Compatibility with newer IDEs can easily be verified for plugins hosted on the [
For non-public plugins, [intellij-plugin-verifier](https://github.com/JetBrains/intellij-plugin-verifier) can be used standalone as well.
Consider using the following inspections to get additional alerts in the IDE for code that uses unstable API features:
Consider using the following IDE inspections to get additional alerts about code that uses unstable API features:
- JVM languages \| Unstable API Usage
- JVM languages \| Unstable type is used in signature

View File

@ -70,6 +70,9 @@ public interface ChangeActionNotifier {
![Subscribing](img/subscribe.png)
> **NOTE** If targeting 2019.3 or later, use [declarative registration](/basics/plugin_structure/plugin_listeners.md) if possible.
```java
public void init(MessageBus bus) {
bus.connect().subscribe(ActionTopics.CHANGE_ACTION_TOPIC, new ChangeActionNotifier() {